-
Notifications
You must be signed in to change notification settings - Fork 13.2k
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
Implementations conflict when using associated type across crates #51445
Comments
The names of the types don't have to be the same, and... when the associated type is not public, there is no workaround AFAICT. I ran into this while trying to implement |
I think the issue here is that A possible (but not easy) change in the language would be to mark the associated type as stable under non-breaking changes. The type system can then prove that there will be no conflicing implementation under non-breaking changes and can accept the code. I think the error message this issue generates in unclear. It did cost me a few days to narrow the error down to this issue. A better error message would have helped me here. |
I ran into this, including a completely wrong and unhelpful error, basically where I was I don't see how this isn't a bug. |
Changing a type in your API is already considered a major breaking change, so I don't think that's a factor. I noted a couple dupes; there was a PR that passed review for #85898, but it ran into some CI problems and got dropped. impl<'a> GatLike<'a, String> for Foo {
type Ref = &'a String;
}
impl<'a> GatLike<'a, <String as Deref>::Target> for Foo {
type Ref = &'a <String as Deref>::Target;
} It's quite annoying in a macro context, where now I have to manually supply the normalized types. Search aids: Associated type projection, normalization. While I feel this is a bug that should be fixed, the error is also counter-factual, so |
This commit addressed an issue of implementing trait for associated types, by replacing implementation for associated type with concrete type `pb::Vote`. - Related issues: rust-lang/rust#51445 - The minimized reproduce repo is: https://github.com/drmingdrmer/conflict-trait-in-main Explanation: If one crate `lib.rs` implements a trait(`Default`) for an associated type(`<() as Container>::Item`, which is `Foo`), in another crate `main.rs`, it seems the compiler treats the associated type(`<() as Container>::Item`) as a generic type `T` and assumes `T` would be any type and results in the conflict with a local type that tries to implement `Default`, while actually `Foo` and `Wow` are actually different types. ``` ▾ src/ lib.rs main.rs ``` `lib.rs`: ```rust pub trait Container { type Item; } impl Container for () { type Item = Foo; } pub struct Foo; impl Default for <() as Container>::Item { fn default() -> Self { Foo } } ``` `main.rs`: ```rust // Make main.rs depends on lib.rs use t_conflict::Container as _; struct Wow; impl Default for Wow { fn default() -> Self { Wow } } fn main() {} ```
This commit addressed an issue of implementing trait for associated types, by replacing implementation for associated type with concrete type `pb::Vote`. - Related issues: rust-lang/rust#51445 - The minimized reproduce repo is: https://github.com/drmingdrmer/conflict-trait-in-main Explanation: If one crate `lib.rs` implements a trait(`Default`) for an associated type(`<() as Container>::Item`, which is `Foo`), in another crate `main.rs`, it seems the compiler treats the associated type(`<() as Container>::Item`) as a generic type `T` and assumes `T` would be any type and results in the conflict with a local type that tries to implement `Default`, while actually `Foo` and `Wow` are actually different types. cargo repo: ``` ▾ src/ lib.rs main.rs ``` `lib.rs`: ```rust pub trait Container { type Item; } impl Container for () { type Item = Foo; } pub struct Foo; impl Default for <() as Container>::Item { fn default() -> Self { Foo } } ``` `main.rs`: ```rust // Make main.rs depends on lib.rs use t_conflict::Container as _; struct Wow; impl Default for Wow { fn default() -> Self { Wow } } fn main() {} ``` `cargo build` yield this error: ``` error[E0119]: conflicting implementations of trait `Default` for type `Wow` --> t-conflict/src/main.rs:7:1 | 7 | impl Default for Wow { | ^^^^^^^^^^^^^^^^^^^^ | = note: conflicting implementation in crate `t_conflict`: - impl Default for <() as Container>::Item; ```
crate bar:
crate foo:
Output:
I can only reproduce this issue when using the
<Bar as SomeTrait>::Next
syntax, and only when Bar is in an external crate. Reproduced in current stable and nightly.The text was updated successfully, but these errors were encountered: