Replace LifetimeRes::Anonymous by LifetimeRes::Infer.

This commit is contained in:
Camille GILLOT 2022-06-13 08:22:06 +02:00
parent ab63591f00
commit 10be0dd8df
9 changed files with 51 additions and 105 deletions

View File

@ -1883,25 +1883,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
} }
hir::LifetimeName::Param(param, ParamName::Fresh) hir::LifetimeName::Param(param, ParamName::Fresh)
} }
LifetimeRes::Anonymous { binder } => { LifetimeRes::Infer => hir::LifetimeName::Infer,
let mut l_name = None;
if let Some(mut captured_lifetimes) = self.captured_lifetimes.take() {
if !captured_lifetimes.binders_to_ignore.contains(&binder) {
let p_id = self.next_node_id();
let p_def_id = self.create_def(
captured_lifetimes.parent_def_id,
p_id,
DefPathData::LifetimeNs(kw::UnderscoreLifetime),
);
captured_lifetimes
.captures
.insert(p_def_id, (span, p_id, ParamName::Fresh, res));
l_name = Some(hir::LifetimeName::Param(p_def_id, ParamName::Fresh));
}
self.captured_lifetimes = Some(captured_lifetimes);
};
l_name.unwrap_or(hir::LifetimeName::Underscore)
}
LifetimeRes::Static => hir::LifetimeName::Static, LifetimeRes::Static => hir::LifetimeName::Static,
LifetimeRes::Error => hir::LifetimeName::Error, LifetimeRes::Error => hir::LifetimeName::Error,
res => panic!("Unexpected lifetime resolution {:?} for {:?} at {:?}", res, ident, span), res => panic!("Unexpected lifetime resolution {:?} for {:?} at {:?}", res, ident, span),

View File

@ -589,7 +589,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
hir::LifetimeName::Param(_, hir::ParamName::Fresh) hir::LifetimeName::Param(_, hir::ParamName::Fresh)
| hir::LifetimeName::ImplicitObjectLifetimeDefault | hir::LifetimeName::ImplicitObjectLifetimeDefault
| hir::LifetimeName::Underscore => { | hir::LifetimeName::Infer => {
// In this case, the user left off the lifetime; so // In this case, the user left off the lifetime; so
// they wrote something like: // they wrote something like:
// //

View File

@ -738,11 +738,8 @@ pub enum LifetimeRes {
binder: NodeId, binder: NodeId,
}, },
/// This variant is used for anonymous lifetimes that we did not resolve during /// This variant is used for anonymous lifetimes that we did not resolve during
/// late resolution. Shifting the work to the HIR lifetime resolver. /// late resolution. Those lifetimes will be inferred by typechecking.
Anonymous { Infer,
/// Id of the introducing place. See `Param`.
binder: NodeId,
},
/// Explicit `'static` lifetime. /// Explicit `'static` lifetime.
Static, Static,
/// Resolution failure. /// Resolution failure.

View File

@ -108,7 +108,8 @@ pub enum LifetimeName {
Error, Error,
/// User wrote an anonymous lifetime, either `'_` or nothing. /// User wrote an anonymous lifetime, either `'_` or nothing.
Underscore, /// The semantics of this lifetime should be inferred by typechecking code.
Infer,
/// User wrote `'static`. /// User wrote `'static`.
Static, Static,
@ -118,7 +119,7 @@ impl LifetimeName {
pub fn ident(&self) -> Ident { pub fn ident(&self) -> Ident {
match *self { match *self {
LifetimeName::ImplicitObjectLifetimeDefault | LifetimeName::Error => Ident::empty(), LifetimeName::ImplicitObjectLifetimeDefault | LifetimeName::Error => Ident::empty(),
LifetimeName::Underscore => Ident::with_dummy_span(kw::UnderscoreLifetime), LifetimeName::Infer => Ident::with_dummy_span(kw::UnderscoreLifetime),
LifetimeName::Static => Ident::with_dummy_span(kw::StaticLifetime), LifetimeName::Static => Ident::with_dummy_span(kw::StaticLifetime),
LifetimeName::Param(_, param_name) => param_name.ident(), LifetimeName::Param(_, param_name) => param_name.ident(),
} }
@ -127,7 +128,7 @@ impl LifetimeName {
pub fn is_anonymous(&self) -> bool { pub fn is_anonymous(&self) -> bool {
match *self { match *self {
LifetimeName::ImplicitObjectLifetimeDefault LifetimeName::ImplicitObjectLifetimeDefault
| LifetimeName::Underscore | LifetimeName::Infer
| LifetimeName::Param(_, ParamName::Fresh) | LifetimeName::Param(_, ParamName::Fresh)
| LifetimeName::Error => true, | LifetimeName::Error => true,
LifetimeName::Static | LifetimeName::Param(..) => false, LifetimeName::Static | LifetimeName::Param(..) => false,
@ -136,7 +137,7 @@ impl LifetimeName {
pub fn is_elided(&self) -> bool { pub fn is_elided(&self) -> bool {
match self { match self {
LifetimeName::ImplicitObjectLifetimeDefault | LifetimeName::Underscore => true, LifetimeName::ImplicitObjectLifetimeDefault | LifetimeName::Infer => true,
// It might seem surprising that `Fresh` counts as // It might seem surprising that `Fresh` counts as
// *not* elided -- but this is because, as far as the code // *not* elided -- but this is because, as far as the code

View File

@ -497,7 +497,7 @@ pub fn walk_lifetime<'v, V: Visitor<'v>>(visitor: &mut V, lifetime: &'v Lifetime
| LifetimeName::Static | LifetimeName::Static
| LifetimeName::Error | LifetimeName::Error
| LifetimeName::ImplicitObjectLifetimeDefault | LifetimeName::ImplicitObjectLifetimeDefault
| LifetimeName::Underscore => {} | LifetimeName::Infer => {}
} }
} }

View File

@ -865,7 +865,7 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
let previous_state = replace(&mut this.in_func_body, true); let previous_state = replace(&mut this.in_func_body, true);
// Resolve the function body, potentially inside the body of an async closure // Resolve the function body, potentially inside the body of an async closure
this.with_lifetime_rib( this.with_lifetime_rib(
LifetimeRibKind::Elided(LifetimeRes::Anonymous { binder: fn_id }), LifetimeRibKind::Elided(LifetimeRes::Infer),
|this| this.visit_block(body), |this| this.visit_block(body),
); );
@ -893,9 +893,7 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
this.with_lifetime_rib( this.with_lifetime_rib(
match binder { match binder {
ClosureBinder::NotPresent => { ClosureBinder::NotPresent => {
LifetimeRibKind::Elided(LifetimeRes::Anonymous { LifetimeRibKind::Elided(LifetimeRes::Infer)
binder: fn_id,
})
} }
ClosureBinder::For { .. } => LifetimeRibKind::AnonymousReportError, ClosureBinder::For { .. } => LifetimeRibKind::AnonymousReportError,
}, },
@ -907,7 +905,7 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
let previous_state = replace(&mut this.in_func_body, true); let previous_state = replace(&mut this.in_func_body, true);
// Resolve the function body, potentially inside the body of an async closure // Resolve the function body, potentially inside the body of an async closure
this.with_lifetime_rib( this.with_lifetime_rib(
LifetimeRibKind::Elided(LifetimeRes::Anonymous { binder: fn_id }), LifetimeRibKind::Elided(LifetimeRes::Infer),
|this| this.visit_expr(body), |this| this.visit_expr(body),
); );
@ -1645,35 +1643,12 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
if !missing { if !missing {
// Do not create a parameter for patterns and expressions. // Do not create a parameter for patterns and expressions.
for rib in self.lifetime_ribs.iter().rev() { for id in node_ids {
match rib.kind { self.record_lifetime_res(
LifetimeRibKind::Elided(res @ LifetimeRes::Anonymous { .. }) => { id,
for id in node_ids { LifetimeRes::Infer,
self.record_lifetime_res(id, res, LifetimeElisionCandidate::Named); LifetimeElisionCandidate::Named,
} );
break;
}
// `LifetimeRes::Error`, which would usually be used in the case of
// `ReportError`, is unsuitable here, as we don't emit an error yet. Instead,
// we simply resolve to an implicit lifetime, which will be checked later, at
// which point a suitable error will be emitted.
LifetimeRibKind::AnonymousReportError | LifetimeRibKind::Item => {
// FIXME(cjgillot) This resolution is wrong, but this does not matter
// since these cases are erroneous anyway. Lifetime resolution should
// emit a "missing lifetime specifier" diagnostic.
let res = LifetimeRes::Anonymous { binder: DUMMY_NODE_ID };
for id in node_ids {
self.record_lifetime_res(id, res, LifetimeElisionCandidate::Named);
}
break;
}
LifetimeRibKind::AnonymousCreateParameter { .. }
| LifetimeRibKind::Elided(_)
| LifetimeRibKind::ElisionFailure
| LifetimeRibKind::Generics { .. }
| LifetimeRibKind::ConstGeneric
| LifetimeRibKind::AnonConst => {}
}
} }
continue; continue;
} }
@ -1814,15 +1789,12 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
) )
} }
match res { match res {
LifetimeRes::Param { .. } LifetimeRes::Param { .. } | LifetimeRes::Fresh { .. } | LifetimeRes::Static => {
| LifetimeRes::Fresh { .. }
| LifetimeRes::Anonymous { .. }
| LifetimeRes::Static => {
if let Some(ref mut candidates) = self.lifetime_elision_candidates { if let Some(ref mut candidates) = self.lifetime_elision_candidates {
candidates.insert(res, candidate); candidates.insert(res, candidate);
} }
} }
LifetimeRes::Error | LifetimeRes::ElidedAnchor { .. } => {} LifetimeRes::Infer | LifetimeRes::Error | LifetimeRes::ElidedAnchor { .. } => {}
} }
} }
@ -2245,26 +2217,23 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
this.with_lifetime_rib(LifetimeRibKind::Elided(LifetimeRes::Static), |this| { this.with_lifetime_rib(LifetimeRibKind::Elided(LifetimeRes::Static), |this| {
this.visit_ty(ty); this.visit_ty(ty);
}); });
this.with_lifetime_rib( this.with_lifetime_rib(LifetimeRibKind::Elided(LifetimeRes::Infer), |this| {
LifetimeRibKind::Elided(LifetimeRes::Anonymous { binder: item.id }), if let Some(expr) = expr {
|this| { let constant_item_kind = match item.kind {
if let Some(expr) = expr { ItemKind::Const(..) => ConstantItemKind::Const,
let constant_item_kind = match item.kind { ItemKind::Static(..) => ConstantItemKind::Static,
ItemKind::Const(..) => ConstantItemKind::Const, _ => unreachable!(),
ItemKind::Static(..) => ConstantItemKind::Static, };
_ => unreachable!(), // We already forbid generic params because of the above item rib,
}; // so it doesn't matter whether this is a trivial constant.
// We already forbid generic params because of the above item rib, this.with_constant_rib(
// so it doesn't matter whether this is a trivial constant. IsRepeatExpr::No,
this.with_constant_rib( HasGenericParams::Yes,
IsRepeatExpr::No, Some((item.ident, constant_item_kind)),
HasGenericParams::Yes, |this| this.visit_expr(expr),
Some((item.ident, constant_item_kind)), );
|this| this.visit_expr(expr), }
); });
}
},
);
}); });
} }
@ -2521,7 +2490,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
// Type parameters can already be used and as associated consts are // Type parameters can already be used and as associated consts are
// not used as part of the type system, this is far less surprising. // not used as part of the type system, this is far less surprising.
self.with_lifetime_rib( self.with_lifetime_rib(
LifetimeRibKind::Elided(LifetimeRes::Anonymous { binder: item.id }), LifetimeRibKind::Elided(LifetimeRes::Infer),
|this| { |this| {
this.with_constant_rib( this.with_constant_rib(
IsRepeatExpr::No, IsRepeatExpr::No,
@ -2694,17 +2663,14 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
// //
// Type parameters can already be used and as associated consts are // Type parameters can already be used and as associated consts are
// not used as part of the type system, this is far less surprising. // not used as part of the type system, this is far less surprising.
self.with_lifetime_rib( self.with_lifetime_rib(LifetimeRibKind::Elided(LifetimeRes::Infer), |this| {
LifetimeRibKind::Elided(LifetimeRes::Anonymous { binder: item.id }), this.with_constant_rib(
|this| { IsRepeatExpr::No,
this.with_constant_rib( HasGenericParams::Yes,
IsRepeatExpr::No, None,
HasGenericParams::Yes, |this| this.visit_expr(expr),
None, )
|this| this.visit_expr(expr), });
)
},
);
} }
} }
AssocItemKind::Fn(box Fn { generics, .. }) => { AssocItemKind::Fn(box Fn { generics, .. }) => {

View File

@ -819,7 +819,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
// `Box<dyn Debug + 'static>`. // `Box<dyn Debug + 'static>`.
self.resolve_object_lifetime_default(lifetime) self.resolve_object_lifetime_default(lifetime)
} }
LifetimeName::Underscore => { LifetimeName::Infer => {
// If the user writes `'_`, we use the *ordinary* elision // If the user writes `'_`, we use the *ordinary* elision
// rules. So the `'_` in e.g., `Box<dyn Debug + '_>` will be // rules. So the `'_` in e.g., `Box<dyn Debug + '_>` will be
// resolved the same as the `'_` in `&'_ Foo`. // resolved the same as the `'_` in `&'_ Foo`.
@ -1135,7 +1135,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
#[tracing::instrument(level = "debug", skip(self))] #[tracing::instrument(level = "debug", skip(self))]
fn visit_lifetime(&mut self, lifetime_ref: &'tcx hir::Lifetime) { fn visit_lifetime(&mut self, lifetime_ref: &'tcx hir::Lifetime) {
match lifetime_ref.name { match lifetime_ref.name {
hir::LifetimeName::ImplicitObjectLifetimeDefault | hir::LifetimeName::Underscore => { hir::LifetimeName::ImplicitObjectLifetimeDefault | hir::LifetimeName::Infer => {
self.resolve_elided_lifetimes(&[lifetime_ref]) self.resolve_elided_lifetimes(&[lifetime_ref])
} }
hir::LifetimeName::Static => self.insert_lifetime(lifetime_ref, Region::Static), hir::LifetimeName::Static => self.insert_lifetime(lifetime_ref, Region::Static),

View File

@ -166,7 +166,7 @@ fn captures_all_lifetimes(inputs: &[Ty<'_>], output_lifetimes: &[LifetimeName])
// - There's only one output lifetime bound using `+ '_` // - There's only one output lifetime bound using `+ '_`
// - All input lifetimes are explicitly bound to the output // - All input lifetimes are explicitly bound to the output
input_lifetimes.is_empty() input_lifetimes.is_empty()
|| (output_lifetimes.len() == 1 && matches!(output_lifetimes[0], LifetimeName::Underscore)) || (output_lifetimes.len() == 1 && matches!(output_lifetimes[0], LifetimeName::Infer))
|| input_lifetimes || input_lifetimes
.iter() .iter()
.all(|in_lt| output_lifetimes.iter().any(|out_lt| in_lt == out_lt)) .all(|in_lt| output_lifetimes.iter().any(|out_lt| in_lt == out_lt))

View File

@ -351,7 +351,7 @@ impl fmt::Display for RefPrefix {
name.fmt(f)?; name.fmt(f)?;
f.write_char(' ')?; f.write_char(' ')?;
}, },
LifetimeName::Underscore => f.write_str("'_ ")?, LifetimeName::Infer => f.write_str("'_ ")?,
LifetimeName::Static => f.write_str("'static ")?, LifetimeName::Static => f.write_str("'static ")?,
_ => (), _ => (),
} }