Skip to content

Commit b30faaa

Browse files
committed
Extend HIR to track the source and syntax of a lifetime
An upcoming lint will want to be able to know if a lifetime is hidden (e.g. `&u8`, `ContainsLifetime`) or anonymous: (e.g. `&'_ u8`, `ContainsLifetime<'_>`). It will also want to know if the lifetime is related to a reference (`&u8`) or a path (`ContainsLifetime`).
1 parent ffd2a7d commit b30faaa

File tree

6 files changed

+205
-108
lines changed

6 files changed

+205
-108
lines changed

compiler/rustc_ast_lowering/src/item.rs

+8-3
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use rustc_ast::*;
55
use rustc_errors::ErrorGuaranteed;
66
use rustc_hir::def::{DefKind, Res};
77
use rustc_hir::def_id::{CRATE_DEF_ID, LocalDefId};
8-
use rustc_hir::{self as hir, HirId, IsAnonInPath, PredicateOrigin};
8+
use rustc_hir::{self as hir, HirId, LifetimeSource, PredicateOrigin};
99
use rustc_index::{IndexSlice, IndexVec};
1010
use rustc_middle::ty::{ResolverAstLowering, TyCtxt};
1111
use rustc_span::edit_distance::find_best_match_for_name;
@@ -1864,7 +1864,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
18641864
}
18651865
GenericParamKind::Lifetime => {
18661866
let lt_id = self.next_node_id();
1867-
let lifetime = self.new_named_lifetime(id, lt_id, ident, IsAnonInPath::No);
1867+
let lifetime =
1868+
self.new_named_lifetime(id, lt_id, ident, LifetimeSource::Other, ident.into());
18681869
hir::WherePredicateKind::RegionPredicate(hir::WhereRegionPredicate {
18691870
lifetime,
18701871
bounds,
@@ -1897,7 +1898,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
18971898
}),
18981899
WherePredicateKind::RegionPredicate(WhereRegionPredicate { lifetime, bounds }) => {
18991900
hir::WherePredicateKind::RegionPredicate(hir::WhereRegionPredicate {
1900-
lifetime: self.lower_lifetime(lifetime),
1901+
lifetime: self.lower_lifetime(
1902+
lifetime,
1903+
LifetimeSource::Other,
1904+
lifetime.ident.into(),
1905+
),
19011906
bounds: self.lower_param_bounds(
19021907
bounds,
19031908
ImplTraitContext::Disallowed(ImplTraitPosition::Bound),

compiler/rustc_ast_lowering/src/lib.rs

+73-48
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,8 @@ use rustc_errors::{DiagArgFromDisplay, DiagCtxtHandle, StashKey};
5555
use rustc_hir::def::{DefKind, LifetimeRes, Namespace, PartialRes, PerNS, Res};
5656
use rustc_hir::def_id::{CRATE_DEF_ID, LOCAL_CRATE, LocalDefId};
5757
use rustc_hir::{
58-
self as hir, ConstArg, GenericArg, HirId, IsAnonInPath, ItemLocalMap, LangItem, ParamName,
59-
TraitCandidate,
58+
self as hir, ConstArg, GenericArg, HirId, ItemLocalMap, LangItem, LifetimeSource,
59+
LifetimeSyntax, ParamName, TraitCandidate,
6060
};
6161
use rustc_index::{Idx, IndexSlice, IndexVec};
6262
use rustc_macros::extension;
@@ -1080,7 +1080,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
10801080
itctx: ImplTraitContext,
10811081
) -> hir::GenericArg<'hir> {
10821082
match arg {
1083-
ast::GenericArg::Lifetime(lt) => GenericArg::Lifetime(self.lower_lifetime(lt)),
1083+
ast::GenericArg::Lifetime(lt) => GenericArg::Lifetime(self.lower_lifetime(
1084+
lt,
1085+
LifetimeSource::Path { with_angle_brackets: true },
1086+
lt.ident.into(),
1087+
)),
10841088
ast::GenericArg::Type(ty) => {
10851089
// We cannot just match on `TyKind::Infer` as `(_)` is represented as
10861090
// `TyKind::Paren(TyKind::Infer)` and should also be lowered to `GenericArg::Infer`
@@ -1199,35 +1203,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
11991203
TyKind::Slice(ty) => hir::TyKind::Slice(self.lower_ty(ty, itctx)),
12001204
TyKind::Ptr(mt) => hir::TyKind::Ptr(self.lower_mt(mt, itctx)),
12011205
TyKind::Ref(region, mt) => {
1202-
let region = region.unwrap_or_else(|| {
1203-
let id = if let Some(LifetimeRes::ElidedAnchor { start, end }) =
1204-
self.resolver.get_lifetime_res(t.id)
1205-
{
1206-
debug_assert_eq!(start.plus(1), end);
1207-
start
1208-
} else {
1209-
self.next_node_id()
1210-
};
1211-
let span = self.tcx.sess.source_map().start_point(t.span).shrink_to_hi();
1212-
Lifetime { ident: Ident::new(kw::UnderscoreLifetime, span), id }
1213-
});
1214-
let lifetime = self.lower_lifetime(&region);
1206+
let lifetime = self.lower_ty_direct_lifetime(t, *region);
12151207
hir::TyKind::Ref(lifetime, self.lower_mt(mt, itctx))
12161208
}
12171209
TyKind::PinnedRef(region, mt) => {
1218-
let region = region.unwrap_or_else(|| {
1219-
let id = if let Some(LifetimeRes::ElidedAnchor { start, end }) =
1220-
self.resolver.get_lifetime_res(t.id)
1221-
{
1222-
debug_assert_eq!(start.plus(1), end);
1223-
start
1224-
} else {
1225-
self.next_node_id()
1226-
};
1227-
let span = self.tcx.sess.source_map().start_point(t.span).shrink_to_hi();
1228-
Lifetime { ident: Ident::new(kw::UnderscoreLifetime, span), id }
1229-
});
1230-
let lifetime = self.lower_lifetime(&region);
1210+
let lifetime = self.lower_ty_direct_lifetime(t, *region);
12311211
let kind = hir::TyKind::Ref(lifetime, self.lower_mt(mt, itctx));
12321212
let span = self.lower_span(t.span);
12331213
let arg = hir::Ty { kind, span, hir_id: self.next_id() };
@@ -1303,7 +1283,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
13031283
}
13041284
GenericBound::Outlives(lifetime) => {
13051285
if lifetime_bound.is_none() {
1306-
lifetime_bound = Some(this.lower_lifetime(lifetime));
1286+
lifetime_bound = Some(this.lower_lifetime(
1287+
lifetime,
1288+
LifetimeSource::Other,
1289+
lifetime.ident.into(),
1290+
));
13071291
}
13081292
None
13091293
}
@@ -1394,6 +1378,31 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
13941378
hir::Ty { kind, span: self.lower_span(t.span), hir_id: self.lower_node_id(t.id) }
13951379
}
13961380

1381+
fn lower_ty_direct_lifetime(
1382+
&mut self,
1383+
t: &Ty,
1384+
region: Option<Lifetime>,
1385+
) -> &'hir hir::Lifetime {
1386+
let (region, syntax) = match region {
1387+
Some(region) => (region, region.ident.into()),
1388+
1389+
None => {
1390+
let id = if let Some(LifetimeRes::ElidedAnchor { start, end }) =
1391+
self.resolver.get_lifetime_res(t.id)
1392+
{
1393+
debug_assert_eq!(start.plus(1), end);
1394+
start
1395+
} else {
1396+
self.next_node_id()
1397+
};
1398+
let span = self.tcx.sess.source_map().start_point(t.span).shrink_to_hi();
1399+
let region = Lifetime { ident: Ident::new(kw::UnderscoreLifetime, span), id };
1400+
(region, LifetimeSyntax::Hidden)
1401+
}
1402+
};
1403+
self.lower_lifetime(&region, LifetimeSource::Reference, syntax)
1404+
}
1405+
13971406
/// Lowers a `ReturnPositionOpaqueTy` (`-> impl Trait`) or a `TypeAliasesOpaqueTy` (`type F =
13981407
/// impl Trait`): this creates the associated Opaque Type (TAIT) definition and then returns a
13991408
/// HIR type that references the TAIT.
@@ -1475,9 +1484,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
14751484
precise_capturing_args: &[PreciseCapturingArg],
14761485
) -> &'hir [hir::PreciseCapturingArg<'hir>] {
14771486
self.arena.alloc_from_iter(precise_capturing_args.iter().map(|arg| match arg {
1478-
PreciseCapturingArg::Lifetime(lt) => {
1479-
hir::PreciseCapturingArg::Lifetime(self.lower_lifetime(lt))
1480-
}
1487+
PreciseCapturingArg::Lifetime(lt) => hir::PreciseCapturingArg::Lifetime(
1488+
self.lower_lifetime(lt, LifetimeSource::PreciseCapturing, lt.ident.into()),
1489+
),
14811490
PreciseCapturingArg::Arg(path, id) => {
14821491
let [segment] = path.segments.as_slice() else {
14831492
panic!();
@@ -1745,22 +1754,40 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
17451754
) -> hir::GenericBound<'hir> {
17461755
match tpb {
17471756
GenericBound::Trait(p) => hir::GenericBound::Trait(self.lower_poly_trait_ref(p, itctx)),
1748-
GenericBound::Outlives(lifetime) => {
1749-
hir::GenericBound::Outlives(self.lower_lifetime(lifetime))
1750-
}
1757+
GenericBound::Outlives(lifetime) => hir::GenericBound::Outlives(self.lower_lifetime(
1758+
lifetime,
1759+
LifetimeSource::OutlivesBound,
1760+
lifetime.ident.into(),
1761+
)),
17511762
GenericBound::Use(args, span) => hir::GenericBound::Use(
17521763
self.lower_precise_capturing_args(args),
17531764
self.lower_span(*span),
17541765
),
17551766
}
17561767
}
17571768

1758-
fn lower_lifetime(&mut self, l: &Lifetime) -> &'hir hir::Lifetime {
1759-
self.new_named_lifetime(l.id, l.id, l.ident, IsAnonInPath::No)
1769+
fn lower_lifetime(
1770+
&mut self,
1771+
l: &Lifetime,
1772+
source: LifetimeSource,
1773+
syntax: LifetimeSyntax,
1774+
) -> &'hir hir::Lifetime {
1775+
self.new_named_lifetime(l.id, l.id, l.ident, source, syntax)
17601776
}
17611777

1762-
fn lower_lifetime_anon_in_path(&mut self, id: NodeId, span: Span) -> &'hir hir::Lifetime {
1763-
self.new_named_lifetime(id, id, Ident::new(kw::UnderscoreLifetime, span), IsAnonInPath::Yes)
1778+
fn lower_lifetime_hidden_in_path(
1779+
&mut self,
1780+
id: NodeId,
1781+
span: Span,
1782+
with_angle_brackets: bool,
1783+
) -> &'hir hir::Lifetime {
1784+
self.new_named_lifetime(
1785+
id,
1786+
id,
1787+
Ident::new(kw::UnderscoreLifetime, span),
1788+
LifetimeSource::Path { with_angle_brackets },
1789+
LifetimeSyntax::Hidden,
1790+
)
17641791
}
17651792

17661793
#[instrument(level = "debug", skip(self))]
@@ -1769,7 +1796,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
17691796
id: NodeId,
17701797
new_id: NodeId,
17711798
ident: Ident,
1772-
is_anon_in_path: IsAnonInPath,
1799+
source: LifetimeSource,
1800+
syntax: LifetimeSyntax,
17731801
) -> &'hir hir::Lifetime {
17741802
debug_assert_ne!(ident.name, kw::Empty);
17751803
let res = self.resolver.get_lifetime_res(id).unwrap_or(LifetimeRes::Error);
@@ -1794,17 +1822,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
17941822
}
17951823
};
17961824

1797-
#[cfg(debug_assertions)]
1798-
if is_anon_in_path == IsAnonInPath::Yes {
1799-
debug_assert_eq!(ident.name, kw::UnderscoreLifetime);
1800-
}
1801-
18021825
debug!(?res);
18031826
self.arena.alloc(hir::Lifetime::new(
18041827
self.lower_node_id(new_id),
18051828
self.lower_ident(ident),
18061829
res,
1807-
is_anon_in_path,
1830+
source,
1831+
syntax,
18081832
))
18091833
}
18101834

@@ -2393,7 +2417,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
23932417
self.next_id(),
23942418
Ident::new(kw::UnderscoreLifetime, self.lower_span(span)),
23952419
hir::LifetimeName::ImplicitObjectLifetimeDefault,
2396-
IsAnonInPath::No,
2420+
LifetimeSource::Other,
2421+
LifetimeSyntax::Hidden,
23972422
);
23982423
debug!("elided_dyn_bound: r={:?}", r);
23992424
self.arena.alloc(r)

compiler/rustc_ast_lowering/src/path.rs

+11-7
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
use std::sync::Arc;
22

33
use rustc_ast::{self as ast, *};
4-
use rustc_hir as hir;
5-
use rustc_hir::GenericArg;
64
use rustc_hir::def::{DefKind, PartialRes, Res};
75
use rustc_hir::def_id::DefId;
6+
use rustc_hir::{self as hir, GenericArg};
87
use rustc_middle::span_bug;
98
use rustc_session::parse::add_feature_diagnostics;
109
use rustc_span::{BytePos, DUMMY_SP, DesugaringKind, Ident, Span, Symbol, sym};
@@ -433,24 +432,29 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
433432

434433
// Note: these spans are used for diagnostics when they can't be inferred.
435434
// See rustc_resolve::late::lifetimes::LifetimeContext::add_missing_lifetime_specifiers_label
436-
let elided_lifetime_span = if generic_args.span.is_empty() {
435+
let (elided_lifetime_span, with_angle_brackets) = if generic_args.span.is_empty() {
437436
// If there are no brackets, use the identifier span.
438437
// HACK: we use find_ancestor_inside to properly suggest elided spans in paths
439438
// originating from macros, since the segment's span might be from a macro arg.
440-
segment_ident_span.find_ancestor_inside(path_span).unwrap_or(path_span)
439+
(segment_ident_span.find_ancestor_inside(path_span).unwrap_or(path_span), false)
441440
} else if generic_args.is_empty() {
442441
// If there are brackets, but not generic arguments, then use the opening bracket
443-
generic_args.span.with_hi(generic_args.span.lo() + BytePos(1))
442+
(generic_args.span.with_hi(generic_args.span.lo() + BytePos(1)), true)
444443
} else {
445444
// Else use an empty span right after the opening bracket.
446-
generic_args.span.with_lo(generic_args.span.lo() + BytePos(1)).shrink_to_lo()
445+
(generic_args.span.with_lo(generic_args.span.lo() + BytePos(1)).shrink_to_lo(), true)
447446
};
448447

449448
generic_args.args.insert_many(
450449
0,
451450
(start.as_u32()..end.as_u32()).map(|i| {
452451
let id = NodeId::from_u32(i);
453-
let l = self.lower_lifetime_anon_in_path(id, elided_lifetime_span);
452+
453+
let l = self.lower_lifetime_hidden_in_path(
454+
id,
455+
elided_lifetime_span,
456+
with_angle_brackets,
457+
);
454458
GenericArg::Lifetime(l)
455459
}),
456460
);

0 commit comments

Comments
 (0)