1
Fork 0

Fix ICE when opaque captures a duplicated/invalid lifetime

This commit is contained in:
Michael Goulet 2025-01-01 16:55:10 +00:00
parent 7f75bfa1ad
commit d3c6067275
8 changed files with 53 additions and 27 deletions

View file

@ -1845,11 +1845,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
GenericParamKind::Lifetime => {
// AST resolution emitted an error on those parameters, so we lower them using
// `ParamName::Error`.
let ident = self.lower_ident(param.ident);
let param_name =
if let Some(LifetimeRes::Error) = self.resolver.get_lifetime_res(param.id) {
ParamName::Error
ParamName::Error(ident)
} else {
let ident = self.lower_ident(param.ident);
ParamName::Plain(ident)
};
let kind =

View file

@ -52,6 +52,13 @@ pub enum ParamName {
/// Some user-given name like `T` or `'x`.
Plain(Ident),
/// Indicates an illegal name was given and an error has been
/// reported (so we should squelch other derived errors).
///
/// Occurs when, e.g., `'_` is used in the wrong place, or a
/// lifetime name is duplicated.
Error(Ident),
/// Synthetic name generated when user elided a lifetime in an impl header.
///
/// E.g., the lifetimes in cases like these:
@ -67,18 +74,13 @@ pub enum ParamName {
/// where `'f` is something like `Fresh(0)`. The indices are
/// unique per impl, but not necessarily continuous.
Fresh,
/// Indicates an illegal name was given and an error has been
/// reported (so we should squelch other derived errors). Occurs
/// when, e.g., `'_` is used in the wrong place.
Error,
}
impl ParamName {
pub fn ident(&self) -> Ident {
match *self {
ParamName::Plain(ident) => ident,
ParamName::Fresh | ParamName::Error => Ident::with_dummy_span(kw::UnderscoreLifetime),
ParamName::Plain(ident) | ParamName::Error(ident) => ident,
ParamName::Fresh => Ident::with_dummy_span(kw::UnderscoreLifetime),
}
}
}

View file

@ -928,8 +928,8 @@ pub fn walk_generic_param<'v, V: Visitor<'v>>(
) -> V::Result {
try_visit!(visitor.visit_id(param.hir_id));
match param.name {
ParamName::Plain(ident) => try_visit!(visitor.visit_ident(ident)),
ParamName::Error | ParamName::Fresh => {}
ParamName::Plain(ident) | ParamName::Error(ident) => try_visit!(visitor.visit_ident(ident)),
ParamName::Fresh => {}
}
match param.kind {
GenericParamKind::Lifetime { .. } => {}

View file

@ -2007,7 +2007,10 @@ fn check_variances_for_type_defn<'tcx>(
}
match hir_param.name {
hir::ParamName::Error => {}
hir::ParamName::Error(_) => {
// Don't report a bivariance error for a lifetime that isn't
// even valid to name.
}
_ => {
let has_explicit_bounds = explicitly_bounded_params.contains(&parameter);
report_bivariance(tcx, hir_param, has_explicit_bounds, item);

View file

@ -1,9 +0,0 @@
//@ known-bug: #132766
trait Trait {}
impl<'a> Trait for () {
fn pass2<'a>() -> impl Trait2 {}
}
trait Trait2 {}
impl Trait2 for () {}

View file

@ -0,0 +1,19 @@
// This uses edition 2024 for new lifetime capture rules.
//@ edition: 2024
// The problem here is that the presence of the opaque which captures all lifetimes in scope
// means that the duplicated `'a` (which I'll call the dupe) is considered to be *early-bound*
// since it shows up in the output but not the inputs. This is paired with the fact that we
// were previously setting the name of the dupe to `'_` in the generic param definition, which
// means that the identity args for the function were `['a#0, '_#1]` even though the lifetime
// for the dupe should've been `'a#1`. This difference in symbol meant that NLL couldn't
// actually match the lifetime against the identity lifetimes, leading to an ICE.
struct Foo<'a>(&'a ());
impl<'a> Foo<'a> {
fn pass<'a>() -> impl Sized {}
//~^ ERROR lifetime name `'a` shadows a lifetime name that is already in scope
}
fn main() {}

View file

@ -0,0 +1,11 @@
error[E0496]: lifetime name `'a` shadows a lifetime name that is already in scope
--> $DIR/captured-invalid-lifetime.rs:15:13
|
LL | impl<'a> Foo<'a> {
| -- first declared here
LL | fn pass<'a>() -> impl Sized {}
| ^^ lifetime `'a` already in scope
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0496`.

View file

@ -146,13 +146,13 @@ hir-stats Variant 144 ( 1.6%) 2 72
hir-stats GenericBound 256 ( 2.9%) 4 64
hir-stats - Trait 256 ( 2.9%) 4
hir-stats Block 288 ( 3.2%) 6 48
hir-stats GenericParam 360 ( 4.0%) 5 72
hir-stats Pat 360 ( 4.0%) 5 72
hir-stats - Struct 72 ( 0.8%) 1
hir-stats - Wild 72 ( 0.8%) 1
hir-stats - Binding 216 ( 2.4%) 3
hir-stats Generics 560 ( 6.3%) 10 56
hir-stats Ty 720 ( 8.1%) 15 48
hir-stats GenericParam 400 ( 4.5%) 5 80
hir-stats Generics 560 ( 6.2%) 10 56
hir-stats Ty 720 ( 8.0%) 15 48
hir-stats - Ptr 48 ( 0.5%) 1
hir-stats - Ref 48 ( 0.5%) 1
hir-stats - Path 624 ( 7.0%) 13
@ -171,8 +171,8 @@ hir-stats - Impl 88 ( 1.0%) 1
hir-stats - Trait 88 ( 1.0%) 1
hir-stats - Fn 176 ( 2.0%) 2
hir-stats - Use 352 ( 3.9%) 4
hir-stats Path 1_240 (13.9%) 31 40
hir-stats PathSegment 1_920 (21.5%) 40 48
hir-stats Path 1_240 (13.8%) 31 40
hir-stats PathSegment 1_920 (21.4%) 40 48
hir-stats ----------------------------------------------------------------
hir-stats Total 8_936 180
hir-stats Total 8_976 180
hir-stats