Eagerly elaborate auto-trait supertraits into dyn Trait#119825
Eagerly elaborate auto-trait supertraits into dyn Trait#119825compiler-errors wants to merge 3 commits intorust-lang:masterfrom
dyn Trait#119825Conversation
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 Footype is elaborated to includeSendas 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
+ AutoTraitor have it implied from the supertrait bounds. This PR removes this subtle distinction.IMO, It never makes sense for
dyn Footo 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