-
Notifications
You must be signed in to change notification settings - Fork 12.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Spurious "note: downstream crates may implement trait Foo
for type &_
"
#48869
Comments
may be it is possible to simplify code after resolving rust-lang/rust#48869
may be it is possible to simplify code after resolving rust-lang/rust#48869
may be it is possible to simplify code after resolving rust-lang/rust#48869
Similar problem when using trait Foo {
fn foo(&self) -> u32;
}
trait Bar {
fn bar(&self) -> u32;
}
impl<T: Foo> Bar for Vec<T> {
fn bar(&self) -> u32 {
self.iter().map(|x| x.foo()).sum()
}
}
impl<T: Foo> Bar for Vec<Box<T>> {
fn bar(&self) -> u32 {
self.iter().map(|x| x.foo()).sum()
}
}
This problem is possibly more definitive than the OP's as it is impossible for downstream crates to implement Unlike the assumption I made, however, this problem does not occur with other types in the prelude (like This problem does not occur when using a concrete type instead of the generic type parameter: trait Foo {
fn foo(&self) -> u32;
}
trait Baz : Foo {}
trait Bar {
fn bar(&self) -> u32;
}
impl<T: Foo> Bar for Vec<T> {
fn bar(&self) -> u32 {
self.iter().map(|x| x.foo()).sum()
}
}
impl Bar for Vec<Box<Baz>> {
fn bar(&self) -> u32 {
self.iter().map(|x| x.foo()).sum()
}
} The problem can be (suboptimally) worked around by implementing trait Foo {
fn foo(&self) -> u32;
}
impl<T: Foo> Foo for Box<T> {
fn foo(&self) -> u32 {
self.as_ref().foo()
}
}
trait Bar {
fn bar(&self) -> u32;
}
impl<T: Foo> Bar for Vec<T> {
fn bar(&self) -> u32 {
self.iter().map(|x| x.foo()).sum()
}
} |
@eviltak As described in RFC 1023, fundamental structs like struct A;
impl std::ops::Add for Box<A> {
type Output = Box<A>;
fn add(self, rhs: Box<A>) -> Self::Output {
Box::new(A)
}
} |
@qnighy but Seems to be the same problem as issue #50238 |
Any updates fam? |
Given that there seem to be no updates, does anybody have a workaround for this issue yet? |
I just had a similar case, only there was no note about downstream crates. This was in some ways even more confusing, as
I tried to reproduce this in the playground but my reduced version did have the note about downstream crates, which led me here. Perhaps because the original involved separate crates, not just separate modules. I didn't find a different bug for this error message when there is no spurious note, but I'm wondering if there is one... or if anyone is interested enough that I should try harder to reproduce the situation and open one. (And incidentally, my work around was to macro up some impls for concrete types to replace the generic impl.) |
Reduced version which still fails ( trait Foo {}
trait Bar {}
impl<'a, T: Bar> Bar for &'a T {}
impl<T: Foo> Bar for T {} From what I understand, downstream may do this: struct S;
impl Foo for &'static S {}
impl Bar for S {} ... and now we have conflicting impls of But it does seem like the coherence rule here is too strong, since it would be sufficient to prevent the downstream crate from creating both those impls. |
This is then essentially the same restriction as #22865: a library may not provide impls which the user could cause to impl. But note that this restriction is not applied uniformly; for example, the following is allowed: pub trait Foo {}
impl<T> Foo for T {} In the latter case, we simply prevent conflicting implementations downstream (e.g. |
Are there any updates? |
The following code:
produces the following compiler output:
While there might be legitimate reasons why this is not allowed, the note is wrong: the trait
Foo
is not public, a downstream can't possibly implement it for some type.The text was updated successfully, but these errors were encountered: