-
Notifications
You must be signed in to change notification settings - Fork 13.3k
Oddity with lifetime elision and type aliases #140611
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
Comments
It does, but it also does not capture this oddity I think: https://github.com/rust-lang/fls/blob/main/src/types-and-traits.rst#lifetime-elision |
Interestingly, rust-analyzer, when configured to show inlay lifetime hints, gets That is, it annotates it like this: impl<'a> Alias<'a> {
fn f1<'x>(self: &W<'a>, x: &'x ()) -> &'x () { x } //~ `'_ == 'x`, what?
fn f2<'x>(self: &Alias<'a>, x: &'x ()) -> &'x () { x } //~ `'_ == 'x`, what?
fn f3<'0, 'x>(&self, _: &'x ()) -> &'0 () { self.0 } //~ OK.
}
impl<'a> W<'a> {
fn f4<'x>(self: &W<'a>, _: &'x ()) -> &'x () { self.0 } //~ Wrong r-a annotation.
fn f5<'x>(self: &Alias<'a>, x: &'x ()) -> &'x () { x } //~ `'_ == 'x`, what?
fn f6<'0, 'x>(&self, _: &'x ()) -> &'0 () { self.0 } //~ OK.
} |
Those inlay hints are entirely syntactically based and known to be wrong in some scenarios (r-a has not implemented semantic lifetime elision yet) |
We discussed this in today's @rust-lang/lang meeting. This seems emphatically like a bug. We should try to fix it, and do a crater run to see if fixing it breaks anything. |
This is two bugs: (1.) Lifetime elision special-casing for
|
Res::Def(DefKind::Struct | DefKind::Union | DefKind::Enum, _,) | Res::PrimTy(_) |
That is to say, we don't prefer the lifetime in self: &Alias
even if we're in some impl Alias
because we only prefer structs/unions/enums in this hack.
(2.) Lifetime elision special-casing does not look through type aliases
We prefer the lifetime in self: &Struct
only in impl Struct
, only considering syntactical equality between the impl self type and the type inside the reference.
rust/compiler/rustc_resolve/src/late.rs
Lines 2467 to 2473 in 2a5da7a
TyKind::Path(None, _) => { | |
let path_res = self.r.partial_res_map[&ty.id].full_res(); | |
if let Some(Res::SelfTyParam { .. } | Res::SelfTyAlias { .. }) = path_res { | |
return true; | |
} | |
self.impl_self.is_some() && path_res == self.impl_self | |
} |
I believe (1.) could be easily tweaked to also consider aliases. That would fix:
pub struct W<'a>(&'a ());
pub type Alias<'a> = W<'a>;
impl<'a> Alias<'a> {
fn f2<'x>(self: &Alias<'a>, x: &'x ()) -> &() { self.0 }
}
I don't believe (2.) could be fixed to look through aliases, though, since this lifetime elision happens pretty early in the compiler, and I'm not sure we have the information to look through type aliases yet.
I'm kinda unsure why we even support this partial "is self type" behavior. It's pretty inconsistent, i.e. we prefer the self lifetime if the self type matches the struct of the only shallowly i.e. W<i32>
would match W<()>
and prefer its lifetime in self: &W<i32>
.
I think it would've only been nice to support lifetimes when users write self: &Self
and not self: &Struct
(when the impl self is Struct
).
I didn't look for much justification in the following PRs, but maybe someone had thoughts there:
Thanks for those details and that analysis. In looking through #61207, I see there is this write-up by @nikomatsakis trying to document the then-current behavior: https://gist.github.com/nikomatsakis/5996e4f58899ef5c6926948b6f76835e |
In reviewing a test case for,
mismatched-lifetime-syntaxes
lint #138677I was led to the following oddity:
Playground link
This was noticed long ago in #60944 (comment), which is presumably when the test case was added, but I can't immediately find later discussion.
The Reference doesn't document this behavior.
(The FLS, as best I can tell on a skim, does not document lifetime elision at all.)If there's a good reason for this as the correct behavior, we should probably write this down in the Reference. Otherwise, I'm going to propose we agree to try to do away with this somehow, if possible, maybe over an edition.
@rustbot labels +C-discussion +T-lang +I-lang-nominated +A-lifetimes
cc @rust-lang/lang @ehuss
The text was updated successfully, but these errors were encountered: