-
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
[WIP] Fix compiler regression from 1.64.0 relating to &(dyn Trait + '_)
params
#104272
Conversation
Feel free, though I am not super familiar, it's definitely something I can dig into. |
This comment has been minimized.
This comment has been minimized.
debug_assert_eq!(lifetime.ident.name, kw::UnderscoreLifetime); | ||
debug_assert!(self.diagnostic_metadata.current_trait_object.is_some()); | ||
|
||
if self.in_func_params { |
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 is likely to be incorrect in some corner cases. Could you:
- iterate on
self.lifetime_ribs
likeresolve_anonymous_lifetime
does, - check
LifetimeRibKind::Fresh
?
Is the behaviour restricted to function parameters, or anywhere we have a Fresh
rib?
What should impl &(dyn Trait + '_) { /**/ }
mean?
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.
impl &(dyn Trait + '_) { ... }
isn't allowed:
error[E0390]: cannot define inherent `impl` for primitive types
--> /Users/ben/Documents/Rust/rust-lang/rust/src/test/ui/lifetimes/issue-103762-1.rs:42:6
|
LL | impl &(dyn Trait + '_) {
| ^^^^^^^^^^^^^^^^^
|
= help: consider using an extension trait instead
= note: you could also try moving the reference to uses of `dyn Trait` (such as `self`) within the implementation
I can believe that this way of doing it is brittle. Can you try to think of any more edge cases? I'm fresh out of ideas at the moment.
I'll try out your strategy of checking for the presence of the rib. Though I think you probably meant LifetimeRibKind::AnonymousCreateParameter
rather than LifetimeRibKind::Fresh
?
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.
impl Trait for &(dyn Trait2 + '_) {}
is allowed.
If you want corner cases:
fn foo(_: fn(&(dyn Trait + '_)) -> &(dyn Trait + '_)) {}
fn bar(_: [u8; { { fn blah() -> &(dyn Trait + '_) {} }; 5 }]) {}
I'll try out your strategy of checking for the presence of the rib. Though I think you probably meant LifetimeRibKind::AnonymousCreateParameter rather than LifetimeRibKind::Fresh?
Exactly.
compiler/rustc_resolve/src/late.rs
Outdated
debug_assert!(self.diagnostic_metadata.current_trait_object.is_some()); | ||
|
||
if self.in_func_params { | ||
self.with_lifetime_rib(LifetimeRibKind::Elided(LifetimeRes::Infer), |this| { |
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.
The resolution is not Infer
. In HIR, we should get an ImplicitObjectLifetimeDefault
, but I did not create such variant in LifetimeRes
. Could you create an extra ImplicitObjectLifetimeDefault
variant in LifetimeRes
and adapt lowering to translate it to LifetimeName::ImplicitObjectLifetimeDefault
?
Infer
means that type-checking will try to find the correct lifetime through type-inference. This is typically what appears in function bodies. ImplicitObjectLifetimeDefault
means that we will inspect the surrounding type to apply the object lifetime rules: &'a (dyn Trait + '_)
implicitly becomes &'a (dyn Trait + 'a)
etc.
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.
Thank you for the pointer!
This does indeed get us past any errors in resolve and astconv, and all the tests I wrote compile as I had intended.
However, it seems ImplicitObjectLifetimeDefault
results in the wrong lifetime for Box<dyn Trait + '_>
, as this failed test shows:
// check-pass
struct Ctxt {
v: usize,
}
trait GetCtxt {
// Here the `&` is bound in the method definition:
fn get_ctxt(&self) -> &Ctxt;
}
struct HasCtxt<'a> {
c: &'a Ctxt,
}
impl<'a> GetCtxt for HasCtxt<'a> {
// Ok: Have implied bound of WF(&'b HasCtxt<'a>)
// so know 'a: 'b
// so know &'a Ctxt <: &'b Ctxt
fn get_ctxt<'b>(&'b self) -> &'a Ctxt {
self.c
}
}
fn get_v(gc: Box<dyn GetCtxt + '_>) -> usize {
gc.get_ctxt().v
}
fn main() {
let ctxt = Ctxt { v: 22 };
let hc = HasCtxt { c: &ctxt };
assert_eq!(get_v(Box::new(hc) as Box<dyn GetCtxt>), 22);
}
---- [ui] src/test/ui/regions/regions-trait-1.rs stdout ----
error: test compilation failed although it shouldn't!
status: exit status: 1
command: "/Users/ben/Documents/Rust/rust-lang/rust/build/aarch64-apple-darwin/stage1/bin/rustc" "/Users/ben/Documents/Rust/rust-lang/rust/src/test/ui/regions/regions-trait-1.rs" "-Zthreads=1" "--target=aarch64-apple-darwin" "--error-format" "json" "--json" "future-incompat" "-Ccodegen-units=1" "-Zui-testing" "-Zdeduplicate-diagnostics=no" "-Cstrip=debuginfo" "--emit" "metadata" "-C" "prefer-dynamic" "--out-dir" "/Users/ben/Documents/Rust/rust-lang/rust/build/aarch64-apple-darwin/test/ui/regions/regions-trait-1" "-A" "unused" "-Crpath" "-Cdebuginfo=0" "-Lnative=/Users/ben/Documents/Rust/rust-lang/rust/build/aarch64-apple-darwin/native/rust-test-helpers" "-L" "/Users/ben/Documents/Rust/rust-lang/rust/build/aarch64-apple-darwin/test/ui/regions/regions-trait-1/auxiliary"
stdout: none
--- stderr -------------------------------
error[E0597]: `ctxt` does not live long enough
--> /Users/ben/Documents/Rust/rust-lang/rust/src/test/ui/regions/regions-trait-1.rs:31:27
|
LL | let hc = HasCtxt { c: &ctxt };
| ^^^^^ borrowed value does not live long enough
LL | assert_eq!(get_v(Box::new(hc) as Box<dyn GetCtxt>), 22);
| ------------ cast requires that `ctxt` is borrowed for `'static`
LL | }
| - `ctxt` dropped here while still borrowed
error: aborting due to previous error
For more information about this error, try `rustc --explain E0597`.
------------------------------------------
So, I'm not sure where to go from there.
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 is the more concerning bit. Please advise when you can.
…'_` in trait objects.
@BGR360 I realise that I led you in a completely wrong direction. I'm sorry. The fix is actually much simpler than all this: ignore the lifetime from the trait object when looking for elision candidates. rust/compiler/rustc_resolve/src/late/lifetimes.rs Lines 2857 to 2861 in b276b65
The easiest way to do that is to thread a |
☔ The latest upstream changes (presumably #106193) made this pull request unmergeable. Please resolve the merge conflicts. |
Closing this PR as inactive. Feel free to open a new pr if you wish to continue working on this. |
This is my attempt to fix #103762. It doesn't fully work. I'd like some input on what to try next.
What I did was special-case the treatment of anonymous lifetime bounds (
+ '_
) in trait object types when they are encountered inside a function's parameters. I simply resolved them toLifetimeRes::Infer
to try to let typeck figure them out.This does successfully get around the error that the OP of #103762 encountered, and goes through to astconv.
However, now it fails in astconv with the following error:
And I discovered an existing test case which shows that
(_: Box<dyn Trait + '_>)
was previously accepted, which I found interesting. It now fails with the same error though:I don't know for sure what this means, but it sounds like I'm sorta between a rock and a hard place. I think astconv probably wants
Fresh
lifetimes for these anonymous bounds, butresolve_fn_signature
does not want that. Does there perhaps want to be aLifetimeRes::FreshIfNoOtherFresh
?I'm definitely in over my head a bit here. I've learned quite a bit about rustc_resolve in trying to do this, but the amount of time it would take me alone to learn enough about it to figure out where to go next is too much. I think I really need some direction from somebody who's familiar with this.
r? @cjgillot since it seems you've been the one doing most of the work to do more lifetime checking in rustc_resolve.
But if they're busy, then @compiler-errors is this an area of rustc I could pick your brain about at your office hours?