Auto merge of #104048 - cjgillot:split-lifetime, r=compiler-errors

Separate lifetime ident from lifetime resolution in HIR

Drive-by: change how suggested generic args are computed.
Fixes https://github.com/rust-lang/rust/issues/103815

I recommend reviewing commit-by-commit.
This commit is contained in:
bors 2022-11-27 14:30:19 +00:00
commit 696ea0627d
5 changed files with 33 additions and 46 deletions

View File

@ -10,8 +10,8 @@ use rustc_hir::lang_items;
use rustc_hir::FnRetTy::Return; use rustc_hir::FnRetTy::Return;
use rustc_hir::{ use rustc_hir::{
BareFnTy, BodyId, FnDecl, GenericArg, GenericBound, GenericParam, GenericParamKind, Generics, Impl, ImplItem, BareFnTy, BodyId, FnDecl, GenericArg, GenericBound, GenericParam, GenericParamKind, Generics, Impl, ImplItem,
ImplItemKind, Item, ItemKind, Lifetime, LifetimeName, ParamName, PolyTraitRef, PredicateOrigin, TraitFn, TraitItem, ImplItemKind, Item, ItemKind, Lifetime, LifetimeName, LifetimeParamKind, PolyTraitRef, PredicateOrigin, TraitFn,
TraitItemKind, Ty, TyKind, WherePredicate, TraitItem, TraitItemKind, Ty, TyKind, WherePredicate,
}; };
use rustc_lint::{LateContext, LateLintPass}; use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::hir::nested_filter as middle_nested_filter; use rustc_middle::hir::nested_filter as middle_nested_filter;
@ -180,7 +180,7 @@ fn check_fn_inner<'tcx>(
_ => None, _ => None,
}); });
for bound in lifetimes { for bound in lifetimes {
if bound.name != LifetimeName::Static && !bound.is_elided() { if !bound.is_static() && !bound.is_elided() {
return; return;
} }
} }
@ -414,17 +414,13 @@ impl<'a, 'tcx> RefVisitor<'a, 'tcx> {
fn record(&mut self, lifetime: &Option<Lifetime>) { fn record(&mut self, lifetime: &Option<Lifetime>) {
if let Some(ref lt) = *lifetime { if let Some(ref lt) = *lifetime {
if lt.name == LifetimeName::Static { if lt.is_static() {
self.lts.push(RefLt::Static); self.lts.push(RefLt::Static);
} else if let LifetimeName::Param(_, ParamName::Fresh) = lt.name { } else if lt.is_anonymous() {
// Fresh lifetimes generated should be ignored. // Fresh lifetimes generated should be ignored.
self.lts.push(RefLt::Unnamed); self.lts.push(RefLt::Unnamed);
} else if lt.is_elided() { } else if let LifetimeName::Param(def_id) = lt.res {
self.lts.push(RefLt::Unnamed);
} else if let LifetimeName::Param(def_id, _) = lt.name {
self.lts.push(RefLt::Named(def_id)); self.lts.push(RefLt::Named(def_id));
} else {
self.lts.push(RefLt::Unnamed);
} }
} else { } else {
self.lts.push(RefLt::Unnamed); self.lts.push(RefLt::Unnamed);
@ -472,7 +468,7 @@ impl<'a, 'tcx> Visitor<'tcx> for RefVisitor<'a, 'tcx> {
walk_item(self, item); walk_item(self, item);
self.lts.truncate(len); self.lts.truncate(len);
self.lts.extend(bounds.iter().filter_map(|bound| match bound { self.lts.extend(bounds.iter().filter_map(|bound| match bound {
GenericArg::Lifetime(l) => Some(if let LifetimeName::Param(def_id, _) = l.name { GenericArg::Lifetime(l) => Some(if let LifetimeName::Param(def_id) = l.res {
RefLt::Named(def_id) RefLt::Named(def_id)
} else { } else {
RefLt::Unnamed RefLt::Unnamed
@ -498,10 +494,8 @@ impl<'a, 'tcx> Visitor<'tcx> for RefVisitor<'a, 'tcx> {
} }
fn visit_generic_arg(&mut self, generic_arg: &'tcx GenericArg<'tcx>) { fn visit_generic_arg(&mut self, generic_arg: &'tcx GenericArg<'tcx>) {
if let GenericArg::Lifetime(l) = generic_arg if let GenericArg::Lifetime(l) = generic_arg && let LifetimeName::Param(def_id) = l.res {
&& let LifetimeName::Param(def_id, _) = l.name self.lifetime_generic_arg_spans.entry(def_id).or_insert(l.ident.span);
{
self.lifetime_generic_arg_spans.entry(def_id).or_insert(l.span);
} }
// Replace with `walk_generic_arg` if/when https://github.com/rust-lang/rust/pull/103692 lands. // Replace with `walk_generic_arg` if/when https://github.com/rust-lang/rust/pull/103692 lands.
// walk_generic_arg(self, generic_arg); // walk_generic_arg(self, generic_arg);
@ -577,7 +571,7 @@ where
// for lifetimes as parameters of generics // for lifetimes as parameters of generics
fn visit_lifetime(&mut self, lifetime: &'tcx Lifetime) { fn visit_lifetime(&mut self, lifetime: &'tcx Lifetime) {
self.map.remove(&lifetime.name.ident().name); self.map.remove(&lifetime.ident.name);
} }
fn visit_generic_param(&mut self, param: &'tcx GenericParam<'_>) { fn visit_generic_param(&mut self, param: &'tcx GenericParam<'_>) {
@ -601,7 +595,9 @@ fn report_extra_lifetimes<'tcx>(cx: &LateContext<'tcx>, func: &'tcx FnDecl<'_>,
.params .params
.iter() .iter()
.filter_map(|par| match par.kind { .filter_map(|par| match par.kind {
GenericParamKind::Lifetime { .. } => Some((par.name.ident().name, par.span)), GenericParamKind::Lifetime {
kind: LifetimeParamKind::Explicit,
} => Some((par.name.ident().name, par.span)),
_ => None, _ => None,
}) })
.collect(); .collect();
@ -626,7 +622,9 @@ fn report_extra_impl_lifetimes<'tcx>(cx: &LateContext<'tcx>, impl_: &'tcx Impl<'
.params .params
.iter() .iter()
.filter_map(|par| match par.kind { .filter_map(|par| match par.kind {
GenericParamKind::Lifetime { .. } => Some((par.name.ident().name, par.span)), GenericParamKind::Lifetime {
kind: LifetimeParamKind::Explicit,
} => Some((par.name.ident().name, par.span)),
_ => None, _ => None,
}) })
.collect(); .collect();
@ -653,7 +651,7 @@ struct BodyLifetimeChecker {
impl<'tcx> Visitor<'tcx> for BodyLifetimeChecker { impl<'tcx> Visitor<'tcx> for BodyLifetimeChecker {
// for lifetimes as parameters of generics // for lifetimes as parameters of generics
fn visit_lifetime(&mut self, lifetime: &'tcx Lifetime) { fn visit_lifetime(&mut self, lifetime: &'tcx Lifetime) {
if lifetime.name.ident().name != kw::UnderscoreLifetime && lifetime.name.ident().name != kw::StaticLifetime { if !lifetime.is_anonymous() && lifetime.ident.name != kw::StaticLifetime {
self.lifetimes_used_in_body = true; self.lifetimes_used_in_body = true;
} }
} }

View File

@ -118,7 +118,7 @@ fn future_trait_ref<'tcx>(
.iter() .iter()
.filter_map(|bound| { .filter_map(|bound| {
if let GenericArg::Lifetime(lt) = bound { if let GenericArg::Lifetime(lt) = bound {
Some(lt.name) Some(lt.res)
} else { } else {
None None
} }
@ -153,7 +153,7 @@ fn captures_all_lifetimes(inputs: &[Ty<'_>], output_lifetimes: &[LifetimeName])
.iter() .iter()
.filter_map(|ty| { .filter_map(|ty| {
if let TyKind::Rptr(lt, _) = ty.kind { if let TyKind::Rptr(lt, _) = ty.kind {
Some(lt.name) Some(lt.res)
} else { } else {
None None
} }

View File

@ -12,8 +12,8 @@ use rustc_hir::hir_id::HirIdMap;
use rustc_hir::intravisit::{walk_expr, Visitor}; use rustc_hir::intravisit::{walk_expr, Visitor};
use rustc_hir::{ use rustc_hir::{
self as hir, AnonConst, BinOpKind, BindingAnnotation, Body, Expr, ExprKind, FnRetTy, FnSig, GenericArg, self as hir, AnonConst, BinOpKind, BindingAnnotation, Body, Expr, ExprKind, FnRetTy, FnSig, GenericArg,
ImplItemKind, ItemKind, Lifetime, LifetimeName, Mutability, Node, Param, ParamName, PatKind, QPath, TraitFn, ImplItemKind, ItemKind, Lifetime, Mutability, Node, Param, PatKind, QPath, TraitFn, TraitItem, TraitItemKind,
TraitItem, TraitItemKind, TyKind, Unsafety, TyKind, Unsafety,
}; };
use rustc_infer::infer::TyCtxtInferExt; use rustc_infer::infer::TyCtxtInferExt;
use rustc_infer::traits::{Obligation, ObligationCause}; use rustc_infer::traits::{Obligation, ObligationCause};
@ -343,21 +343,16 @@ impl PtrArg<'_> {
} }
struct RefPrefix { struct RefPrefix {
lt: LifetimeName, lt: Lifetime,
mutability: Mutability, mutability: Mutability,
} }
impl fmt::Display for RefPrefix { impl fmt::Display for RefPrefix {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
use fmt::Write; use fmt::Write;
f.write_char('&')?; f.write_char('&')?;
match self.lt { if !self.lt.is_anonymous() {
LifetimeName::Param(_, ParamName::Plain(name)) => { self.lt.ident.fmt(f)?;
name.fmt(f)?; f.write_char(' ')?;
f.write_char(' ')?;
},
LifetimeName::Infer => f.write_str("'_ ")?,
LifetimeName::Static => f.write_str("'static ")?,
_ => (),
} }
f.write_str(self.mutability.prefix_str()) f.write_str(self.mutability.prefix_str())
} }
@ -495,7 +490,7 @@ fn check_fn_args<'cx, 'tcx: 'cx>(
ty_name: name.ident.name, ty_name: name.ident.name,
method_renames, method_renames,
ref_prefix: RefPrefix { ref_prefix: RefPrefix {
lt: lt.name, lt: lt.clone(),
mutability, mutability,
}, },
deref_ty, deref_ty,

View File

@ -31,10 +31,10 @@ pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, lt: &Lifetime, m
return false; return false;
} }
let ltopt = if lt.name.is_anonymous() { let ltopt = if lt.is_anonymous() {
String::new() String::new()
} else { } else {
format!("{} ", lt.name.ident().as_str()) format!("{} ", lt.ident.as_str())
}; };
if mut_ty.mutbl == Mutability::Mut { if mut_ty.mutbl == Mutability::Mut {

View File

@ -7,7 +7,7 @@ use rustc_hir::def::Res;
use rustc_hir::HirIdMap; use rustc_hir::HirIdMap;
use rustc_hir::{ use rustc_hir::{
ArrayLen, BinOpKind, BindingAnnotation, Block, BodyId, Closure, Expr, ExprField, ExprKind, FnRetTy, GenericArg, ArrayLen, BinOpKind, BindingAnnotation, Block, BodyId, Closure, Expr, ExprField, ExprKind, FnRetTy, GenericArg,
GenericArgs, Guard, HirId, InlineAsmOperand, Let, Lifetime, LifetimeName, ParamName, Pat, PatField, PatKind, Path, GenericArgs, Guard, HirId, InlineAsmOperand, Let, Lifetime, LifetimeName, Pat, PatField, PatKind, Path,
PathSegment, PrimTy, QPath, Stmt, StmtKind, Ty, TyKind, TypeBinding, PathSegment, PrimTy, QPath, Stmt, StmtKind, Ty, TyKind, TypeBinding,
}; };
use rustc_lexer::{tokenize, TokenKind}; use rustc_lexer::{tokenize, TokenKind};
@ -337,7 +337,7 @@ impl HirEqInterExpr<'_, '_, '_> {
} }
fn eq_lifetime(left: &Lifetime, right: &Lifetime) -> bool { fn eq_lifetime(left: &Lifetime, right: &Lifetime) -> bool {
left.name == right.name left.res == right.res
} }
fn eq_pat_field(&mut self, left: &PatField<'_>, right: &PatField<'_>) -> bool { fn eq_pat_field(&mut self, left: &PatField<'_>, right: &PatField<'_>) -> bool {
@ -925,16 +925,10 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
} }
pub fn hash_lifetime(&mut self, lifetime: &Lifetime) { pub fn hash_lifetime(&mut self, lifetime: &Lifetime) {
std::mem::discriminant(&lifetime.name).hash(&mut self.s); lifetime.ident.name.hash(&mut self.s);
if let LifetimeName::Param(param_id, ref name) = lifetime.name { std::mem::discriminant(&lifetime.res).hash(&mut self.s);
std::mem::discriminant(name).hash(&mut self.s); if let LifetimeName::Param(param_id) = lifetime.res {
param_id.hash(&mut self.s); param_id.hash(&mut self.s);
match name {
ParamName::Plain(ref ident) => {
ident.name.hash(&mut self.s);
},
ParamName::Fresh | ParamName::Error => {},
}
} }
} }