Separate lifetime ident from resolution in HIR.

This commit is contained in:
Camille GILLOT 2022-11-05 22:41:07 +00:00
parent d121aa3b55
commit fb7d25e978
28 changed files with 177 additions and 273 deletions

View File

@ -303,7 +303,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
}
fn visit_lifetime(&mut self, lifetime: &'hir Lifetime) {
self.insert(lifetime.span, lifetime.hir_id, Node::Lifetime(lifetime));
self.insert(lifetime.ident.span, lifetime.hir_id, Node::Lifetime(lifetime));
}
fn visit_variant(&mut self, v: &'hir Variant<'hir>) {

View File

@ -1479,10 +1479,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
}))
}
GenericParamKind::Lifetime => {
let ident_span = self.lower_span(ident.span);
let ident = self.lower_ident(ident);
let lt_id = self.next_node_id();
let lifetime = self.new_named_lifetime(id, lt_id, ident_span, ident);
let lifetime = self.new_named_lifetime(id, lt_id, ident);
Some(hir::WherePredicate::RegionPredicate(hir::WhereRegionPredicate {
lifetime,
span,

View File

@ -1255,7 +1255,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
} else {
self.next_node_id()
};
let span = self.tcx.sess.source_map().start_point(t.span);
let span = self.tcx.sess.source_map().start_point(t.span).shrink_to_hi();
Lifetime { ident: Ident::new(kw::UnderscoreLifetime, span), id }
});
let lifetime = self.lower_lifetime(&region);
@ -1546,15 +1546,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
let lifetimes =
self.arena.alloc_from_iter(collected_lifetimes.into_iter().map(|(_, lifetime)| {
let id = self.next_node_id();
let span = lifetime.ident.span;
let ident = if lifetime.ident.name == kw::UnderscoreLifetime {
Ident::with_dummy_span(kw::UnderscoreLifetime)
} else {
lifetime.ident
};
let l = self.new_named_lifetime(lifetime.id, id, span, ident);
let l = self.new_named_lifetime(lifetime.id, id, lifetime.ident);
hir::GenericArg::Lifetime(l)
}));
debug!(?lifetimes);
@ -2014,18 +2006,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
let generic_args = self.arena.alloc_from_iter(collected_lifetimes.into_iter().map(
|(_, lifetime, res)| {
let id = self.next_node_id();
let span = lifetime.ident.span;
let ident = if lifetime.ident.name == kw::UnderscoreLifetime {
Ident::with_dummy_span(kw::UnderscoreLifetime)
} else {
lifetime.ident
};
let res = res.unwrap_or(
self.resolver.get_lifetime_res(lifetime.id).unwrap_or(LifetimeRes::Error),
);
hir::GenericArg::Lifetime(self.new_named_lifetime_with_res(id, span, ident, res))
hir::GenericArg::Lifetime(self.new_named_lifetime_with_res(id, lifetime.ident, res))
},
));
@ -2095,43 +2079,41 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
}
fn lower_lifetime(&mut self, l: &Lifetime) -> &'hir hir::Lifetime {
let span = self.lower_span(l.ident.span);
let ident = self.lower_ident(l.ident);
self.new_named_lifetime(l.id, l.id, span, ident)
self.new_named_lifetime(l.id, l.id, ident)
}
#[instrument(level = "debug", skip(self))]
fn new_named_lifetime_with_res(
&mut self,
id: NodeId,
span: Span,
ident: Ident,
res: LifetimeRes,
) -> &'hir hir::Lifetime {
let name = match res {
let res = match res {
LifetimeRes::Param { param, .. } => {
let p_name = ParamName::Plain(ident);
let param = self.get_remapped_def_id(param);
hir::LifetimeName::Param(param, p_name)
hir::LifetimeName::Param(param)
}
LifetimeRes::Fresh { param, .. } => {
debug_assert_eq!(ident.name, kw::UnderscoreLifetime);
let param = self.local_def_id(param);
hir::LifetimeName::Param(param, ParamName::Fresh)
hir::LifetimeName::Param(param)
}
LifetimeRes::Infer => hir::LifetimeName::Infer,
LifetimeRes::Static => hir::LifetimeName::Static,
LifetimeRes::Error => hir::LifetimeName::Error,
res => panic!("Unexpected lifetime resolution {:?} for {:?} at {:?}", res, ident, span),
res => panic!(
"Unexpected lifetime resolution {:?} for {:?} at {:?}",
res, ident, ident.span
),
};
debug!(?name);
debug!(?res);
self.arena.alloc(hir::Lifetime {
hir_id: self.lower_node_id(id),
span: self.lower_span(span),
name,
ident: self.lower_ident(ident),
res,
})
}
@ -2140,11 +2122,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
&mut self,
id: NodeId,
new_id: NodeId,
span: Span,
ident: Ident,
) -> &'hir hir::Lifetime {
let res = self.resolver.get_lifetime_res(id).unwrap_or(LifetimeRes::Error);
self.new_named_lifetime_with_res(new_id, span, ident, res)
self.new_named_lifetime_with_res(new_id, ident, res)
}
fn lower_generic_params_mut<'s>(
@ -2556,8 +2537,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
fn elided_dyn_bound(&mut self, span: Span) -> &'hir hir::Lifetime {
let r = hir::Lifetime {
hir_id: self.next_id(),
span: self.lower_span(span),
name: hir::LifetimeName::ImplicitObjectLifetimeDefault,
ident: Ident::new(kw::Empty, self.lower_span(span)),
res: hir::LifetimeName::ImplicitObjectLifetimeDefault,
};
debug!("elided_dyn_bound: r={:?}", r);
self.arena.alloc(r)

View File

@ -2509,7 +2509,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
if let hir::TyKind::Rptr(lifetime, _) = &fn_decl.inputs[index].kind {
// With access to the lifetime, we can get
// the span of it.
arguments.push((*argument, lifetime.span));
arguments.push((*argument, lifetime.ident.span));
} else {
bug!("ty type is a ref but hir type is not");
}
@ -2528,7 +2528,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
let mut return_span = fn_decl.output.span();
if let hir::FnRetTy::Return(ty) = &fn_decl.output {
if let hir::TyKind::Rptr(lifetime, _) = ty.kind {
return_span = lifetime.span;
return_span = lifetime.ident.span;
}
}

View File

@ -1211,7 +1211,7 @@ fn get_mut_span_in_struct_field<'tcx>(
&& let hir::Node::Field(field) = node
&& let hir::TyKind::Rptr(lt, hir::MutTy { mutbl: hir::Mutability::Not, ty }) = field.ty.kind
{
return Some(lt.span.between(ty.span));
return Some(lt.ident.span.between(ty.span));
}
None

View File

@ -576,30 +576,10 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
let args = last_segment.args.as_ref()?;
let lifetime =
self.try_match_adt_and_generic_args(substs, needle_fr, args, search_stack)?;
match lifetime.name {
hir::LifetimeName::Param(_, hir::ParamName::Plain(_) | hir::ParamName::Error)
| hir::LifetimeName::Error
| hir::LifetimeName::Static => {
let lifetime_span = lifetime.span;
Some(RegionNameHighlight::MatchedAdtAndSegment(lifetime_span))
}
hir::LifetimeName::Param(_, hir::ParamName::Fresh)
| hir::LifetimeName::ImplicitObjectLifetimeDefault
| hir::LifetimeName::Infer => {
// In this case, the user left off the lifetime; so
// they wrote something like:
//
// ```
// x: Foo<T>
// ```
//
// where the fully elaborated form is `Foo<'_, '1,
// T>`. We don't consider this a match; instead we let
// the "fully elaborated" type fallback above handle
// it.
None
}
if lifetime.is_anonymous() {
None
} else {
Some(RegionNameHighlight::MatchedAdtAndSegment(lifetime.ident.span))
}
}

View File

@ -29,7 +29,7 @@ use std::fmt;
#[derive(Debug, Copy, Clone, Encodable, HashStable_Generic)]
pub struct Lifetime {
pub hir_id: HirId,
pub span: Span,
pub ident: Ident,
/// Either "`'a`", referring to a named lifetime definition,
/// or "``" (i.e., `kw::Empty`), for elision placeholders.
@ -37,7 +37,7 @@ pub struct Lifetime {
/// HIR lowering inserts these placeholders in type paths that
/// refer to type definitions needing lifetime parameters,
/// `&T` and `&mut T`, and trait objects without `... + 'a`.
pub name: LifetimeName,
pub res: LifetimeName,
}
#[derive(Debug, Clone, PartialEq, Eq, Encodable, Hash, Copy)]
@ -88,7 +88,7 @@ impl ParamName {
#[derive(HashStable_Generic)]
pub enum LifetimeName {
/// User-given names or fresh (synthetic) names.
Param(LocalDefId, ParamName),
Param(LocalDefId),
/// Implicit lifetime in a context like `dyn Foo`. This is
/// distinguished from implicit lifetimes elsewhere because the
@ -116,25 +116,6 @@ pub enum LifetimeName {
}
impl LifetimeName {
pub fn ident(&self) -> Ident {
match *self {
LifetimeName::ImplicitObjectLifetimeDefault | LifetimeName::Error => Ident::empty(),
LifetimeName::Infer => Ident::with_dummy_span(kw::UnderscoreLifetime),
LifetimeName::Static => Ident::with_dummy_span(kw::StaticLifetime),
LifetimeName::Param(_, param_name) => param_name.ident(),
}
}
pub fn is_anonymous(&self) -> bool {
match *self {
LifetimeName::ImplicitObjectLifetimeDefault
| LifetimeName::Infer
| LifetimeName::Param(_, ParamName::Fresh)
| LifetimeName::Error => true,
LifetimeName::Static | LifetimeName::Param(..) => false,
}
}
pub fn is_elided(&self) -> bool {
match self {
LifetimeName::ImplicitObjectLifetimeDefault | LifetimeName::Infer => true,
@ -146,34 +127,25 @@ impl LifetimeName {
LifetimeName::Error | LifetimeName::Param(..) | LifetimeName::Static => false,
}
}
fn is_static(&self) -> bool {
self == &LifetimeName::Static
}
pub fn normalize_to_macros_2_0(&self) -> LifetimeName {
match *self {
LifetimeName::Param(def_id, param_name) => {
LifetimeName::Param(def_id, param_name.normalize_to_macros_2_0())
}
lifetime_name => lifetime_name,
}
}
}
impl fmt::Display for Lifetime {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.name.ident().fmt(f)
self.ident.fmt(f)
}
}
impl Lifetime {
pub fn is_elided(&self) -> bool {
self.name.is_elided()
self.res.is_elided()
}
pub fn is_anonymous(&self) -> bool {
self.ident.name == kw::Empty || self.ident.name == kw::UnderscoreLifetime
}
pub fn is_static(&self) -> bool {
self.name.is_static()
self.res == LifetimeName::Static
}
}
@ -267,7 +239,7 @@ pub enum GenericArg<'hir> {
impl GenericArg<'_> {
pub fn span(&self) -> Span {
match self {
GenericArg::Lifetime(l) => l.span,
GenericArg::Lifetime(l) => l.ident.span,
GenericArg::Type(t) => t.span,
GenericArg::Const(c) => c.span,
GenericArg::Infer(i) => i.span,
@ -284,7 +256,7 @@ impl GenericArg<'_> {
}
pub fn is_synthetic(&self) -> bool {
matches!(self, GenericArg::Lifetime(lifetime) if lifetime.name.ident() == Ident::empty())
matches!(self, GenericArg::Lifetime(lifetime) if lifetime.ident == Ident::empty())
}
pub fn descr(&self) -> &'static str {
@ -446,7 +418,7 @@ impl GenericBound<'_> {
match self {
GenericBound::Trait(t, ..) => t.span,
GenericBound::LangItemTrait(_, span, ..) => *span,
GenericBound::Outlives(l) => l.span,
GenericBound::Outlives(l) => l.ident.span,
}
}
}
@ -559,6 +531,19 @@ impl<'hir> Generics<'hir> {
}
}
/// If there are generic parameters, return where to introduce a new one.
pub fn span_for_lifetime_suggestion(&self) -> Option<Span> {
if let Some(first) = self.params.first()
&& self.span.contains(first.span)
{
// `fn foo<A>(t: impl Trait)`
// ^ suggest `'a, ` here
Some(first.span.shrink_to_lo())
} else {
None
}
}
/// If there are generic parameters, return where to introduce a new one.
pub fn span_for_param_suggestion(&self) -> Option<Span> {
if self.params.iter().any(|p| self.span.contains(p.span)) {
@ -765,10 +750,7 @@ pub struct WhereRegionPredicate<'hir> {
impl<'hir> WhereRegionPredicate<'hir> {
/// Returns `true` if `param_def_id` matches the `lifetime` of this predicate.
pub fn is_param_bound(&self, param_def_id: LocalDefId) -> bool {
match self.lifetime.name {
LifetimeName::Param(id, _) => id == param_def_id,
_ => false,
}
self.lifetime.res == LifetimeName::Param(param_def_id)
}
}
@ -3453,7 +3435,7 @@ impl<'hir> Node<'hir> {
| Node::Variant(Variant { ident, .. })
| Node::Item(Item { ident, .. })
| Node::PathSegment(PathSegment { ident, .. }) => Some(*ident),
Node::Lifetime(lt) => Some(lt.name.ident()),
Node::Lifetime(lt) => Some(lt.ident),
Node::GenericParam(p) => Some(p.name.ident()),
Node::TypeBinding(b) => Some(b.ident),
Node::Param(..)

View File

@ -1109,17 +1109,7 @@ pub fn walk_generic_arg<'v, V: Visitor<'v>>(visitor: &mut V, generic_arg: &'v Ge
pub fn walk_lifetime<'v, V: Visitor<'v>>(visitor: &mut V, lifetime: &'v Lifetime) {
visitor.visit_id(lifetime.hir_id);
match lifetime.name {
LifetimeName::Param(_, ParamName::Plain(ident)) => {
visitor.visit_ident(ident);
}
LifetimeName::Param(_, ParamName::Fresh)
| LifetimeName::Param(_, ParamName::Error)
| LifetimeName::Static
| LifetimeName::Error
| LifetimeName::ImplicitObjectLifetimeDefault
| LifetimeName::Infer => {}
}
visitor.visit_ident(lifetime.ident);
}
pub fn walk_qpath<'v, V: Visitor<'v>>(visitor: &mut V, qpath: &'v QPath<'v>, id: HirId) {

View File

@ -5,6 +5,7 @@
#![feature(associated_type_defaults)]
#![feature(closure_track_caller)]
#![feature(const_btree_len)]
#![feature(let_chains)]
#![feature(min_specialization)]
#![feature(never_type)]
#![feature(rustc_attrs)]

View File

@ -241,14 +241,14 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
}
None => {
self.re_infer(def, lifetime.span).unwrap_or_else(|| {
self.re_infer(def, lifetime.ident.span).unwrap_or_else(|| {
debug!(?lifetime, "unelided lifetime in signature");
// This indicates an illegal lifetime
// elision. `resolve_lifetime` should have
// reported an error in this case -- but if
// not, let's error out.
tcx.sess.delay_span_bug(lifetime.span, "unelided lifetime in signature");
tcx.sess.delay_span_bug(lifetime.ident.span, "unelided lifetime in signature");
// Supply some dummy value. We don't have an
// `re_error`, annoyingly, so use `'static`.
@ -961,9 +961,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
}
hir::GenericBound::Outlives(lifetime) => {
let region = self.ast_region_to_region(lifetime, None);
bounds
.region_bounds
.push((ty::Binder::bind_with_vars(region, bound_vars), lifetime.span));
bounds.region_bounds.push((
ty::Binder::bind_with_vars(region, bound_vars),
lifetime.ident.span,
));
}
}
}

View File

@ -398,7 +398,7 @@ fn has_late_bound_regions<'tcx>(tcx: TyCtxt<'tcx>, node: Node<'tcx>) -> Option<S
Some(rl::Region::Static | rl::Region::EarlyBound(..)) => {}
Some(rl::Region::LateBound(debruijn, _, _)) if debruijn < self.outer_index => {}
Some(rl::Region::LateBound(..) | rl::Region::Free(..)) | None => {
self.has_late_bound_regions = Some(lt.span);
self.has_late_bound_regions = Some(lt.ident.span);
}
}
}

View File

@ -19,7 +19,7 @@ use rustc_middle::hir::nested_filter;
use rustc_middle::middle::resolve_lifetime::*;
use rustc_middle::ty::{self, DefIdTree, TyCtxt, TypeSuperVisitable, TypeVisitor};
use rustc_span::def_id::DefId;
use rustc_span::symbol::{sym, Ident};
use rustc_span::symbol::{kw, sym, Ident};
use rustc_span::Span;
use std::fmt;
@ -595,7 +595,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
this.visit_poly_trait_ref(bound);
}
});
match lifetime.name {
match lifetime.res {
LifetimeName::ImplicitObjectLifetimeDefault => {
// If the user does not write *anything*, we
// use the object lifetime defaulting
@ -686,7 +686,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
if !parent_id.is_owner() {
struct_span_err!(
self.tcx.sess,
lifetime.span,
lifetime.ident.span,
E0657,
"`impl Trait` can only capture lifetimes bound at the fn or impl level"
)
@ -698,7 +698,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
}) = self.tcx.hir().get(parent_id)
{
let mut err = self.tcx.sess.struct_span_err(
lifetime.span,
lifetime.ident.span,
"higher kinded lifetime bounds on nested opaque types are not supported yet",
);
err.span_note(self.tcx.def_span(def_id), "lifetime declared here");
@ -802,9 +802,9 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
#[instrument(level = "debug", skip(self))]
fn visit_lifetime(&mut self, lifetime_ref: &'tcx hir::Lifetime) {
match lifetime_ref.name {
match lifetime_ref.res {
hir::LifetimeName::Static => self.insert_lifetime(lifetime_ref, Region::Static),
hir::LifetimeName::Param(param_def_id, _) => {
hir::LifetimeName::Param(param_def_id) => {
self.resolve_lifetime_ref(param_def_id, lifetime_ref)
}
// If we've already reported an error, just ignore `lifetime_ref`.
@ -912,27 +912,27 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
this.visit_lifetime(lifetime);
walk_list!(this, visit_param_bound, bounds);
if lifetime.name != hir::LifetimeName::Static {
if lifetime.res != hir::LifetimeName::Static {
for bound in bounds {
let hir::GenericBound::Outlives(ref lt) = bound else {
continue;
};
if lt.name != hir::LifetimeName::Static {
if lt.res != hir::LifetimeName::Static {
continue;
}
this.insert_lifetime(lt, Region::Static);
this.tcx
.sess
.struct_span_warn(
lifetime.span,
lifetime.ident.span,
&format!(
"unnecessary lifetime parameter `{}`",
lifetime.name.ident(),
lifetime.ident,
),
)
.help(&format!(
"you can use the `'static` lifetime directly, in place of `{}`",
lifetime.name.ident(),
lifetime.ident,
))
.emit();
}
@ -1043,7 +1043,7 @@ fn object_lifetime_default<'tcx>(tcx: TyCtxt<'tcx>, param_def_id: DefId) -> Obje
for bound in bound.bounds {
if let hir::GenericBound::Outlives(ref lifetime) = *bound {
set.insert(lifetime.name.normalize_to_macros_2_0());
set.insert(lifetime.res);
}
}
}
@ -1051,7 +1051,7 @@ fn object_lifetime_default<'tcx>(tcx: TyCtxt<'tcx>, param_def_id: DefId) -> Obje
match set {
Set1::Empty => ObjectLifetimeDefault::Empty,
Set1::One(hir::LifetimeName::Static) => ObjectLifetimeDefault::Static,
Set1::One(hir::LifetimeName::Param(param_def_id, _)) => {
Set1::One(hir::LifetimeName::Param(param_def_id)) => {
ObjectLifetimeDefault::Param(param_def_id.to_def_id())
}
_ => ObjectLifetimeDefault::Ambiguous,
@ -1195,42 +1195,48 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
// Fresh lifetimes in APIT used to be allowed in async fns and forbidden in
// regular fns.
if let Some(hir::PredicateOrigin::ImplTrait) = where_bound_origin
&& let hir::LifetimeName::Param(_, hir::ParamName::Fresh) = lifetime_ref.name
&& let hir::LifetimeName::Param(_) = lifetime_ref.res
&& lifetime_ref.is_anonymous()
&& let hir::IsAsync::NotAsync = self.tcx.asyncness(lifetime_ref.hir_id.owner.def_id)
&& !self.tcx.features().anonymous_lifetime_in_impl_trait
{
let mut diag = rustc_session::parse::feature_err(
&self.tcx.sess.parse_sess,
sym::anonymous_lifetime_in_impl_trait,
lifetime_ref.span,
lifetime_ref.ident.span,
"anonymous lifetimes in `impl Trait` are unstable",
);
match self.tcx.hir().get_generics(lifetime_ref.hir_id.owner.def_id) {
Some(generics) => {
if let Some(generics) =
self.tcx.hir().get_generics(lifetime_ref.hir_id.owner.def_id)
{
let new_param_sugg = if let Some(span) =
generics.span_for_lifetime_suggestion()
{
(span, "'a, ".to_owned())
} else {
(generics.span, "<'a>".to_owned())
};
let new_param_sugg_tuple;
let lifetime_sugg = match lifetime_ref.ident.name {
kw::Empty => "'a, ".to_owned(),
kw::UnderscoreLifetime => "'a ".to_owned(),
_ => "'a ".to_owned(),
};
let suggestions = vec![
(lifetime_ref.ident.span.shrink_to_hi(), lifetime_sugg),
new_param_sugg,
];
new_param_sugg_tuple = match generics.span_for_param_suggestion() {
Some(_) => {
Some((self.tcx.sess.source_map().span_through_char(generics.span, '<').shrink_to_hi(), "'a, ".to_owned()))
},
None => Some((generics.span, "<'a>".to_owned()))
};
let mut multi_sugg_vec = vec![(lifetime_ref.span.shrink_to_hi(), "'a ".to_owned())];
if let Some(new_tuple) = new_param_sugg_tuple{
multi_sugg_vec.push(new_tuple);
}
diag.span_label(lifetime_ref.span, "expected named lifetime parameter");
diag.multipart_suggestion("consider introducing a named lifetime parameter",
multi_sugg_vec,
rustc_errors::Applicability::MaybeIncorrect);
},
None => { }
diag.span_label(
lifetime_ref.ident.span,
"expected named lifetime parameter",
);
diag.multipart_suggestion(
"consider introducing a named lifetime parameter",
suggestions,
rustc_errors::Applicability::MaybeIncorrect,
);
}
diag.emit();
@ -1287,7 +1293,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
where_bound_origin: Some(hir::PredicateOrigin::ImplTrait), ..
} => {
let mut err = self.tcx.sess.struct_span_err(
lifetime_ref.span,
lifetime_ref.ident.span,
"`impl Trait` can only mention lifetimes bound at the fn or impl level",
);
err.span_note(self.tcx.def_span(region_def_id), "lifetime declared here");
@ -1307,7 +1313,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
}
self.tcx.sess.delay_span_bug(
lifetime_ref.span,
lifetime_ref.ident.span,
&format!("Could not resolve {:?} in scope {:#?}", lifetime_ref, self.scope,),
);
}
@ -1625,10 +1631,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
#[instrument(level = "debug", skip(self))]
fn insert_lifetime(&mut self, lifetime_ref: &'tcx hir::Lifetime, def: Region) {
debug!(
node = ?self.tcx.hir().node_to_string(lifetime_ref.hir_id),
span = ?self.tcx.sess.source_map().span_to_diagnostic_string(lifetime_ref.span)
);
debug!(span = ?lifetime_ref.ident.span);
self.map.defs.insert(lifetime_ref.hir_id, def);
}
@ -1839,7 +1842,7 @@ fn is_late_bound_map(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<&FxIndexSet<
}
fn visit_lifetime(&mut self, lifetime_ref: &'v hir::Lifetime) {
if let hir::LifetimeName::Param(def_id, _) = lifetime_ref.name {
if let hir::LifetimeName::Param(def_id) = lifetime_ref.res {
self.regions.insert(def_id);
}
}
@ -1852,7 +1855,7 @@ fn is_late_bound_map(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<&FxIndexSet<
impl<'v> Visitor<'v> for AllCollector {
fn visit_lifetime(&mut self, lifetime_ref: &'v hir::Lifetime) {
if let hir::LifetimeName::Param(def_id, _) = lifetime_ref.name {
if let hir::LifetimeName::Param(def_id) = lifetime_ref.res {
self.regions.insert(def_id);
}
}

View File

@ -229,7 +229,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP
predicates.extend(region_pred.bounds.iter().map(|bound| {
let (r2, span) = match bound {
hir::GenericBound::Outlives(lt) => {
(<dyn AstConv<'_>>::ast_region_to_region(&icx, lt, None), lt.span)
(<dyn AstConv<'_>>::ast_region_to_region(&icx, lt, None), lt.ident.span)
}
_ => bug!(),
};

View File

@ -2159,7 +2159,7 @@ impl<'a> State<'a> {
}
pub fn print_lifetime(&mut self, lifetime: &hir::Lifetime) {
self.print_ident(lifetime.name.ident())
self.print_ident(lifetime.ident)
}
pub fn print_where_clause(&mut self, generics: &hir::Generics<'_>) {

View File

@ -375,7 +375,7 @@ impl AddToDiagnostic for AddLifetimeParamsSuggestion<'_> {
return false;
};
if !lifetime_sub.name.is_anonymous() || !lifetime_sup.name.is_anonymous() {
if !lifetime_sub.is_anonymous() || !lifetime_sup.is_anonymous() {
return false;
};
@ -407,20 +407,20 @@ impl AddToDiagnostic for AddLifetimeParamsSuggestion<'_> {
let suggestion_param_name =
suggestion_param_name.map(|n| n.to_string()).unwrap_or_else(|| "'a".to_owned());
debug!(?lifetime_sup.span);
debug!(?lifetime_sub.span);
let make_suggestion = |span: rustc_span::Span| {
if span.is_empty() {
(span, format!("{}, ", suggestion_param_name))
} else if let Ok("&") = self.tcx.sess.source_map().span_to_snippet(span).as_deref()
{
(span.shrink_to_hi(), format!("{} ", suggestion_param_name))
debug!(?lifetime_sup.ident.span);
debug!(?lifetime_sub.ident.span);
let make_suggestion = |ident: Ident| {
let sugg = if ident.name == kw::Empty {
format!("{}, ", suggestion_param_name)
} else if ident.name == kw::UnderscoreLifetime && ident.span.is_empty() {
format!("{} ", suggestion_param_name)
} else {
(span, suggestion_param_name.clone())
}
suggestion_param_name.clone()
};
(ident.span, sugg)
};
let mut suggestions =
vec![make_suggestion(lifetime_sub.span), make_suggestion(lifetime_sup.span)];
vec![make_suggestion(lifetime_sub.ident), make_suggestion(lifetime_sup.ident)];
if introduce_new {
let new_param_suggestion = if let Some(first) =

View File

@ -314,10 +314,10 @@ pub fn suggest_new_region_bound(
.iter()
.filter_map(|arg| match arg {
GenericBound::Outlives(Lifetime {
name: LifetimeName::Static,
span,
res: LifetimeName::Static,
ident,
..
}) => Some(*span),
}) => Some(ident.span),
_ => None,
})
.next()
@ -342,10 +342,10 @@ pub fn suggest_new_region_bound(
.bounds
.iter()
.filter_map(|arg| match arg {
GenericBound::Outlives(Lifetime { name, span, .. })
if name.ident().to_string() == lifetime_name =>
GenericBound::Outlives(Lifetime { ident, .. })
if ident.name.to_string() == lifetime_name =>
{
Some(*span)
Some(ident.span)
}
_ => None,
})
@ -361,8 +361,8 @@ pub fn suggest_new_region_bound(
);
}
}
TyKind::TraitObject(_, lt, _) => match lt.name {
LifetimeName::ImplicitObjectLifetimeDefault => {
TyKind::TraitObject(_, lt, _) => {
if let LifetimeName::ImplicitObjectLifetimeDefault = lt.res {
err.span_suggestion_verbose(
fn_return.span.shrink_to_hi(),
&format!(
@ -374,15 +374,14 @@ pub fn suggest_new_region_bound(
&plus_lt,
Applicability::MaybeIncorrect,
);
}
name if name.ident().to_string() != lifetime_name => {
} else if lt.ident.name.to_string() != lifetime_name {
// With this check we avoid suggesting redundant bounds. This
// would happen if there are nested impl/dyn traits and only
// one of them has the bound we'd suggest already there, like
// in `impl Foo<X = dyn Bar> + '_`.
if let Some(explicit_static) = &explicit_static {
err.span_suggestion_verbose(
lt.span,
lt.ident.span,
&format!("{} the trait object's {}", consider, explicit_static),
&lifetime_name,
Applicability::MaybeIncorrect,
@ -397,8 +396,7 @@ pub fn suggest_new_region_bound(
);
}
}
_ => {}
},
}
_ => {}
}
}
@ -561,7 +559,7 @@ impl<'a, 'tcx> Visitor<'tcx> for HirTraitObjectVisitor<'a> {
fn visit_ty(&mut self, t: &'tcx hir::Ty<'tcx>) {
if let TyKind::TraitObject(
poly_trait_refs,
Lifetime { name: LifetimeName::ImplicitObjectLifetimeDefault, .. },
Lifetime { res: LifetimeName::ImplicitObjectLifetimeDefault, .. },
_,
) = t.kind
{

View File

@ -272,11 +272,7 @@ fn gen_args(segment: &PathSegment<'_>) -> String {
.args
.iter()
.filter_map(|arg| {
if let GenericArg::Lifetime(lt) = arg {
Some(lt.name.ident().to_string())
} else {
None
}
if let GenericArg::Lifetime(lt) = arg { Some(lt.ident.to_string()) } else { None }
})
.collect::<Vec<_>>();

View File

@ -78,7 +78,7 @@ fn gen_args(cx: &LateContext<'_>, segment: &PathSegment<'_>) -> String {
.args
.iter()
.map(|arg| match arg {
GenericArg::Lifetime(lt) => lt.name.ident().to_string(),
GenericArg::Lifetime(lt) => lt.ident.to_string(),
GenericArg::Type(ty) => {
cx.tcx.sess.source_map().span_to_snippet(ty.span).unwrap_or_else(|_| "_".into())
}

View File

@ -1058,7 +1058,7 @@ impl<'hir> Map<'hir> {
Node::Arm(arm) => arm.span,
Node::Block(block) => block.span,
Node::Ctor(..) => self.span_with_body(self.get_parent_node(hir_id)),
Node::Lifetime(lifetime) => lifetime.span,
Node::Lifetime(lifetime) => lifetime.ident.span,
Node::GenericParam(param) => param.span,
Node::Infer(i) => i.span,
Node::Local(local) => local.span,

View File

@ -397,7 +397,7 @@ impl<'v> hir::intravisit::Visitor<'v> for TraitObjectVisitor<'v> {
hir::TyKind::TraitObject(
_,
hir::Lifetime {
name:
res:
hir::LifetimeName::ImplicitObjectLifetimeDefault | hir::LifetimeName::Static,
..
},
@ -421,10 +421,9 @@ pub struct StaticLifetimeVisitor<'tcx>(pub Vec<Span>, pub crate::hir::map::Map<'
impl<'v> hir::intravisit::Visitor<'v> for StaticLifetimeVisitor<'v> {
fn visit_lifetime(&mut self, lt: &'v hir::Lifetime) {
if let hir::LifetimeName::ImplicitObjectLifetimeDefault | hir::LifetimeName::Static =
lt.name
if let hir::LifetimeName::ImplicitObjectLifetimeDefault | hir::LifetimeName::Static = lt.res
{
self.0.push(lt.span);
self.0.push(lt.ident.span);
}
}
}

View File

@ -167,7 +167,7 @@ impl<'hir> Sig for hir::Ty<'hir> {
}
hir::TyKind::Rptr(ref lifetime, ref mt) => {
let mut prefix = "&".to_owned();
prefix.push_str(&lifetime.name.ident().to_string());
prefix.push_str(&lifetime.ident.to_string());
prefix.push(' ');
if let hir::Mutability::Mut = mt.mutbl {
prefix.push_str("mut ");

View File

@ -208,7 +208,7 @@ fn clean_lifetime<'tcx>(lifetime: &hir::Lifetime, cx: &mut DocContext<'tcx>) ->
return lt;
}
}
Lifetime(lifetime.name.ident().name)
Lifetime(lifetime.ident.name)
}
pub(crate) fn clean_const<'tcx>(constant: &hir::ConstArg, cx: &mut DocContext<'tcx>) -> Constant {
@ -1524,16 +1524,7 @@ pub(crate) fn clean_ty<'tcx>(ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> T
TyKind::Never => Primitive(PrimitiveType::Never),
TyKind::Ptr(ref m) => RawPointer(m.mutbl, Box::new(clean_ty(m.ty, cx))),
TyKind::Rptr(ref l, ref m) => {
// There are two times a `Fresh` lifetime can be created:
// 1. For `&'_ x`, written by the user. This corresponds to `lower_lifetime` in `rustc_ast_lowering`.
// 2. For `&x` as a parameter to an `async fn`. This corresponds to `elided_ref_lifetime in `rustc_ast_lowering`.
// See #59286 for more information.
// Ideally we would only hide the `'_` for case 2., but I don't know a way to distinguish it.
// Turning `fn f(&'_ self)` into `fn f(&self)` isn't the worst thing in the world, though;
// there's no case where it could cause the function to fail to compile.
let elided =
l.is_elided() || matches!(l.name, LifetimeName::Param(_, ParamName::Fresh));
let lifetime = if elided { None } else { Some(clean_lifetime(*l, cx)) };
let lifetime = if l.is_anonymous() { None } else { Some(clean_lifetime(*l, cx)) };
BorrowedRef { lifetime, mutability: m.mutbl, type_: Box::new(clean_ty(m.ty, cx)) }
}
TyKind::Slice(ty) => Slice(Box::new(clean_ty(ty, cx))),

View File

@ -119,7 +119,7 @@ hir-stats HIR STATS
hir-stats Name Accumulated Size Count Item Size
hir-stats ----------------------------------------------------------------
hir-stats ForeignItemRef 24 ( 0.3%) 1 24
hir-stats Lifetime 32 ( 0.3%) 1 32
hir-stats Lifetime 24 ( 0.3%) 1 24
hir-stats Mod 32 ( 0.3%) 1 32
hir-stats ExprField 40 ( 0.4%) 1 40
hir-stats TraitItemRef 56 ( 0.6%) 2 28
@ -152,7 +152,7 @@ hir-stats - Struct 72 ( 0.8%) 1
hir-stats - Binding 216 ( 2.4%) 3
hir-stats GenericParam 400 ( 4.4%) 5 80
hir-stats Generics 560 ( 6.1%) 10 56
hir-stats Ty 720 ( 7.8%) 15 48
hir-stats Ty 720 ( 7.9%) 15 48
hir-stats - Ptr 48 ( 0.5%) 1
hir-stats - Rptr 48 ( 0.5%) 1
hir-stats - Path 624 ( 6.8%) 13
@ -171,8 +171,8 @@ hir-stats - ForeignMod 80 ( 0.9%) 1
hir-stats - Impl 80 ( 0.9%) 1
hir-stats - Fn 160 ( 1.7%) 2
hir-stats - Use 400 ( 4.4%) 5
hir-stats Path 1_280 (13.9%) 32 40
hir-stats Path 1_280 (14.0%) 32 40
hir-stats PathSegment 1_920 (20.9%) 40 48
hir-stats ----------------------------------------------------------------
hir-stats Total 9_176
hir-stats Total 9_168
hir-stats

View File

@ -10,7 +10,7 @@ use rustc_hir::lang_items;
use rustc_hir::FnRetTy::Return;
use rustc_hir::{
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, PolyTraitRef, PredicateOrigin, TraitFn, TraitItem,
TraitItemKind, Ty, TyKind, WherePredicate,
};
use rustc_lint::{LateContext, LateLintPass};
@ -180,7 +180,7 @@ fn check_fn_inner<'tcx>(
_ => None,
});
for bound in lifetimes {
if bound.name != LifetimeName::Static && !bound.is_elided() {
if !bound.is_static() && !bound.is_elided() {
return;
}
}
@ -414,17 +414,13 @@ impl<'a, 'tcx> RefVisitor<'a, 'tcx> {
fn record(&mut self, lifetime: &Option<Lifetime>) {
if let Some(ref lt) = *lifetime {
if lt.name == LifetimeName::Static {
if lt.is_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.
self.lts.push(RefLt::Unnamed);
} else if lt.is_elided() {
self.lts.push(RefLt::Unnamed);
} else if let LifetimeName::Param(def_id, _) = lt.name {
} else if let LifetimeName::Param(def_id) = lt.res {
self.lts.push(RefLt::Named(def_id));
} else {
self.lts.push(RefLt::Unnamed);
}
} else {
self.lts.push(RefLt::Unnamed);
@ -472,7 +468,7 @@ impl<'a, 'tcx> Visitor<'tcx> for RefVisitor<'a, 'tcx> {
walk_item(self, item);
self.lts.truncate(len);
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)
} else {
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>) {
if let GenericArg::Lifetime(l) = generic_arg
&& let LifetimeName::Param(def_id, _) = l.name
{
self.lifetime_generic_arg_spans.entry(def_id).or_insert(l.span);
if let GenericArg::Lifetime(l) = generic_arg && let LifetimeName::Param(def_id) = l.res {
self.lifetime_generic_arg_spans.entry(def_id).or_insert(l.ident.span);
}
// Replace with `walk_generic_arg` if/when https://github.com/rust-lang/rust/pull/103692 lands.
// walk_generic_arg(self, generic_arg);
@ -577,7 +571,7 @@ where
// for lifetimes as parameters of generics
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<'_>) {
@ -653,7 +647,7 @@ struct BodyLifetimeChecker {
impl<'tcx> Visitor<'tcx> for BodyLifetimeChecker {
// for lifetimes as parameters of generics
fn visit_lifetime(&mut self, lifetime: &'tcx Lifetime) {
if lifetime.name.ident().name != kw::UnderscoreLifetime && lifetime.name.ident().name != kw::StaticLifetime {
if lifetime.ident.name != kw::UnderscoreLifetime && lifetime.ident.name != kw::StaticLifetime {
self.lifetimes_used_in_body = true;
}
}

View File

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

View File

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

View File

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

View File

@ -7,7 +7,7 @@ use rustc_hir::def::Res;
use rustc_hir::HirIdMap;
use rustc_hir::{
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,
};
use rustc_lexer::{tokenize, TokenKind};
@ -337,7 +337,7 @@ impl HirEqInterExpr<'_, '_, '_> {
}
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 {
@ -925,16 +925,10 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
}
pub fn hash_lifetime(&mut self, lifetime: &Lifetime) {
std::mem::discriminant(&lifetime.name).hash(&mut self.s);
if let LifetimeName::Param(param_id, ref name) = lifetime.name {
std::mem::discriminant(name).hash(&mut self.s);
lifetime.ident.name.hash(&mut self.s);
std::mem::discriminant(&lifetime.res).hash(&mut self.s);
if let LifetimeName::Param(param_id) = lifetime.res {
param_id.hash(&mut self.s);
match name {
ParamName::Plain(ref ident) => {
ident.name.hash(&mut self.s);
},
ParamName::Fresh | ParamName::Error => {},
}
}
}