-
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
use different lifetime name for object-lifetime-default elision #63376
Conversation
6d0f938
to
8e96dd3
Compare
Note to self, as I'm not really at keyboard now: Check what happens with Also check similar scenarios like Arguably, we should create a lifetime parameter for the opaque type that we create, but it should get a value of |
Yeah, I'd also be curious about This fix makes sense to me, but the collection of lifetime-shifting-in-lowering logic is growing increasingly complex and scary. I don't have a particular fix in mind, but spending some time brainstorming could be good. r=me with those tests added and @Centril's nits addressed. |
Yes.
I was reviewing our object lifetime default rules (specified in RFC 599 and then amended in RFC 1156). The latter RFC in particular institutes the rule that we take the default from the "innermost enclosing type", essentially; hence It seems to me that similar logic applies to Your example: -> impl Trait<Item = Box<dyn OtherTrait<impl ThirdTrait>>> would therefore default to: -> impl Trait<Item = Box<dyn OtherTrait<impl ThirdTrait> + 'static>> |
So I added tests for On nightly, this means that I've got a fix that I just pushed but it's not really the right fix. It simply uses Probably the right behavior is to operate analogously an input type parameter. In other words, if you have trait Foo<'a, T: 'a + ?Sized> { .. } and trait Foo<'a> {
type Item: 'a + ?Sized;
} and trait Foo {
type Item: ?Sized;
} then |
432bae1
to
83f0640
Compare
Another, conservative option would be to require explicit bounds in this scenario. But that would be more of a breaking change. |
I've been investigating what it will take to do the more complex handling of object lifetime default bounds that I described above. It would definitely be complex, because at the phase where we are figuring this sort of thing out, we haven't yet resolved the I suppose a conservative option would be to default to |
d0c042d
to
afa4a2a
Compare
I pushed a commit implementing the conservative rule I described above. It's technically a breaking change, as I noted, although I believe the current behavior is pretty clearly a bug. I wouldn't expect a large impact but it's hard to know. The affected case is something like |
@bors try In case we want to try and do a crater run |
use different lifetime name for object-lifetime-default elision Introduce a distinct value for `LifetimeName` to use when this is a object-lifetime-default elision. This allows us to avoid creating incorrect lifetime parameters for the opaque types that result. We really need to overhaul this setup at some point! It's getting increasingly byzantine. But this seems like a relatively... surgical fix. r? @cramertj Fixes #62517
☀️ Try build successful - checks-azure |
@craterbot run mode=check-only |
👌 Experiment ℹ️ Crater is a tool to run experiments across parts of the Rust ecosystem. Learn more |
Dear @rust-lang/lang -- this PR makes a breaking change (bug fix, in my opinion) to the compiler. We are doing a crater run now to see if there are any effects. I wrote up a summary of the situation in a gist, explaining both the background, intended behavior, current behavior, and the effect of this PR. |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
🎉 Experiment
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks great. Thanks also for the write-up.
Regression tree (from root):
Seems reasonably fixable by just sending a PR. |
Hello, according to rust-lang/rust#63376 , the compiler used to accept the current function signature of `drain_extensions()` by mistake, the compiler will soon fix this (after the above PR lands), and after that the current code won't compile. This PR fixes the code. Please note that the latest published version soketto-0.2.2 contains this error too.
Object-lifetime-default elision is distinct from other forms of elision; it always refers to some enclosing lifetime *present in the surrounding type* (e.g., `&dyn Bar` expands to `&'a (dyn Bar + 'a)`. If there is no enclosing lifetime, then it expands to `'static`. Therefore, in an `impl Trait<Item = dyn Bar>` setting, we don't expand to create a lifetime parameter for the `dyn Bar + 'X` bound. It will just be resolved to `'static`. Annoyingly, the responsibility for this resolution is spread across multiple bits of code right now (`middle::resolve_lifetimes`, `lowering`). The lowering code knows that the default is for an object lifetime, but it doesn't know what the correct result would be. Probably this should be fixed, but what we do now is a surgical fix: we have it generate a different result for elided lifetimes in a object context, and then we can ignore those results when figuring out the lifetimes that are captured in the opaque type.
Currently the default is "inherited" from context, so e.g. `&impl Foo<Item = dyn Bar>` would default to `&'x impl Foo<Item = dyn Bar + 'x>`, but this triggers an ICE and is not very consistent. This patch doesn't implement what I expect would be the correct semantics, because those are likely too complex. Instead, it handles what I'd expect to be the common case -- where the trait has no lifetime parameters.
afa4a2a
to
7ee1af5
Compare
@bors r=cramertj |
📌 Commit 7ee1af5 has been approved by |
…7, r=cramertj use different lifetime name for object-lifetime-default elision Introduce a distinct value for `LifetimeName` to use when this is a object-lifetime-default elision. This allows us to avoid creating incorrect lifetime parameters for the opaque types that result. We really need to overhaul this setup at some point! It's getting increasingly byzantine. But this seems like a relatively... surgical fix. r? @cramertj Fixes rust-lang#62517
Rollup of 5 pull requests Successful merges: - #63252 (Remove recommendation about idiomatic syntax for Arc::clone) - #63376 (use different lifetime name for object-lifetime-default elision) - #63620 (Use constraint span when lowering associated types) - #63699 (Fix suggestion from incorrect `move async` to `async move`.) - #63704 ( Fixed: error: unnecessary trailing semicolon) Failed merges: r? @ghost
…amertj Stabilize `async_await` in Rust 1.39.0 Here we stabilize: - free and inherent `async fn`s, - the `<expr>.await` expression form, - and the `async move? { ... }` block form. Closes rust-lang#62149. Closes rust-lang#50547. All the blockers are now closed. <details> - [x] FCP in rust-lang#62149 - [x] rust-lang#61949; PR in rust-lang#62849. - [x] rust-lang#62517; PR in rust-lang#63376. - [x] rust-lang#63225; PR in rust-lang#63501 - [x] rust-lang#63388; PR in rust-lang#63499 - [x] rust-lang#63500; PR in rust-lang#63501 - [x] rust-lang#62121 (comment) - [x] Some tests for control flow (PR rust-lang#63387): - `?` - `return` in `async` blocks - `break` - [x] rust-lang#61775 (comment), i.e. tests for rust-lang#60944 with `async fn`s instead). PR in rust-lang#63383 </details> r? @cramertj
Introduce a distinct value for
LifetimeName
to use when this is a object-lifetime-default elision. This allows us to avoid creating incorrect lifetime parameters for the opaque types that result. We really need to overhaul this setup at some point! It's getting increasingly byzantine. But this seems like a relatively... surgical fix.r? @cramertj
Fixes #62517