Spurious "note: downstream crates may implement trait Foo for type &_"
The following code:
trait Foo {}
impl<T: Foo> std::fmt::Display for T {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
Ok(())
}
}
produces the following compiler output:
error[E0119]: conflicting implementations of trait `std::fmt::Display` for type `&_`:
--> src/main.rs:3:1
|
3 | impl<T: Foo> std::fmt::Display for T {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: conflicting implementation in crate `core`:
- impl<'a, T> std::fmt::Display for &'a T
where T: std::fmt::Display, T: ?Sized;
= note: downstream crates may implement trait `Foo` for type `&_`
error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g. `MyStruct<T>`); only traits defined in the current crate can be implemented for a type parameter
--> src/main.rs:3:1
|
3 | / impl<T: Foo> std::fmt::Display for T {
4 | | fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
5 | | Ok(())
6 | | }
7 | | }
| |_^
error: aborting due to 2 previous errors
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.
Similar problem when using
Box: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() } }error[E0119]: conflicting implementations of trait `Bar` for type `std::vec::Vec<std::boxed::Box<_>>`: --> src/main.rs:19:1 | 13 | impl<T: Foo> Bar for Vec<T> { | --------------------------- first implementation here ... 19 | impl<T: Foo> Bar for Vec<Box<T>> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `std::vec::Vec<std::boxed::Box<_>>` | = note: downstream crates may implement trait `Foo` for type `std::boxed::Box<_>` error: aborting due to previous errorThis problem is possibly more definitive than the OP's as it is impossible for downstream crates to implement
Foo(public or not) forBox, since neither the trait (Foo) nor the struct (Box) belong to the downstream crate.Unlike the assumption I made, however, this problem does not occur with other types in the prelude (like
Option).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
FooforBox<T> where T : Fooprovided the usages of the boxed and non-boxed versions of the trait objects are the same, like in my example: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() } }Arav Singhal at 2018-05-24 06:58:19
@eviltak As described in RFC 1023, fundamental structs like
Box<_>are treated transparently by the coherence rules. Therefore you can actually implement an upstream trait forBox.struct A; impl std::ops::Add for Box<A> { type Output = Box<A>; fn add(self, rhs: Box<A>) -> Self::Output { Box::new(A) } }Masaki Hara at 2018-05-24 09:20:32
@qnighy but
std::ops::Addis public while neitherFoonorBarareSeems to be the same problem as issue #50238
Philipp Korber at 2018-05-24 17:34:23
I wasn't aware of that, @qnighy. Thanks for that useful snippet of information!
Thank you for pointing me to #50238, @dathinab! #50238 should be the issue to follow for my problem.
Arav Singhal at 2018-05-24 18:03:10
Any updates fam?
Thomas Braun at 2019-07-16 17:45:14
Given that there seem to be no updates, does anybody have a workaround for this issue yet?
msrd0 at 2020-03-30 20:28:21
I just had a similar case, only there was no note about downstream crates. This was in some ways even more confusing, as
- The error said my generic
impl<T> TraitAresulting in a conflictingimpl TraitB, but - Replacing the
impl<T> TraitAwith a direct non-genericimpl TraitBcompiled meaning - There was no (existing) conflict and the error was stating a non-fact
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.)
jeekobu at 2020-04-23 16:45:48
- The error said my generic
Reduced version which still fails (
BarreplacesDisplay):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
Bar for &'static S.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.
Diggory Hardy at 2020-12-22 14:06:49
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.
struct S; impl From<S> for S {}).Diggory Hardy at 2020-12-22 14:22:36
Are there any updates?
Alex Andreba at 2022-07-29 18:37:06