Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 21b6d23

Browse files
committedApr 27, 2022
Collect extra lifetime parameters during late resolution.
1 parent b590e30 commit 21b6d23

File tree

4 files changed

+138
-222
lines changed

4 files changed

+138
-222
lines changed
 

‎compiler/rustc_ast_lowering/src/item.rs

Lines changed: 22 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -84,9 +84,6 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> {
8484
generator_kind: None,
8585
task_context: None,
8686
current_item: None,
87-
lifetimes_to_define: Default::default(),
88-
is_collecting_anonymous_lifetimes: None,
89-
in_scope_lifetimes: Vec::new(),
9087
captured_lifetimes: None,
9188
allow_try_trait: Some([sym::try_trait_v2][..].into()),
9289
allow_gen_future: Some([sym::gen_future][..].into()),
@@ -149,36 +146,8 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> {
149146
// This is used to track which lifetimes have already been defined,
150147
// and which need to be replicated when lowering an async fn.
151148
match parent_hir.node().expect_item().kind {
152-
hir::ItemKind::Impl(hir::Impl { ref of_trait, ref generics, .. }) => {
149+
hir::ItemKind::Impl(hir::Impl { ref of_trait, .. }) => {
153150
lctx.is_in_trait_impl = of_trait.is_some();
154-
lctx.in_scope_lifetimes = generics
155-
.params
156-
.iter()
157-
.filter(|param| {
158-
matches!(param.kind, hir::GenericParamKind::Lifetime { .. })
159-
})
160-
.map(|param| {
161-
let def_id =
162-
parent_hir.nodes.local_id_to_def_id[&param.hir_id.local_id];
163-
let name = param.name;
164-
(name, def_id)
165-
})
166-
.collect();
167-
}
168-
hir::ItemKind::Trait(_, _, ref generics, ..) => {
169-
lctx.in_scope_lifetimes = generics
170-
.params
171-
.iter()
172-
.filter(|param| {
173-
matches!(param.kind, hir::GenericParamKind::Lifetime { .. })
174-
})
175-
.map(|param| {
176-
let def_id =
177-
parent_hir.nodes.local_id_to_def_id[&param.hir_id.local_id];
178-
let name = param.name;
179-
(name, def_id)
180-
})
181-
.collect();
182151
}
183152
_ => {}
184153
};
@@ -286,7 +255,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
286255
ref body,
287256
..
288257
}) => {
289-
let fn_def_id = self.resolver.local_def_id(id);
290258
self.with_new_scopes(|this| {
291259
this.current_item = Some(ident.span);
292260

@@ -299,7 +267,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
299267
this.lower_maybe_async_body(span, &decl, asyncness, body.as_deref());
300268

301269
let (generics, decl) =
302-
this.add_implicit_generics(generics, fn_def_id, |this, idty| {
270+
this.add_implicit_generics(generics, id, |this, idty| {
303271
let ret_id = asyncness.opt_return_id();
304272
this.lower_fn_decl(&decl, Some((id, idty)), FnDeclKind::Fn, ret_id)
305273
});
@@ -415,9 +383,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
415383
// method, it will not be considered an in-band
416384
// lifetime to be added, but rather a reference to a
417385
// parent lifetime.
418-
let lowered_trait_def_id = hir_id.expect_owner();
419386
let (generics, (trait_ref, lowered_ty)) =
420-
self.add_implicit_generics(ast_generics, lowered_trait_def_id, |this, _| {
387+
self.add_implicit_generics(ast_generics, id, |this, _| {
421388
let trait_ref = trait_ref.as_ref().map(|trait_ref| {
422389
this.lower_trait_ref(
423390
trait_ref,
@@ -431,12 +398,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
431398
(trait_ref, lowered_ty)
432399
});
433400

434-
let new_impl_items =
435-
self.with_in_scope_lifetime_defs(&ast_generics.params, |this| {
436-
this.arena.alloc_from_iter(
437-
impl_items.iter().map(|item| this.lower_impl_item_ref(item)),
438-
)
439-
});
401+
let new_impl_items = self
402+
.arena
403+
.alloc_from_iter(impl_items.iter().map(|item| self.lower_impl_item_ref(item)));
440404

441405
// `defaultness.has_value()` is never called for an `impl`, always `true` in order
442406
// to not cause an assertion failure inside the `lower_defaultness` function.
@@ -743,7 +707,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
743707
ForeignItemKind::Fn(box Fn { ref sig, ref generics, .. }) => {
744708
let fdec = &sig.decl;
745709
let (generics, (fn_dec, fn_args)) =
746-
self.add_implicit_generics(generics, def_id, |this, _| {
710+
self.add_implicit_generics(generics, i.id, |this, _| {
747711
(
748712
// Disallow `impl Trait` in foreign items.
749713
this.lower_fn_decl(fdec, None, FnDeclKind::ExternFn, None),
@@ -1343,9 +1307,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
13431307
kind: FnDeclKind,
13441308
is_async: Option<NodeId>,
13451309
) -> (hir::Generics<'hir>, hir::FnSig<'hir>) {
1346-
let fn_def_id = self.resolver.local_def_id(id);
13471310
let header = self.lower_fn_header(sig.header);
1348-
let (generics, decl) = self.add_implicit_generics(generics, fn_def_id, |this, idty| {
1311+
let (generics, decl) = self.add_implicit_generics(generics, id, |this, idty| {
13491312
this.lower_fn_decl(&sig.decl, Some((id, idty)), kind, is_async)
13501313
});
13511314
(generics, hir::FnSig { header, decl, span: self.lower_span(sig.span) })
@@ -1487,24 +1450,20 @@ impl<'hir> LoweringContext<'_, 'hir> {
14871450
ref bounded_ty,
14881451
ref bounds,
14891452
span,
1490-
}) => self.with_in_scope_lifetime_defs(&bound_generic_params, |this| {
1491-
hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate {
1492-
bound_generic_params: this.lower_generic_params(
1493-
bound_generic_params,
1494-
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
1495-
),
1496-
bounded_ty: this.lower_ty(
1497-
bounded_ty,
1498-
ImplTraitContext::Disallowed(ImplTraitPosition::Type),
1499-
),
1500-
bounds: this.arena.alloc_from_iter(bounds.iter().map(|bound| {
1501-
this.lower_param_bound(
1502-
bound,
1503-
ImplTraitContext::Disallowed(ImplTraitPosition::Bound),
1504-
)
1505-
})),
1506-
span: this.lower_span(span),
1507-
})
1453+
}) => hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate {
1454+
bound_generic_params: self.lower_generic_params(
1455+
bound_generic_params,
1456+
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
1457+
),
1458+
bounded_ty: self
1459+
.lower_ty(bounded_ty, ImplTraitContext::Disallowed(ImplTraitPosition::Type)),
1460+
bounds: self.arena.alloc_from_iter(bounds.iter().map(|bound| {
1461+
self.lower_param_bound(
1462+
bound,
1463+
ImplTraitContext::Disallowed(ImplTraitPosition::Bound),
1464+
)
1465+
})),
1466+
span: self.lower_span(span),
15081467
}),
15091468
WherePredicate::RegionPredicate(WhereRegionPredicate {
15101469
ref lifetime,

‎compiler/rustc_ast_lowering/src/lib.rs

Lines changed: 72 additions & 150 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ use rustc_ast::{self as ast, *};
4545
use rustc_ast_pretty::pprust;
4646
use rustc_data_structures::captures::Captures;
4747
use rustc_data_structures::fingerprint::Fingerprint;
48-
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap};
48+
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
4949
use rustc_data_structures::sorted_map::SortedMap;
5050
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
5151
use rustc_data_structures::sync::Lrc;
@@ -122,20 +122,6 @@ struct LoweringContext<'a, 'hir: 'a> {
122122
is_in_trait_impl: bool,
123123
is_in_dyn_type: bool,
124124

125-
/// Used to create lifetime definitions for anonymous lifetimes.
126-
/// When an anonymous lifetime is encountered in a function or impl header and
127-
/// requires to create a fresh lifetime parameter, it is added
128-
/// to this list. The results of this list are then added to the list of
129-
/// lifetime definitions in the corresponding impl or function generics.
130-
lifetimes_to_define: FxIndexMap<NodeId, Span>,
131-
132-
/// If anonymous lifetimes are being collected, this field holds the parent
133-
/// `LocalDefId` to create the fresh lifetime parameters' `LocalDefId`.
134-
is_collecting_anonymous_lifetimes: Option<LocalDefId>,
135-
136-
/// Currently in-scope lifetimes defined in impl headers, fn headers, or HRTB.
137-
in_scope_lifetimes: Vec<(ParamName, LocalDefId)>,
138-
139125
/// Used to handle lifetimes appearing in impl-traits.
140126
captured_lifetimes: Option<LifetimeCaptureContext>,
141127

@@ -173,8 +159,6 @@ pub enum LifetimeRes {
173159
Fresh {
174160
/// Id of the generic parameter that introduced it.
175161
param: LocalDefId,
176-
/// Id to create the HirId. This is used when creating the `Fresh` lifetime parameters.
177-
introducer: Option<NodeId>,
178162
/// Id of the introducing place. See `Param`.
179163
binder: NodeId,
180164
},
@@ -237,6 +221,9 @@ pub trait ResolverAstLowering {
237221
/// Obtains resolution for a lifetime with the given `NodeId`.
238222
fn get_lifetime_res(&self, id: NodeId) -> Option<LifetimeRes>;
239223

224+
/// Obtain the list of lifetimes parameters to add to an item.
225+
fn take_extra_lifetime_params(&mut self, id: NodeId) -> Vec<(Ident, NodeId, LifetimeRes)>;
226+
240227
fn create_stable_hashing_context(&self) -> StableHashingContext<'_>;
241228

242229
fn definitions(&self) -> &Definitions;
@@ -694,46 +681,34 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
694681
}
695682

696683
/// Converts a lifetime into a new generic parameter.
697-
fn fresh_lifetime_to_generic_param(
684+
fn lifetime_res_to_generic_param(
698685
&mut self,
699-
span: Span,
686+
ident: Ident,
700687
node_id: NodeId,
701-
) -> hir::GenericParam<'hir> {
688+
res: LifetimeRes,
689+
) -> Option<hir::GenericParam<'hir>> {
690+
let (name, kind) = match res {
691+
LifetimeRes::Param { .. } => {
692+
(hir::ParamName::Plain(ident), hir::LifetimeParamKind::Explicit)
693+
}
694+
LifetimeRes::Fresh { param, .. } => {
695+
(hir::ParamName::Fresh(param), hir::LifetimeParamKind::Elided)
696+
}
697+
LifetimeRes::Static | LifetimeRes::Error => return None,
698+
res => panic!(
699+
"Unexpected lifetime resolution {:?} for {:?} at {:?}",
700+
res, ident, ident.span
701+
),
702+
};
702703
let hir_id = self.lower_node_id(node_id);
703-
let def_id = self.resolver.local_def_id(node_id);
704-
hir::GenericParam {
704+
Some(hir::GenericParam {
705705
hir_id,
706-
name: hir::ParamName::Fresh(def_id),
706+
name,
707707
bounds: &[],
708-
span: self.lower_span(span),
708+
span: self.lower_span(ident.span),
709709
pure_wrt_drop: false,
710-
kind: hir::GenericParamKind::Lifetime { kind: hir::LifetimeParamKind::Elided },
711-
}
712-
}
713-
714-
/// Evaluates `f` with the lifetimes in `params` in-scope.
715-
/// This is used to track which lifetimes have already been defined,
716-
/// which need to be duplicated for async fns.
717-
fn with_in_scope_lifetime_defs<T>(
718-
&mut self,
719-
params: &[GenericParam],
720-
f: impl FnOnce(&mut Self) -> T,
721-
) -> T {
722-
let old_len = self.in_scope_lifetimes.len();
723-
let lt_def_names = params.iter().filter_map(|param| match param.kind {
724-
GenericParamKind::Lifetime { .. } => {
725-
let def_id = self.resolver.local_def_id(param.id);
726-
let name = ParamName::Plain(param.ident);
727-
Some((name, def_id))
728-
}
729-
_ => None,
730-
});
731-
self.in_scope_lifetimes.extend(lt_def_names);
732-
733-
let res = f(self);
734-
735-
self.in_scope_lifetimes.truncate(old_len);
736-
res
710+
kind: hir::GenericParamKind::Lifetime { kind },
711+
})
737712
}
738713

739714
/// Creates a new `hir::GenericParam` for every new `Fresh` lifetime and
@@ -742,39 +717,23 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
742717
fn add_implicit_generics<T>(
743718
&mut self,
744719
generics: &Generics,
745-
parent_def_id: LocalDefId,
720+
parent_node_id: NodeId,
746721
f: impl FnOnce(&mut Self, &mut Vec<hir::GenericParam<'hir>>) -> T,
747722
) -> (hir::Generics<'hir>, T) {
748-
let lifetime_stash = std::mem::take(&mut self.lifetimes_to_define);
749-
let was_collecting =
750-
std::mem::replace(&mut self.is_collecting_anonymous_lifetimes, Some(parent_def_id));
751-
752723
let mut impl_trait_defs = Vec::new();
724+
let mut lowered_generics = self.lower_generics_mut(
725+
generics,
726+
ImplTraitContext::Universal(&mut impl_trait_defs, self.current_hir_id_owner),
727+
);
728+
let res = f(self, &mut impl_trait_defs);
753729

754-
let (mut lowered_generics, res) =
755-
self.with_in_scope_lifetime_defs(&generics.params, |this| {
756-
// Note: it is necessary to lower generics *before* calling `f`.
757-
// When lowering `async fn`, there's a final step when lowering
758-
// the return type that assumes that all in-scope lifetimes have
759-
// already been added to either `in_scope_lifetimes` or
760-
// `lifetimes_to_define`. If we swapped the order of these two,
761-
// fresh lifetimes introduced by generics or where-clauses
762-
// wouldn't have been added yet.
763-
let generics = this.lower_generics_mut(
764-
generics,
765-
ImplTraitContext::Universal(&mut impl_trait_defs, this.current_hir_id_owner),
766-
);
767-
let res = f(this, &mut impl_trait_defs);
768-
(generics, res)
769-
});
770-
771-
self.is_collecting_anonymous_lifetimes = was_collecting;
772-
let lifetimes_to_define = std::mem::replace(&mut self.lifetimes_to_define, lifetime_stash);
773-
730+
let extra_lifetimes = self.resolver.take_extra_lifetime_params(parent_node_id);
774731
lowered_generics.params.extend(
775-
lifetimes_to_define
732+
extra_lifetimes
776733
.into_iter()
777-
.map(|(node_id, span)| self.fresh_lifetime_to_generic_param(span, node_id))
734+
.filter_map(|(ident, node_id, res)| {
735+
self.lifetime_res_to_generic_param(ident, node_id, res)
736+
})
778737
.chain(impl_trait_defs),
779738
);
780739

@@ -1227,19 +1186,17 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
12271186
let lifetime = self.lower_lifetime(&region);
12281187
hir::TyKind::Rptr(lifetime, self.lower_mt(mt, itctx))
12291188
}
1230-
TyKind::BareFn(ref f) => self.with_in_scope_lifetime_defs(&f.generic_params, |this| {
1231-
this.with_lifetime_binder(t.id, |this| {
1232-
hir::TyKind::BareFn(this.arena.alloc(hir::BareFnTy {
1233-
generic_params: this.lower_generic_params(
1234-
&f.generic_params,
1235-
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
1236-
),
1237-
unsafety: this.lower_unsafety(f.unsafety),
1238-
abi: this.lower_extern(f.ext),
1239-
decl: this.lower_fn_decl(&f.decl, None, FnDeclKind::Pointer, None),
1240-
param_names: this.lower_fn_params_to_names(&f.decl),
1241-
}))
1242-
})
1189+
TyKind::BareFn(ref f) => self.with_lifetime_binder(t.id, |this| {
1190+
hir::TyKind::BareFn(this.arena.alloc(hir::BareFnTy {
1191+
generic_params: this.lower_generic_params(
1192+
&f.generic_params,
1193+
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
1194+
),
1195+
unsafety: this.lower_unsafety(f.unsafety),
1196+
abi: this.lower_extern(f.ext),
1197+
decl: this.lower_fn_decl(&f.decl, None, FnDeclKind::Pointer, None),
1198+
param_names: this.lower_fn_params_to_names(&f.decl),
1199+
}))
12431200
}),
12441201
TyKind::Never => hir::TyKind::Never,
12451202
TyKind::Tup(ref tys) => {
@@ -1676,70 +1633,50 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
16761633
// should be figured out using the ordinary elision rules, and
16771634
// this desugaring achieves that.
16781635

1679-
debug!("lower_async_fn_ret_ty: in_scope_lifetimes={:#?}", self.in_scope_lifetimes);
1680-
debug!("lower_async_fn_ret_ty: lifetimes_to_define={:#?}", self.lifetimes_to_define);
1681-
16821636
// Calculate all the lifetimes that should be captured
16831637
// by the opaque type. This should include all in-scope
16841638
// lifetime parameters, including those defined in-band.
16851639

1686-
// Input lifetime like `'a`:
16871640
let mut captures = FxHashMap::default();
1688-
for &(p_name, def_id) in &self.in_scope_lifetimes {
1689-
let Ident { name, span } = p_name.ident();
1690-
let node_id = self.resolver.next_node_id();
1641+
1642+
let extra_lifetime_params = self.resolver.take_extra_lifetime_params(opaque_ty_node_id);
1643+
debug!(?extra_lifetime_params);
1644+
for (ident, outer_node_id, outer_res) in extra_lifetime_params {
1645+
let Ident { name, span } = ident;
1646+
let outer_def_id = self.resolver.local_def_id(outer_node_id);
1647+
let inner_node_id = self.resolver.next_node_id();
16911648

16921649
// Add a definition for the in scope lifetime def.
16931650
self.resolver.create_def(
16941651
opaque_ty_def_id,
1695-
node_id,
1652+
inner_node_id,
16961653
DefPathData::LifetimeNs(name),
16971654
ExpnId::root(),
16981655
span.with_parent(None),
16991656
);
17001657

1701-
let res = match p_name {
1702-
hir::ParamName::Plain(_) => {
1703-
LifetimeRes::Param { param: def_id, binder: fn_node_id }
1658+
let (p_name, inner_res) = match outer_res {
1659+
// Input lifetime like `'a`:
1660+
LifetimeRes::Param { param, .. } => {
1661+
(hir::ParamName::Plain(ident), LifetimeRes::Param { param, binder: fn_node_id })
17041662
}
1705-
hir::ParamName::Fresh(_) => {
1706-
LifetimeRes::Fresh { param: def_id, introducer: None, binder: fn_node_id }
1663+
// Input lifetime like `'1`:
1664+
LifetimeRes::Fresh { param, .. } => (
1665+
hir::ParamName::Fresh(outer_def_id),
1666+
LifetimeRes::Fresh { param, binder: fn_node_id },
1667+
),
1668+
LifetimeRes::Static | LifetimeRes::Error => continue,
1669+
res => {
1670+
panic!("Unexpected lifetime resolution {:?} for {:?} at {:?}", res, ident, span)
17071671
}
1708-
hir::ParamName::Error => LifetimeRes::Error,
17091672
};
17101673

1711-
captures.insert(def_id, (span, node_id, p_name, res));
1712-
}
1713-
1714-
// Input lifetime like `'1`:
1715-
for (&node_id, &span) in &self.lifetimes_to_define {
1716-
let def_id = self.resolver.local_def_id(node_id);
1717-
let new_node_id = self.resolver.next_node_id();
1718-
1719-
// Add a definition for the `Fresh` lifetime def.
1720-
let new_def_id = self.resolver.create_def(
1721-
opaque_ty_def_id,
1722-
new_node_id,
1723-
DefPathData::LifetimeNs(kw::UnderscoreLifetime),
1724-
ExpnId::root(),
1725-
span.with_parent(None),
1726-
);
1727-
1728-
captures.insert(
1729-
def_id,
1730-
(
1731-
span,
1732-
new_node_id,
1733-
hir::ParamName::Fresh(new_def_id),
1734-
LifetimeRes::Fresh { param: def_id, introducer: None, binder: fn_node_id },
1735-
),
1736-
);
1674+
captures.insert(outer_def_id, (span, inner_node_id, p_name, inner_res));
17371675
}
17381676

17391677
debug!(?captures);
17401678

17411679
self.with_hir_id_owner(opaque_ty_node_id, |this| {
1742-
debug!("lower_async_fn_ret_ty: lifetimes_to_define={:#?}", this.lifetimes_to_define);
17431680
let future_bound =
17441681
this.while_capturing_lifetimes(opaque_ty_def_id, &mut captures, |this| {
17451682
// We have to be careful to get elision right here. The
@@ -1923,11 +1860,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
19231860
}
19241861
hir::LifetimeName::Param(p_name)
19251862
}
1926-
LifetimeRes::Fresh { mut param, introducer, binder } => {
1863+
LifetimeRes::Fresh { mut param, binder } => {
19271864
debug_assert_eq!(ident.name, kw::UnderscoreLifetime);
1928-
// Only items are allowed to introduce fresh lifetimes,
1929-
// so we know `binder` has a `LocalDefId`.
1930-
let binder_def_id = self.resolver.local_def_id(binder);
19311865
if let Some(LifetimeCaptureContext { parent_def_id, captures, binders_to_ignore }) =
19321866
&mut self.captured_lifetimes
19331867
&& !binders_to_ignore.contains(&binder)
@@ -1949,16 +1883,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
19491883
param = p_def_id;
19501884
}
19511885
}
1952-
} else if let Some(introducer) = introducer {
1953-
if self.is_collecting_anonymous_lifetimes == Some(binder_def_id)
1954-
&& self.resolver.opt_local_def_id(introducer) == Some(param)
1955-
{
1956-
debug!(
1957-
"lifetime_to_define += id={:?} span={:?} res={:?}",
1958-
introducer, span, res
1959-
);
1960-
self.lifetimes_to_define.insert(introducer, span);
1961-
}
19621886
}
19631887
let p_name = ParamName::Fresh(param);
19641888
hir::LifetimeName::Param(p_name)
@@ -2091,10 +2015,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
20912015
let bound_generic_params =
20922016
self.lower_generic_params(&p.bound_generic_params, itctx.reborrow());
20932017

2094-
let trait_ref = self.with_in_scope_lifetime_defs(&p.bound_generic_params, |this| {
2095-
this.with_lifetime_binder(p.trait_ref.ref_id, |this| {
2096-
this.lower_trait_ref(&p.trait_ref, itctx.reborrow())
2097-
})
2018+
let trait_ref = self.with_lifetime_binder(p.trait_ref.ref_id, |this| {
2019+
this.lower_trait_ref(&p.trait_ref, itctx.reborrow())
20982020
});
20992021

21002022
hir::PolyTraitRef { bound_generic_params, trait_ref, span: self.lower_span(p.span) }

‎compiler/rustc_resolve/src/late.rs

Lines changed: 37 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use rustc_ast::ptr::P;
1515
use rustc_ast::visit::{self, AssocCtxt, FnCtxt, FnKind, Visitor};
1616
use rustc_ast::*;
1717
use rustc_ast_lowering::{LifetimeRes, ResolverAstLowering};
18-
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
18+
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap};
1919
use rustc_errors::DiagnosticId;
2020
use rustc_hir::def::Namespace::{self, *};
2121
use rustc_hir::def::{self, CtorKind, DefKind, PartialRes, PerNS};
@@ -244,7 +244,8 @@ impl LifetimeBinderKind {
244244
#[derive(Debug)]
245245
struct LifetimeRib {
246246
kind: LifetimeRibKind,
247-
bindings: IdentMap<LifetimeRes>,
247+
// We need to preserve insertion order for async fns.
248+
bindings: FxIndexMap<Ident, (NodeId, LifetimeRes)>,
248249
}
249250

250251
impl LifetimeRib {
@@ -718,6 +719,32 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
718719
},
719720
);
720721

722+
// Construct the list of in-scope lifetime parameters for async lowering.
723+
// We include all lifetime parameters, either named or "Fresh".
724+
// The order of those parameters does not matter, as long as it is
725+
// deterministic.
726+
let mut extra_lifetime_params =
727+
this.r.extra_lifetime_params_map.get(&fn_id).cloned().unwrap_or_default();
728+
for rib in this.lifetime_ribs.iter().rev() {
729+
extra_lifetime_params.extend(
730+
rib.bindings
731+
.iter()
732+
.map(|(&ident, &(node_id, res))| (ident, node_id, res)),
733+
);
734+
match rib.kind {
735+
LifetimeRibKind::Item => break,
736+
LifetimeRibKind::AnonymousCreateParameter(id) => {
737+
if let Some(earlier_fresh) =
738+
this.r.extra_lifetime_params_map.get(&id)
739+
{
740+
extra_lifetime_params.extend(earlier_fresh);
741+
}
742+
}
743+
_ => {}
744+
}
745+
}
746+
this.r.extra_lifetime_params_map.insert(async_node_id, extra_lifetime_params);
747+
721748
this.with_lifetime_rib(
722749
LifetimeRibKind::AnonymousPassThrough(async_node_id),
723750
|this| visit::walk_fn_ret_ty(this, &declaration.output),
@@ -1126,7 +1153,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
11261153
for i in &mut indices {
11271154
let rib = &self.lifetime_ribs[i];
11281155
let normalized_ident = ident.normalize_to_macros_2_0();
1129-
if let Some(&region) = rib.bindings.get(&normalized_ident) {
1156+
if let Some(&(_, region)) = rib.bindings.get(&normalized_ident) {
11301157
self.record_lifetime_res(lifetime.id, region);
11311158
return;
11321159
}
@@ -1229,12 +1256,13 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
12291256
);
12301257
debug!(?def_id);
12311258

1232-
let region = LifetimeRes::Fresh {
1233-
param: def_id,
1234-
introducer: Some(def_node_id),
1235-
binder: item_node_id,
1236-
};
1259+
let region = LifetimeRes::Fresh { param: def_id, binder: item_node_id };
12371260
self.record_lifetime_res(id, region);
1261+
self.r.extra_lifetime_params_map.entry(item_node_id).or_insert_with(Vec::new).push((
1262+
ident,
1263+
def_node_id,
1264+
region,
1265+
));
12381266
}
12391267

12401268
#[tracing::instrument(level = "debug", skip(self))]
@@ -1818,7 +1846,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
18181846
let LifetimeRibKind::Generics { parent, .. } = lifetime_kind else { panic!() };
18191847
let res = LifetimeRes::Param { param: def_id, binder: parent };
18201848
self.record_lifetime_res(param.id, res);
1821-
function_lifetime_rib.bindings.insert(ident, res);
1849+
function_lifetime_rib.bindings.insert(ident, (param.id, res));
18221850
continue;
18231851
}
18241852
};

‎compiler/rustc_resolve/src/lib.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -903,6 +903,8 @@ pub struct Resolver<'a> {
903903
label_res_map: NodeMap<NodeId>,
904904
/// Resolutions for lifetimes.
905905
lifetimes_res_map: NodeMap<LifetimeRes>,
906+
/// Lifetime parameters that lowering will have to introduce.
907+
extra_lifetime_params_map: NodeMap<Vec<(Ident, NodeId, LifetimeRes)>>,
906908

907909
/// `CrateNum` resolutions of `extern crate` items.
908910
extern_crate_map: FxHashMap<LocalDefId, CrateNum>,
@@ -1159,6 +1161,10 @@ impl ResolverAstLowering for Resolver<'_> {
11591161
self.lifetimes_res_map.get(&id).copied()
11601162
}
11611163

1164+
fn take_extra_lifetime_params(&mut self, id: NodeId) -> Vec<(Ident, NodeId, LifetimeRes)> {
1165+
self.extra_lifetime_params_map.remove(&id).unwrap_or_default()
1166+
}
1167+
11621168
fn create_stable_hashing_context(&self) -> StableHashingContext<'_> {
11631169
StableHashingContext::new(self.session, &self.definitions, self.crate_loader.cstore())
11641170
}
@@ -1308,6 +1314,7 @@ impl<'a> Resolver<'a> {
13081314
import_res_map: Default::default(),
13091315
label_res_map: Default::default(),
13101316
lifetimes_res_map: Default::default(),
1317+
extra_lifetime_params_map: Default::default(),
13111318
extern_crate_map: Default::default(),
13121319
reexport_map: FxHashMap::default(),
13131320
trait_map: NodeMap::default(),

0 commit comments

Comments
 (0)
Please sign in to comment.