diff options
| author | Nicholas Nethercote <n.nethercote@gmail.com> | 2025-03-25 08:21:28 +1100 |
|---|---|---|
| committer | Nicholas Nethercote <n.nethercote@gmail.com> | 2025-03-28 10:15:23 +1100 |
| commit | 8d2c63f514a74752a3186b0bf3e8f3aef57dc12e (patch) | |
| tree | 887b83d34fc08db03dd8b3c09fc80183a15734b5 /compiler/rustc_ast_lowering/src | |
| parent | cfd00f9c16d9b3ab98d6e06125c6baa83dfa4a03 (diff) | |
| download | rust-8d2c63f514a74752a3186b0bf3e8f3aef57dc12e.tar.gz rust-8d2c63f514a74752a3186b0bf3e8f3aef57dc12e.zip | |
Don't use `kw::Empty` in `hir::Lifetime::ident`.
`hir::Lifetime::ident` currently sometimes uses `kw::Empty` for elided lifetimes and sometimes uses `kw::UnderscoreLifetime`, and the distinction is used when creating some error suggestions, e.g. in `Lifetime::suggestion` and `ImplicitLifetimeFinder::visit_ty`. I found this *really* confusing, and it took me a while to understand what was going on. This commit replaces all uses of `kw::Empty` in `hir::Lifetime::ident` with `kw::UnderscoreLifetime`. It adds a new field `hir::Lifetime::is_path_anon` that mostly replaces the old empty/underscore distinction and makes things much clearer. Some other notable changes: - Adds a big comment to `Lifetime` talking about permissable field values. - Adds some assertions in `new_named_lifetime` about what ident values are permissible for the different `LifetimeRes` values. - Adds a `Lifetime::new` constructor that does some checking to make sure the `is_elided` and `is_anonymous` states are valid. - `add_static_impl_trait_suggestion` now looks at `Lifetime::res` instead of the ident when creating the suggestion. This is the one case where `is_path_anon` doesn't replace the old empty/underscore distinction. - A couple of minor pretty-printing improvements.
Diffstat (limited to 'compiler/rustc_ast_lowering/src')
| -rw-r--r-- | compiler/rustc_ast_lowering/src/item.rs | 4 | ||||
| -rw-r--r-- | compiler/rustc_ast_lowering/src/lib.rs | 47 | ||||
| -rw-r--r-- | compiler/rustc_ast_lowering/src/path.rs | 7 |
3 files changed, 38 insertions, 20 deletions
diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index c03d5e53d97..43bf951eddc 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -5,7 +5,7 @@ use rustc_ast::*; use rustc_errors::ErrorGuaranteed; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{CRATE_DEF_ID, LocalDefId}; -use rustc_hir::{self as hir, HirId, PredicateOrigin}; +use rustc_hir::{self as hir, HirId, IsAnonInPath, PredicateOrigin}; use rustc_index::{IndexSlice, IndexVec}; use rustc_middle::ty::{ResolverAstLowering, TyCtxt}; use rustc_span::edit_distance::find_best_match_for_name; @@ -1823,7 +1823,7 @@ impl<'hir> LoweringContext<'_, 'hir> { } GenericParamKind::Lifetime => { let lt_id = self.next_node_id(); - let lifetime = self.new_named_lifetime(id, lt_id, ident); + let lifetime = self.new_named_lifetime(id, lt_id, ident, IsAnonInPath::No); hir::WherePredicateKind::RegionPredicate(hir::WhereRegionPredicate { lifetime, bounds, diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index ced9064fd9f..d5d6dcd8d63 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -55,7 +55,8 @@ use rustc_errors::{DiagArgFromDisplay, DiagCtxtHandle, StashKey}; use rustc_hir::def::{DefKind, LifetimeRes, Namespace, PartialRes, PerNS, Res}; use rustc_hir::def_id::{CRATE_DEF_ID, LOCAL_CRATE, LocalDefId}; use rustc_hir::{ - self as hir, ConstArg, GenericArg, HirId, ItemLocalMap, LangItem, ParamName, TraitCandidate, + self as hir, ConstArg, GenericArg, HirId, IsAnonInPath, ItemLocalMap, LangItem, ParamName, + TraitCandidate, }; use rustc_index::{Idx, IndexSlice, IndexVec}; use rustc_macros::extension; @@ -1755,7 +1756,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } fn lower_lifetime(&mut self, l: &Lifetime) -> &'hir hir::Lifetime { - self.new_named_lifetime(l.id, l.id, l.ident) + self.new_named_lifetime(l.id, l.id, l.ident, IsAnonInPath::No) + } + + fn lower_lifetime_anon_in_path(&mut self, id: NodeId, span: Span) -> &'hir hir::Lifetime { + self.new_named_lifetime(id, id, Ident::new(kw::UnderscoreLifetime, span), IsAnonInPath::Yes) } #[instrument(level = "debug", skip(self))] @@ -1764,28 +1769,43 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { id: NodeId, new_id: NodeId, ident: Ident, + is_anon_in_path: IsAnonInPath, ) -> &'hir hir::Lifetime { + debug_assert_ne!(ident.name, kw::Empty); let res = self.resolver.get_lifetime_res(id).unwrap_or(LifetimeRes::Error); let res = match res { LifetimeRes::Param { param, .. } => 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) } - LifetimeRes::Infer => hir::LifetimeName::Infer, - LifetimeRes::Static { .. } => hir::LifetimeName::Static, + LifetimeRes::Infer => { + debug_assert_eq!(ident.name, kw::UnderscoreLifetime); + hir::LifetimeName::Infer + } + LifetimeRes::Static { .. } => { + debug_assert!(matches!(ident.name, kw::StaticLifetime | kw::UnderscoreLifetime)); + hir::LifetimeName::Static + } LifetimeRes::Error => hir::LifetimeName::Error, LifetimeRes::ElidedAnchor { .. } => { panic!("Unexpected `ElidedAnchar` {:?} at {:?}", ident, ident.span); } }; + #[cfg(debug_assertions)] + if is_anon_in_path == IsAnonInPath::Yes { + debug_assert_eq!(ident.name, kw::UnderscoreLifetime); + } + debug!(?res); - self.arena.alloc(hir::Lifetime { - hir_id: self.lower_node_id(new_id), - ident: self.lower_ident(ident), + self.arena.alloc(hir::Lifetime::new( + self.lower_node_id(new_id), + self.lower_ident(ident), res, - }) + is_anon_in_path, + )) } fn lower_generic_params_mut( @@ -2369,11 +2389,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { /// when the bound is written, even if it is written with `'_` like in /// `Box<dyn Debug + '_>`. In those cases, `lower_lifetime` is invoked. fn elided_dyn_bound(&mut self, span: Span) -> &'hir hir::Lifetime { - let r = hir::Lifetime { - hir_id: self.next_id(), - ident: Ident::new(kw::Empty, self.lower_span(span)), - res: hir::LifetimeName::ImplicitObjectLifetimeDefault, - }; + let r = hir::Lifetime::new( + self.next_id(), + Ident::new(kw::UnderscoreLifetime, self.lower_span(span)), + hir::LifetimeName::ImplicitObjectLifetimeDefault, + IsAnonInPath::No, + ); debug!("elided_dyn_bound: r={:?}", r); self.arena.alloc(r) } diff --git a/compiler/rustc_ast_lowering/src/path.rs b/compiler/rustc_ast_lowering/src/path.rs index d00c797755f..c464c159c34 100644 --- a/compiler/rustc_ast_lowering/src/path.rs +++ b/compiler/rustc_ast_lowering/src/path.rs @@ -7,7 +7,7 @@ use rustc_hir::def::{DefKind, PartialRes, Res}; use rustc_hir::def_id::DefId; use rustc_middle::span_bug; use rustc_session::parse::add_feature_diagnostics; -use rustc_span::{BytePos, DUMMY_SP, DesugaringKind, Ident, Span, Symbol, kw, sym}; +use rustc_span::{BytePos, DUMMY_SP, DesugaringKind, Ident, Span, Symbol, sym}; use smallvec::{SmallVec, smallvec}; use tracing::{debug, instrument}; @@ -450,10 +450,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { 0, (start.as_u32()..end.as_u32()).map(|i| { let id = NodeId::from_u32(i); - let l = self.lower_lifetime(&Lifetime { - id, - ident: Ident::new(kw::Empty, elided_lifetime_span), - }); + let l = self.lower_lifetime_anon_in_path(id, elided_lifetime_span); GenericArg::Lifetime(l) }), ); |
