-
Notifications
You must be signed in to change notification settings - Fork 12.9k
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
Eagerly elaborate auto-trait supertraits into dyn Trait
#119825
Conversation
468280f
to
caeda85
Compare
Some changes occurred to the core trait solver cc @rust-lang/initiative-trait-system-refactor |
@bors try |
Eagerly elaborate auto-trait supertraits into `dyn Trait` When we have a trait like: ``` trait Foo: Send {} ``` Then the `dyn Foo` type is elaborated to include `Send` as part of its auto-traits list. That means it is the *same* type as `dyn Foo + Send`. ## Why? When a auto trait is implied as part of the supertraits of the trait object's principal, the user should *never* care about whether they explicitly write `+ AutoTrait` or have it implied from the supertrait bounds. This PR removes this subtle distinction. IMO, It *never* makes sense for `dyn Foo` to be a distinct type from `dyn Foo + Send`, since both implement `Send`, just via different code paths in the trait solver. --- Alternative approach to rust-lang#119338. r? lcnr
@bors try |
Eagerly elaborate auto-trait supertraits into `dyn Trait` When we have a trait like: ``` trait Foo: Send {} ``` Then the `dyn Foo` type is elaborated to include `Send` as part of its auto-traits list. That means it is the *same* type as `dyn Foo + Send`. ## Why? When a auto trait is implied as part of the supertraits of the trait object's principal, the user should *never* care about whether they explicitly write `+ AutoTrait` or have it implied from the supertrait bounds. This PR removes this subtle distinction. IMO, It *never* makes sense for `dyn Foo` to be a distinct type from `dyn Foo + Send`, since both implement `Send`, just via different code paths in the trait solver. --- Alternative approach to rust-lang#119338. r? lcnr
☀️ Try build successful - checks-actions |
@craterbot check |
👌 Experiment ℹ️ Crater is a tool to run experiments across parts of the Rust ecosystem. Learn more |
🚧 Experiment ℹ️ Crater is a tool to run experiments across parts of the Rust ecosystem. Learn more |
🎉 Experiment
|
alright :/ seems like that's not possible, let go with the coercion 😅 |
yeet |
…=lcnr Consider principal trait ref's auto-trait super-traits in dyn upcasting Given traits like: ```rust trait Subtrait: Supertrait + Send {} trait Supertrait {} ``` We should be able to upcast `dyn Subtrait` to `dyn Supertrait + Send`. This is not currently possible, because when upcasting, we look at the list of auto traits in the object type (`dyn Subtrait`, which has no auto traits in its bounds) and compare them to the target's auto traits (`dyn Supertrait + Send`, which has `Send` in its bound). Since the target has auto traits that are not present in the source, the upcasting fails. This is overly restrictive, since `dyn Subtrait` will always implement `Send` via its built-in object impl. I propose to loosen this restriction here. r? types --- ### ~~Aside: Fix this in astconv instead?~~ ### edit: This causes too many failures. See rust-lang#119825 (comment) We may also fix this by by automatically elaborating all auto-trait supertraits during `AstConv::conv_object_ty_poly_trait_ref`. That is, we can make it so that `dyn Subtrait` is elaborated into the same type of `dyn Subtrait + Send`. I'm open to considering this solution instead, but it would break coherence in the following example: ```rust trait Foo: Send {} trait Bar {} impl Bar for dyn Foo {} impl Bar for dyn Foo + Send {} //~^ This would begin to be an overlapping impl. ```
Consider principal trait ref's auto-trait super-traits in dyn upcasting Given traits like: ```rust trait Subtrait: Supertrait + Send {} trait Supertrait {} ``` We should be able to upcast `dyn Subtrait` to `dyn Supertrait + Send`. This is not currently possible, because when upcasting, we look at the list of auto traits in the object type (`dyn Subtrait`, which has no auto traits in its bounds) and compare them to the target's auto traits (`dyn Supertrait + Send`, which has `Send` in its bound). Since the target has auto traits that are not present in the source, the upcasting fails. This is overly restrictive, since `dyn Subtrait` will always implement `Send` via its built-in object impl. I propose to loosen this restriction here. r? types --- ### ~~Aside: Fix this in astconv instead?~~ ### edit: This causes too many failures. See rust-lang/rust#119825 (comment) We may also fix this by by automatically elaborating all auto-trait supertraits during `AstConv::conv_object_ty_poly_trait_ref`. That is, we can make it so that `dyn Subtrait` is elaborated into the same type of `dyn Subtrait + Send`. I'm open to considering this solution instead, but it would break coherence in the following example: ```rust trait Foo: Send {} trait Bar {} impl Bar for dyn Foo {} impl Bar for dyn Foo + Send {} //~^ This would begin to be an overlapping impl. ```
Consider principal trait ref's auto-trait super-traits in dyn upcasting Given traits like: ```rust trait Subtrait: Supertrait + Send {} trait Supertrait {} ``` We should be able to upcast `dyn Subtrait` to `dyn Supertrait + Send`. This is not currently possible, because when upcasting, we look at the list of auto traits in the object type (`dyn Subtrait`, which has no auto traits in its bounds) and compare them to the target's auto traits (`dyn Supertrait + Send`, which has `Send` in its bound). Since the target has auto traits that are not present in the source, the upcasting fails. This is overly restrictive, since `dyn Subtrait` will always implement `Send` via its built-in object impl. I propose to loosen this restriction here. r? types --- ### ~~Aside: Fix this in astconv instead?~~ ### edit: This causes too many failures. See rust-lang/rust#119825 (comment) We may also fix this by by automatically elaborating all auto-trait supertraits during `AstConv::conv_object_ty_poly_trait_ref`. That is, we can make it so that `dyn Subtrait` is elaborated into the same type of `dyn Subtrait + Send`. I'm open to considering this solution instead, but it would break coherence in the following example: ```rust trait Foo: Send {} trait Bar {} impl Bar for dyn Foo {} impl Bar for dyn Foo + Send {} //~^ This would begin to be an overlapping impl. ```
When we have a trait like:
Then the
dyn Foo
type is elaborated to includeSend
as part of its auto-traits list. That means it is the same type asdyn Foo + Send
.Why?
When a auto trait is implied as part of the supertraits of the trait object's principal, the user should never care about whether they explicitly write
+ AutoTrait
or have it implied from the supertrait bounds. This PR removes this subtle distinction.IMO, It never makes sense for
dyn Foo
to be a distinct type fromdyn Foo + Send
, since both implementSend
, just via different code paths in the trait solver.Alternative approach to #119338.
r? lcnr