Skip to content

Commit 88b8053

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 8bf5a8d commit 88b8053

File tree

6 files changed

+221
-110
lines changed

6 files changed

+221
-110
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;
@@ -1868,7 +1868,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
18681868
}
18691869
GenericParamKind::Lifetime => {
18701870
let lt_id = self.next_node_id();
1871-
let lifetime = self.new_named_lifetime(id, lt_id, ident, IsAnonInPath::No);
1871+
let lifetime =
1872+
self.new_named_lifetime(id, lt_id, ident, LifetimeSource::Other, ident.into());
18721873
hir::WherePredicateKind::RegionPredicate(hir::WhereRegionPredicate {
18731874
lifetime,
18741875
bounds,
@@ -1901,7 +1902,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
19011902
}),
19021903
WherePredicateKind::RegionPredicate(WhereRegionPredicate { lifetime, bounds }) => {
19031904
hir::WherePredicateKind::RegionPredicate(hir::WhereRegionPredicate {
1904-
lifetime: self.lower_lifetime(lifetime),
1905+
lifetime: self.lower_lifetime(
1906+
lifetime,
1907+
LifetimeSource::Other,
1908+
lifetime.ident.into(),
1909+
),
19051910
bounds: self.lower_param_bounds(
19061911
bounds,
19071912
ImplTraitContext::Disallowed(ImplTraitPosition::Bound),

compiler/rustc_ast_lowering/src/lib.rs

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

1380+
fn lower_ty_direct_lifetime(
1381+
&mut self,
1382+
t: &Ty,
1383+
region: Option<Lifetime>,
1384+
) -> &'hir hir::Lifetime {
1385+
let (region, syntax) = match region {
1386+
Some(region) => (region, region.ident.into()),
1387+
1388+
None => {
1389+
let id = if let Some(LifetimeRes::ElidedAnchor { start, end }) =
1390+
self.resolver.get_lifetime_res(t.id)
1391+
{
1392+
debug_assert_eq!(start.plus(1), end);
1393+
start
1394+
} else {
1395+
self.next_node_id()
1396+
};
1397+
let span = self.tcx.sess.source_map().start_point(t.span).shrink_to_hi();
1398+
let region = Lifetime { ident: Ident::new(kw::UnderscoreLifetime, span), id };
1399+
(region, LifetimeSyntax::Hidden)
1400+
}
1401+
};
1402+
self.lower_lifetime(&region, LifetimeSource::Reference, syntax)
1403+
}
1404+
13961405
/// Lowers a `ReturnPositionOpaqueTy` (`-> impl Trait`) or a `TypeAliasesOpaqueTy` (`type F =
13971406
/// impl Trait`): this creates the associated Opaque Type (TAIT) definition and then returns a
13981407
/// HIR type that references the TAIT.
@@ -1474,9 +1483,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
14741483
precise_capturing_args: &[PreciseCapturingArg],
14751484
) -> &'hir [hir::PreciseCapturingArg<'hir>] {
14761485
self.arena.alloc_from_iter(precise_capturing_args.iter().map(|arg| match arg {
1477-
PreciseCapturingArg::Lifetime(lt) => {
1478-
hir::PreciseCapturingArg::Lifetime(self.lower_lifetime(lt))
1479-
}
1486+
PreciseCapturingArg::Lifetime(lt) => hir::PreciseCapturingArg::Lifetime(
1487+
self.lower_lifetime(lt, LifetimeSource::PreciseCapturing, lt.ident.into()),
1488+
),
14801489
PreciseCapturingArg::Arg(path, id) => {
14811490
let [segment] = path.segments.as_slice() else {
14821491
panic!();
@@ -1739,22 +1748,40 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
17391748
) -> hir::GenericBound<'hir> {
17401749
match tpb {
17411750
GenericBound::Trait(p) => hir::GenericBound::Trait(self.lower_poly_trait_ref(p, itctx)),
1742-
GenericBound::Outlives(lifetime) => {
1743-
hir::GenericBound::Outlives(self.lower_lifetime(lifetime))
1744-
}
1751+
GenericBound::Outlives(lifetime) => hir::GenericBound::Outlives(self.lower_lifetime(
1752+
lifetime,
1753+
LifetimeSource::OutlivesBound,
1754+
lifetime.ident.into(),
1755+
)),
17451756
GenericBound::Use(args, span) => hir::GenericBound::Use(
17461757
self.lower_precise_capturing_args(args),
17471758
self.lower_span(*span),
17481759
),
17491760
}
17501761
}
17511762

1752-
fn lower_lifetime(&mut self, l: &Lifetime) -> &'hir hir::Lifetime {
1753-
self.new_named_lifetime(l.id, l.id, l.ident, IsAnonInPath::No)
1763+
fn lower_lifetime(
1764+
&mut self,
1765+
l: &Lifetime,
1766+
source: LifetimeSource,
1767+
syntax: LifetimeSyntax,
1768+
) -> &'hir hir::Lifetime {
1769+
self.new_named_lifetime(l.id, l.id, l.ident, source, syntax)
17541770
}
17551771

1756-
fn lower_lifetime_anon_in_path(&mut self, id: NodeId, span: Span) -> &'hir hir::Lifetime {
1757-
self.new_named_lifetime(id, id, Ident::new(kw::UnderscoreLifetime, span), IsAnonInPath::Yes)
1772+
fn lower_lifetime_hidden_in_path(
1773+
&mut self,
1774+
id: NodeId,
1775+
span: Span,
1776+
with_angle_brackets: bool,
1777+
) -> &'hir hir::Lifetime {
1778+
self.new_named_lifetime(
1779+
id,
1780+
id,
1781+
Ident::new(kw::UnderscoreLifetime, span),
1782+
LifetimeSource::Path { with_angle_brackets },
1783+
LifetimeSyntax::Hidden,
1784+
)
17581785
}
17591786

17601787
#[instrument(level = "debug", skip(self))]
@@ -1763,7 +1790,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
17631790
id: NodeId,
17641791
new_id: NodeId,
17651792
ident: Ident,
1766-
is_anon_in_path: IsAnonInPath,
1793+
source: LifetimeSource,
1794+
syntax: LifetimeSyntax,
17671795
) -> &'hir hir::Lifetime {
17681796
let res = self.resolver.get_lifetime_res(id).unwrap_or(LifetimeRes::Error);
17691797
let res = match res {
@@ -1787,17 +1815,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
17871815
}
17881816
};
17891817

1790-
#[cfg(debug_assertions)]
1791-
if is_anon_in_path == IsAnonInPath::Yes {
1792-
debug_assert_eq!(ident.name, kw::UnderscoreLifetime);
1793-
}
1794-
17951818
debug!(?res);
17961819
self.arena.alloc(hir::Lifetime::new(
17971820
self.lower_node_id(new_id),
17981821
self.lower_ident(ident),
17991822
res,
1800-
is_anon_in_path,
1823+
source,
1824+
syntax,
18011825
))
18021826
}
18031827

@@ -2389,7 +2413,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
23892413
self.next_id(),
23902414
Ident::new(kw::UnderscoreLifetime, self.lower_span(span)),
23912415
hir::LifetimeKind::ImplicitObjectLifetimeDefault,
2392-
IsAnonInPath::No,
2416+
LifetimeSource::Other,
2417+
LifetimeSyntax::Hidden,
23932418
);
23942419
debug!("elided_dyn_bound: r={:?}", r);
23952420
self.arena.alloc(r)

compiler/rustc_ast_lowering/src/path.rs

+10-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,23 +432,27 @@ 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..end).map(|id| {
452-
let l = self.lower_lifetime_anon_in_path(id, elided_lifetime_span);
451+
let l = self.lower_lifetime_hidden_in_path(
452+
id,
453+
elided_lifetime_span,
454+
with_angle_brackets,
455+
);
453456
GenericArg::Lifetime(l)
454457
}),
455458
);

0 commit comments

Comments
 (0)