mirror of https://github.com/rust-lang/rust.git
Collect extra lifetime parameters during late resolution.
This commit is contained in:
parent
b590e3062c
commit
21b6d23890
|
@ -84,9 +84,6 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> {
|
||||||
generator_kind: None,
|
generator_kind: None,
|
||||||
task_context: None,
|
task_context: None,
|
||||||
current_item: None,
|
current_item: None,
|
||||||
lifetimes_to_define: Default::default(),
|
|
||||||
is_collecting_anonymous_lifetimes: None,
|
|
||||||
in_scope_lifetimes: Vec::new(),
|
|
||||||
captured_lifetimes: None,
|
captured_lifetimes: None,
|
||||||
allow_try_trait: Some([sym::try_trait_v2][..].into()),
|
allow_try_trait: Some([sym::try_trait_v2][..].into()),
|
||||||
allow_gen_future: Some([sym::gen_future][..].into()),
|
allow_gen_future: Some([sym::gen_future][..].into()),
|
||||||
|
@ -149,36 +146,8 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> {
|
||||||
// This is used to track which lifetimes have already been defined,
|
// This is used to track which lifetimes have already been defined,
|
||||||
// and which need to be replicated when lowering an async fn.
|
// and which need to be replicated when lowering an async fn.
|
||||||
match parent_hir.node().expect_item().kind {
|
match parent_hir.node().expect_item().kind {
|
||||||
hir::ItemKind::Impl(hir::Impl { ref of_trait, ref generics, .. }) => {
|
hir::ItemKind::Impl(hir::Impl { ref of_trait, .. }) => {
|
||||||
lctx.is_in_trait_impl = of_trait.is_some();
|
lctx.is_in_trait_impl = of_trait.is_some();
|
||||||
lctx.in_scope_lifetimes = generics
|
|
||||||
.params
|
|
||||||
.iter()
|
|
||||||
.filter(|param| {
|
|
||||||
matches!(param.kind, hir::GenericParamKind::Lifetime { .. })
|
|
||||||
})
|
|
||||||
.map(|param| {
|
|
||||||
let def_id =
|
|
||||||
parent_hir.nodes.local_id_to_def_id[¶m.hir_id.local_id];
|
|
||||||
let name = param.name;
|
|
||||||
(name, def_id)
|
|
||||||
})
|
|
||||||
.collect();
|
|
||||||
}
|
|
||||||
hir::ItemKind::Trait(_, _, ref generics, ..) => {
|
|
||||||
lctx.in_scope_lifetimes = generics
|
|
||||||
.params
|
|
||||||
.iter()
|
|
||||||
.filter(|param| {
|
|
||||||
matches!(param.kind, hir::GenericParamKind::Lifetime { .. })
|
|
||||||
})
|
|
||||||
.map(|param| {
|
|
||||||
let def_id =
|
|
||||||
parent_hir.nodes.local_id_to_def_id[¶m.hir_id.local_id];
|
|
||||||
let name = param.name;
|
|
||||||
(name, def_id)
|
|
||||||
})
|
|
||||||
.collect();
|
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
};
|
};
|
||||||
|
@ -286,7 +255,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
ref body,
|
ref body,
|
||||||
..
|
..
|
||||||
}) => {
|
}) => {
|
||||||
let fn_def_id = self.resolver.local_def_id(id);
|
|
||||||
self.with_new_scopes(|this| {
|
self.with_new_scopes(|this| {
|
||||||
this.current_item = Some(ident.span);
|
this.current_item = Some(ident.span);
|
||||||
|
|
||||||
|
@ -299,7 +267,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
this.lower_maybe_async_body(span, &decl, asyncness, body.as_deref());
|
this.lower_maybe_async_body(span, &decl, asyncness, body.as_deref());
|
||||||
|
|
||||||
let (generics, decl) =
|
let (generics, decl) =
|
||||||
this.add_implicit_generics(generics, fn_def_id, |this, idty| {
|
this.add_implicit_generics(generics, id, |this, idty| {
|
||||||
let ret_id = asyncness.opt_return_id();
|
let ret_id = asyncness.opt_return_id();
|
||||||
this.lower_fn_decl(&decl, Some((id, idty)), FnDeclKind::Fn, ret_id)
|
this.lower_fn_decl(&decl, Some((id, idty)), FnDeclKind::Fn, ret_id)
|
||||||
});
|
});
|
||||||
|
@ -415,9 +383,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
// method, it will not be considered an in-band
|
// method, it will not be considered an in-band
|
||||||
// lifetime to be added, but rather a reference to a
|
// lifetime to be added, but rather a reference to a
|
||||||
// parent lifetime.
|
// parent lifetime.
|
||||||
let lowered_trait_def_id = hir_id.expect_owner();
|
|
||||||
let (generics, (trait_ref, lowered_ty)) =
|
let (generics, (trait_ref, lowered_ty)) =
|
||||||
self.add_implicit_generics(ast_generics, lowered_trait_def_id, |this, _| {
|
self.add_implicit_generics(ast_generics, id, |this, _| {
|
||||||
let trait_ref = trait_ref.as_ref().map(|trait_ref| {
|
let trait_ref = trait_ref.as_ref().map(|trait_ref| {
|
||||||
this.lower_trait_ref(
|
this.lower_trait_ref(
|
||||||
trait_ref,
|
trait_ref,
|
||||||
|
@ -431,12 +398,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
(trait_ref, lowered_ty)
|
(trait_ref, lowered_ty)
|
||||||
});
|
});
|
||||||
|
|
||||||
let new_impl_items =
|
let new_impl_items = self
|
||||||
self.with_in_scope_lifetime_defs(&ast_generics.params, |this| {
|
.arena
|
||||||
this.arena.alloc_from_iter(
|
.alloc_from_iter(impl_items.iter().map(|item| self.lower_impl_item_ref(item)));
|
||||||
impl_items.iter().map(|item| this.lower_impl_item_ref(item)),
|
|
||||||
)
|
|
||||||
});
|
|
||||||
|
|
||||||
// `defaultness.has_value()` is never called for an `impl`, always `true` in order
|
// `defaultness.has_value()` is never called for an `impl`, always `true` in order
|
||||||
// to not cause an assertion failure inside the `lower_defaultness` function.
|
// to not cause an assertion failure inside the `lower_defaultness` function.
|
||||||
|
@ -743,7 +707,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
ForeignItemKind::Fn(box Fn { ref sig, ref generics, .. }) => {
|
ForeignItemKind::Fn(box Fn { ref sig, ref generics, .. }) => {
|
||||||
let fdec = &sig.decl;
|
let fdec = &sig.decl;
|
||||||
let (generics, (fn_dec, fn_args)) =
|
let (generics, (fn_dec, fn_args)) =
|
||||||
self.add_implicit_generics(generics, def_id, |this, _| {
|
self.add_implicit_generics(generics, i.id, |this, _| {
|
||||||
(
|
(
|
||||||
// Disallow `impl Trait` in foreign items.
|
// Disallow `impl Trait` in foreign items.
|
||||||
this.lower_fn_decl(fdec, None, FnDeclKind::ExternFn, None),
|
this.lower_fn_decl(fdec, None, FnDeclKind::ExternFn, None),
|
||||||
|
@ -1343,9 +1307,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
kind: FnDeclKind,
|
kind: FnDeclKind,
|
||||||
is_async: Option<NodeId>,
|
is_async: Option<NodeId>,
|
||||||
) -> (hir::Generics<'hir>, hir::FnSig<'hir>) {
|
) -> (hir::Generics<'hir>, hir::FnSig<'hir>) {
|
||||||
let fn_def_id = self.resolver.local_def_id(id);
|
|
||||||
let header = self.lower_fn_header(sig.header);
|
let header = self.lower_fn_header(sig.header);
|
||||||
let (generics, decl) = self.add_implicit_generics(generics, fn_def_id, |this, idty| {
|
let (generics, decl) = self.add_implicit_generics(generics, id, |this, idty| {
|
||||||
this.lower_fn_decl(&sig.decl, Some((id, idty)), kind, is_async)
|
this.lower_fn_decl(&sig.decl, Some((id, idty)), kind, is_async)
|
||||||
});
|
});
|
||||||
(generics, hir::FnSig { header, decl, span: self.lower_span(sig.span) })
|
(generics, hir::FnSig { header, decl, span: self.lower_span(sig.span) })
|
||||||
|
@ -1487,24 +1450,20 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
ref bounded_ty,
|
ref bounded_ty,
|
||||||
ref bounds,
|
ref bounds,
|
||||||
span,
|
span,
|
||||||
}) => self.with_in_scope_lifetime_defs(&bound_generic_params, |this| {
|
}) => hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate {
|
||||||
hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate {
|
bound_generic_params: self.lower_generic_params(
|
||||||
bound_generic_params: this.lower_generic_params(
|
|
||||||
bound_generic_params,
|
bound_generic_params,
|
||||||
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|
||||||
),
|
),
|
||||||
bounded_ty: this.lower_ty(
|
bounded_ty: self
|
||||||
bounded_ty,
|
.lower_ty(bounded_ty, ImplTraitContext::Disallowed(ImplTraitPosition::Type)),
|
||||||
ImplTraitContext::Disallowed(ImplTraitPosition::Type),
|
bounds: self.arena.alloc_from_iter(bounds.iter().map(|bound| {
|
||||||
),
|
self.lower_param_bound(
|
||||||
bounds: this.arena.alloc_from_iter(bounds.iter().map(|bound| {
|
|
||||||
this.lower_param_bound(
|
|
||||||
bound,
|
bound,
|
||||||
ImplTraitContext::Disallowed(ImplTraitPosition::Bound),
|
ImplTraitContext::Disallowed(ImplTraitPosition::Bound),
|
||||||
)
|
)
|
||||||
})),
|
})),
|
||||||
span: this.lower_span(span),
|
span: self.lower_span(span),
|
||||||
})
|
|
||||||
}),
|
}),
|
||||||
WherePredicate::RegionPredicate(WhereRegionPredicate {
|
WherePredicate::RegionPredicate(WhereRegionPredicate {
|
||||||
ref lifetime,
|
ref lifetime,
|
||||||
|
|
|
@ -45,7 +45,7 @@ use rustc_ast::{self as ast, *};
|
||||||
use rustc_ast_pretty::pprust;
|
use rustc_ast_pretty::pprust;
|
||||||
use rustc_data_structures::captures::Captures;
|
use rustc_data_structures::captures::Captures;
|
||||||
use rustc_data_structures::fingerprint::Fingerprint;
|
use rustc_data_structures::fingerprint::Fingerprint;
|
||||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap};
|
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||||
use rustc_data_structures::sorted_map::SortedMap;
|
use rustc_data_structures::sorted_map::SortedMap;
|
||||||
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
|
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
|
||||||
use rustc_data_structures::sync::Lrc;
|
use rustc_data_structures::sync::Lrc;
|
||||||
|
@ -122,20 +122,6 @@ struct LoweringContext<'a, 'hir: 'a> {
|
||||||
is_in_trait_impl: bool,
|
is_in_trait_impl: bool,
|
||||||
is_in_dyn_type: bool,
|
is_in_dyn_type: bool,
|
||||||
|
|
||||||
/// Used to create lifetime definitions for anonymous lifetimes.
|
|
||||||
/// When an anonymous lifetime is encountered in a function or impl header and
|
|
||||||
/// requires to create a fresh lifetime parameter, it is added
|
|
||||||
/// to this list. The results of this list are then added to the list of
|
|
||||||
/// lifetime definitions in the corresponding impl or function generics.
|
|
||||||
lifetimes_to_define: FxIndexMap<NodeId, Span>,
|
|
||||||
|
|
||||||
/// If anonymous lifetimes are being collected, this field holds the parent
|
|
||||||
/// `LocalDefId` to create the fresh lifetime parameters' `LocalDefId`.
|
|
||||||
is_collecting_anonymous_lifetimes: Option<LocalDefId>,
|
|
||||||
|
|
||||||
/// Currently in-scope lifetimes defined in impl headers, fn headers, or HRTB.
|
|
||||||
in_scope_lifetimes: Vec<(ParamName, LocalDefId)>,
|
|
||||||
|
|
||||||
/// Used to handle lifetimes appearing in impl-traits.
|
/// Used to handle lifetimes appearing in impl-traits.
|
||||||
captured_lifetimes: Option<LifetimeCaptureContext>,
|
captured_lifetimes: Option<LifetimeCaptureContext>,
|
||||||
|
|
||||||
|
@ -173,8 +159,6 @@ pub enum LifetimeRes {
|
||||||
Fresh {
|
Fresh {
|
||||||
/// Id of the generic parameter that introduced it.
|
/// Id of the generic parameter that introduced it.
|
||||||
param: LocalDefId,
|
param: LocalDefId,
|
||||||
/// Id to create the HirId. This is used when creating the `Fresh` lifetime parameters.
|
|
||||||
introducer: Option<NodeId>,
|
|
||||||
/// Id of the introducing place. See `Param`.
|
/// Id of the introducing place. See `Param`.
|
||||||
binder: NodeId,
|
binder: NodeId,
|
||||||
},
|
},
|
||||||
|
@ -237,6 +221,9 @@ pub trait ResolverAstLowering {
|
||||||
/// Obtains resolution for a lifetime with the given `NodeId`.
|
/// Obtains resolution for a lifetime with the given `NodeId`.
|
||||||
fn get_lifetime_res(&self, id: NodeId) -> Option<LifetimeRes>;
|
fn get_lifetime_res(&self, id: NodeId) -> Option<LifetimeRes>;
|
||||||
|
|
||||||
|
/// Obtain the list of lifetimes parameters to add to an item.
|
||||||
|
fn take_extra_lifetime_params(&mut self, id: NodeId) -> Vec<(Ident, NodeId, LifetimeRes)>;
|
||||||
|
|
||||||
fn create_stable_hashing_context(&self) -> StableHashingContext<'_>;
|
fn create_stable_hashing_context(&self) -> StableHashingContext<'_>;
|
||||||
|
|
||||||
fn definitions(&self) -> &Definitions;
|
fn definitions(&self) -> &Definitions;
|
||||||
|
@ -694,46 +681,34 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Converts a lifetime into a new generic parameter.
|
/// Converts a lifetime into a new generic parameter.
|
||||||
fn fresh_lifetime_to_generic_param(
|
fn lifetime_res_to_generic_param(
|
||||||
&mut self,
|
&mut self,
|
||||||
span: Span,
|
ident: Ident,
|
||||||
node_id: NodeId,
|
node_id: NodeId,
|
||||||
) -> hir::GenericParam<'hir> {
|
res: LifetimeRes,
|
||||||
|
) -> Option<hir::GenericParam<'hir>> {
|
||||||
|
let (name, kind) = match res {
|
||||||
|
LifetimeRes::Param { .. } => {
|
||||||
|
(hir::ParamName::Plain(ident), hir::LifetimeParamKind::Explicit)
|
||||||
|
}
|
||||||
|
LifetimeRes::Fresh { param, .. } => {
|
||||||
|
(hir::ParamName::Fresh(param), hir::LifetimeParamKind::Elided)
|
||||||
|
}
|
||||||
|
LifetimeRes::Static | LifetimeRes::Error => return None,
|
||||||
|
res => panic!(
|
||||||
|
"Unexpected lifetime resolution {:?} for {:?} at {:?}",
|
||||||
|
res, ident, ident.span
|
||||||
|
),
|
||||||
|
};
|
||||||
let hir_id = self.lower_node_id(node_id);
|
let hir_id = self.lower_node_id(node_id);
|
||||||
let def_id = self.resolver.local_def_id(node_id);
|
Some(hir::GenericParam {
|
||||||
hir::GenericParam {
|
|
||||||
hir_id,
|
hir_id,
|
||||||
name: hir::ParamName::Fresh(def_id),
|
name,
|
||||||
bounds: &[],
|
bounds: &[],
|
||||||
span: self.lower_span(span),
|
span: self.lower_span(ident.span),
|
||||||
pure_wrt_drop: false,
|
pure_wrt_drop: false,
|
||||||
kind: hir::GenericParamKind::Lifetime { kind: hir::LifetimeParamKind::Elided },
|
kind: hir::GenericParamKind::Lifetime { kind },
|
||||||
}
|
})
|
||||||
}
|
|
||||||
|
|
||||||
/// Evaluates `f` with the lifetimes in `params` in-scope.
|
|
||||||
/// This is used to track which lifetimes have already been defined,
|
|
||||||
/// which need to be duplicated for async fns.
|
|
||||||
fn with_in_scope_lifetime_defs<T>(
|
|
||||||
&mut self,
|
|
||||||
params: &[GenericParam],
|
|
||||||
f: impl FnOnce(&mut Self) -> T,
|
|
||||||
) -> T {
|
|
||||||
let old_len = self.in_scope_lifetimes.len();
|
|
||||||
let lt_def_names = params.iter().filter_map(|param| match param.kind {
|
|
||||||
GenericParamKind::Lifetime { .. } => {
|
|
||||||
let def_id = self.resolver.local_def_id(param.id);
|
|
||||||
let name = ParamName::Plain(param.ident);
|
|
||||||
Some((name, def_id))
|
|
||||||
}
|
|
||||||
_ => None,
|
|
||||||
});
|
|
||||||
self.in_scope_lifetimes.extend(lt_def_names);
|
|
||||||
|
|
||||||
let res = f(self);
|
|
||||||
|
|
||||||
self.in_scope_lifetimes.truncate(old_len);
|
|
||||||
res
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a new `hir::GenericParam` for every new `Fresh` lifetime and
|
/// Creates a new `hir::GenericParam` for every new `Fresh` lifetime and
|
||||||
|
@ -742,39 +717,23 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||||
fn add_implicit_generics<T>(
|
fn add_implicit_generics<T>(
|
||||||
&mut self,
|
&mut self,
|
||||||
generics: &Generics,
|
generics: &Generics,
|
||||||
parent_def_id: LocalDefId,
|
parent_node_id: NodeId,
|
||||||
f: impl FnOnce(&mut Self, &mut Vec<hir::GenericParam<'hir>>) -> T,
|
f: impl FnOnce(&mut Self, &mut Vec<hir::GenericParam<'hir>>) -> T,
|
||||||
) -> (hir::Generics<'hir>, T) {
|
) -> (hir::Generics<'hir>, T) {
|
||||||
let lifetime_stash = std::mem::take(&mut self.lifetimes_to_define);
|
|
||||||
let was_collecting =
|
|
||||||
std::mem::replace(&mut self.is_collecting_anonymous_lifetimes, Some(parent_def_id));
|
|
||||||
|
|
||||||
let mut impl_trait_defs = Vec::new();
|
let mut impl_trait_defs = Vec::new();
|
||||||
|
let mut lowered_generics = self.lower_generics_mut(
|
||||||
let (mut lowered_generics, res) =
|
|
||||||
self.with_in_scope_lifetime_defs(&generics.params, |this| {
|
|
||||||
// Note: it is necessary to lower generics *before* calling `f`.
|
|
||||||
// When lowering `async fn`, there's a final step when lowering
|
|
||||||
// the return type that assumes that all in-scope lifetimes have
|
|
||||||
// already been added to either `in_scope_lifetimes` or
|
|
||||||
// `lifetimes_to_define`. If we swapped the order of these two,
|
|
||||||
// fresh lifetimes introduced by generics or where-clauses
|
|
||||||
// wouldn't have been added yet.
|
|
||||||
let generics = this.lower_generics_mut(
|
|
||||||
generics,
|
generics,
|
||||||
ImplTraitContext::Universal(&mut impl_trait_defs, this.current_hir_id_owner),
|
ImplTraitContext::Universal(&mut impl_trait_defs, self.current_hir_id_owner),
|
||||||
);
|
);
|
||||||
let res = f(this, &mut impl_trait_defs);
|
let res = f(self, &mut impl_trait_defs);
|
||||||
(generics, res)
|
|
||||||
});
|
|
||||||
|
|
||||||
self.is_collecting_anonymous_lifetimes = was_collecting;
|
|
||||||
let lifetimes_to_define = std::mem::replace(&mut self.lifetimes_to_define, lifetime_stash);
|
|
||||||
|
|
||||||
|
let extra_lifetimes = self.resolver.take_extra_lifetime_params(parent_node_id);
|
||||||
lowered_generics.params.extend(
|
lowered_generics.params.extend(
|
||||||
lifetimes_to_define
|
extra_lifetimes
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|(node_id, span)| self.fresh_lifetime_to_generic_param(span, node_id))
|
.filter_map(|(ident, node_id, res)| {
|
||||||
|
self.lifetime_res_to_generic_param(ident, node_id, res)
|
||||||
|
})
|
||||||
.chain(impl_trait_defs),
|
.chain(impl_trait_defs),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -1227,8 +1186,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||||
let lifetime = self.lower_lifetime(®ion);
|
let lifetime = self.lower_lifetime(®ion);
|
||||||
hir::TyKind::Rptr(lifetime, self.lower_mt(mt, itctx))
|
hir::TyKind::Rptr(lifetime, self.lower_mt(mt, itctx))
|
||||||
}
|
}
|
||||||
TyKind::BareFn(ref f) => self.with_in_scope_lifetime_defs(&f.generic_params, |this| {
|
TyKind::BareFn(ref f) => self.with_lifetime_binder(t.id, |this| {
|
||||||
this.with_lifetime_binder(t.id, |this| {
|
|
||||||
hir::TyKind::BareFn(this.arena.alloc(hir::BareFnTy {
|
hir::TyKind::BareFn(this.arena.alloc(hir::BareFnTy {
|
||||||
generic_params: this.lower_generic_params(
|
generic_params: this.lower_generic_params(
|
||||||
&f.generic_params,
|
&f.generic_params,
|
||||||
|
@ -1239,7 +1197,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||||
decl: this.lower_fn_decl(&f.decl, None, FnDeclKind::Pointer, None),
|
decl: this.lower_fn_decl(&f.decl, None, FnDeclKind::Pointer, None),
|
||||||
param_names: this.lower_fn_params_to_names(&f.decl),
|
param_names: this.lower_fn_params_to_names(&f.decl),
|
||||||
}))
|
}))
|
||||||
})
|
|
||||||
}),
|
}),
|
||||||
TyKind::Never => hir::TyKind::Never,
|
TyKind::Never => hir::TyKind::Never,
|
||||||
TyKind::Tup(ref tys) => {
|
TyKind::Tup(ref tys) => {
|
||||||
|
@ -1676,70 +1633,50 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||||
// should be figured out using the ordinary elision rules, and
|
// should be figured out using the ordinary elision rules, and
|
||||||
// this desugaring achieves that.
|
// this desugaring achieves that.
|
||||||
|
|
||||||
debug!("lower_async_fn_ret_ty: in_scope_lifetimes={:#?}", self.in_scope_lifetimes);
|
|
||||||
debug!("lower_async_fn_ret_ty: lifetimes_to_define={:#?}", self.lifetimes_to_define);
|
|
||||||
|
|
||||||
// Calculate all the lifetimes that should be captured
|
// Calculate all the lifetimes that should be captured
|
||||||
// by the opaque type. This should include all in-scope
|
// by the opaque type. This should include all in-scope
|
||||||
// lifetime parameters, including those defined in-band.
|
// lifetime parameters, including those defined in-band.
|
||||||
|
|
||||||
// Input lifetime like `'a`:
|
|
||||||
let mut captures = FxHashMap::default();
|
let mut captures = FxHashMap::default();
|
||||||
for &(p_name, def_id) in &self.in_scope_lifetimes {
|
|
||||||
let Ident { name, span } = p_name.ident();
|
let extra_lifetime_params = self.resolver.take_extra_lifetime_params(opaque_ty_node_id);
|
||||||
let node_id = self.resolver.next_node_id();
|
debug!(?extra_lifetime_params);
|
||||||
|
for (ident, outer_node_id, outer_res) in extra_lifetime_params {
|
||||||
|
let Ident { name, span } = ident;
|
||||||
|
let outer_def_id = self.resolver.local_def_id(outer_node_id);
|
||||||
|
let inner_node_id = self.resolver.next_node_id();
|
||||||
|
|
||||||
// Add a definition for the in scope lifetime def.
|
// Add a definition for the in scope lifetime def.
|
||||||
self.resolver.create_def(
|
self.resolver.create_def(
|
||||||
opaque_ty_def_id,
|
opaque_ty_def_id,
|
||||||
node_id,
|
inner_node_id,
|
||||||
DefPathData::LifetimeNs(name),
|
DefPathData::LifetimeNs(name),
|
||||||
ExpnId::root(),
|
ExpnId::root(),
|
||||||
span.with_parent(None),
|
span.with_parent(None),
|
||||||
);
|
);
|
||||||
|
|
||||||
let res = match p_name {
|
let (p_name, inner_res) = match outer_res {
|
||||||
hir::ParamName::Plain(_) => {
|
// Input lifetime like `'a`:
|
||||||
LifetimeRes::Param { param: def_id, binder: fn_node_id }
|
LifetimeRes::Param { param, .. } => {
|
||||||
|
(hir::ParamName::Plain(ident), LifetimeRes::Param { param, binder: fn_node_id })
|
||||||
}
|
}
|
||||||
hir::ParamName::Fresh(_) => {
|
// Input lifetime like `'1`:
|
||||||
LifetimeRes::Fresh { param: def_id, introducer: None, binder: fn_node_id }
|
LifetimeRes::Fresh { param, .. } => (
|
||||||
|
hir::ParamName::Fresh(outer_def_id),
|
||||||
|
LifetimeRes::Fresh { param, binder: fn_node_id },
|
||||||
|
),
|
||||||
|
LifetimeRes::Static | LifetimeRes::Error => continue,
|
||||||
|
res => {
|
||||||
|
panic!("Unexpected lifetime resolution {:?} for {:?} at {:?}", res, ident, span)
|
||||||
}
|
}
|
||||||
hir::ParamName::Error => LifetimeRes::Error,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
captures.insert(def_id, (span, node_id, p_name, res));
|
captures.insert(outer_def_id, (span, inner_node_id, p_name, inner_res));
|
||||||
}
|
|
||||||
|
|
||||||
// Input lifetime like `'1`:
|
|
||||||
for (&node_id, &span) in &self.lifetimes_to_define {
|
|
||||||
let def_id = self.resolver.local_def_id(node_id);
|
|
||||||
let new_node_id = self.resolver.next_node_id();
|
|
||||||
|
|
||||||
// Add a definition for the `Fresh` lifetime def.
|
|
||||||
let new_def_id = self.resolver.create_def(
|
|
||||||
opaque_ty_def_id,
|
|
||||||
new_node_id,
|
|
||||||
DefPathData::LifetimeNs(kw::UnderscoreLifetime),
|
|
||||||
ExpnId::root(),
|
|
||||||
span.with_parent(None),
|
|
||||||
);
|
|
||||||
|
|
||||||
captures.insert(
|
|
||||||
def_id,
|
|
||||||
(
|
|
||||||
span,
|
|
||||||
new_node_id,
|
|
||||||
hir::ParamName::Fresh(new_def_id),
|
|
||||||
LifetimeRes::Fresh { param: def_id, introducer: None, binder: fn_node_id },
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
debug!(?captures);
|
debug!(?captures);
|
||||||
|
|
||||||
self.with_hir_id_owner(opaque_ty_node_id, |this| {
|
self.with_hir_id_owner(opaque_ty_node_id, |this| {
|
||||||
debug!("lower_async_fn_ret_ty: lifetimes_to_define={:#?}", this.lifetimes_to_define);
|
|
||||||
let future_bound =
|
let future_bound =
|
||||||
this.while_capturing_lifetimes(opaque_ty_def_id, &mut captures, |this| {
|
this.while_capturing_lifetimes(opaque_ty_def_id, &mut captures, |this| {
|
||||||
// We have to be careful to get elision right here. The
|
// We have to be careful to get elision right here. The
|
||||||
|
@ -1923,11 +1860,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||||
}
|
}
|
||||||
hir::LifetimeName::Param(p_name)
|
hir::LifetimeName::Param(p_name)
|
||||||
}
|
}
|
||||||
LifetimeRes::Fresh { mut param, introducer, binder } => {
|
LifetimeRes::Fresh { mut param, binder } => {
|
||||||
debug_assert_eq!(ident.name, kw::UnderscoreLifetime);
|
debug_assert_eq!(ident.name, kw::UnderscoreLifetime);
|
||||||
// Only items are allowed to introduce fresh lifetimes,
|
|
||||||
// so we know `binder` has a `LocalDefId`.
|
|
||||||
let binder_def_id = self.resolver.local_def_id(binder);
|
|
||||||
if let Some(LifetimeCaptureContext { parent_def_id, captures, binders_to_ignore }) =
|
if let Some(LifetimeCaptureContext { parent_def_id, captures, binders_to_ignore }) =
|
||||||
&mut self.captured_lifetimes
|
&mut self.captured_lifetimes
|
||||||
&& !binders_to_ignore.contains(&binder)
|
&& !binders_to_ignore.contains(&binder)
|
||||||
|
@ -1949,16 +1883,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||||
param = p_def_id;
|
param = p_def_id;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if let Some(introducer) = introducer {
|
|
||||||
if self.is_collecting_anonymous_lifetimes == Some(binder_def_id)
|
|
||||||
&& self.resolver.opt_local_def_id(introducer) == Some(param)
|
|
||||||
{
|
|
||||||
debug!(
|
|
||||||
"lifetime_to_define += id={:?} span={:?} res={:?}",
|
|
||||||
introducer, span, res
|
|
||||||
);
|
|
||||||
self.lifetimes_to_define.insert(introducer, span);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
let p_name = ParamName::Fresh(param);
|
let p_name = ParamName::Fresh(param);
|
||||||
hir::LifetimeName::Param(p_name)
|
hir::LifetimeName::Param(p_name)
|
||||||
|
@ -2091,10 +2015,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||||
let bound_generic_params =
|
let bound_generic_params =
|
||||||
self.lower_generic_params(&p.bound_generic_params, itctx.reborrow());
|
self.lower_generic_params(&p.bound_generic_params, itctx.reborrow());
|
||||||
|
|
||||||
let trait_ref = self.with_in_scope_lifetime_defs(&p.bound_generic_params, |this| {
|
let trait_ref = self.with_lifetime_binder(p.trait_ref.ref_id, |this| {
|
||||||
this.with_lifetime_binder(p.trait_ref.ref_id, |this| {
|
|
||||||
this.lower_trait_ref(&p.trait_ref, itctx.reborrow())
|
this.lower_trait_ref(&p.trait_ref, itctx.reborrow())
|
||||||
})
|
|
||||||
});
|
});
|
||||||
|
|
||||||
hir::PolyTraitRef { bound_generic_params, trait_ref, span: self.lower_span(p.span) }
|
hir::PolyTraitRef { bound_generic_params, trait_ref, span: self.lower_span(p.span) }
|
||||||
|
|
|
@ -15,7 +15,7 @@ use rustc_ast::ptr::P;
|
||||||
use rustc_ast::visit::{self, AssocCtxt, FnCtxt, FnKind, Visitor};
|
use rustc_ast::visit::{self, AssocCtxt, FnCtxt, FnKind, Visitor};
|
||||||
use rustc_ast::*;
|
use rustc_ast::*;
|
||||||
use rustc_ast_lowering::{LifetimeRes, ResolverAstLowering};
|
use rustc_ast_lowering::{LifetimeRes, ResolverAstLowering};
|
||||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap};
|
||||||
use rustc_errors::DiagnosticId;
|
use rustc_errors::DiagnosticId;
|
||||||
use rustc_hir::def::Namespace::{self, *};
|
use rustc_hir::def::Namespace::{self, *};
|
||||||
use rustc_hir::def::{self, CtorKind, DefKind, PartialRes, PerNS};
|
use rustc_hir::def::{self, CtorKind, DefKind, PartialRes, PerNS};
|
||||||
|
@ -244,7 +244,8 @@ impl LifetimeBinderKind {
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct LifetimeRib {
|
struct LifetimeRib {
|
||||||
kind: LifetimeRibKind,
|
kind: LifetimeRibKind,
|
||||||
bindings: IdentMap<LifetimeRes>,
|
// We need to preserve insertion order for async fns.
|
||||||
|
bindings: FxIndexMap<Ident, (NodeId, LifetimeRes)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LifetimeRib {
|
impl LifetimeRib {
|
||||||
|
@ -718,6 +719,32 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Construct the list of in-scope lifetime parameters for async lowering.
|
||||||
|
// We include all lifetime parameters, either named or "Fresh".
|
||||||
|
// The order of those parameters does not matter, as long as it is
|
||||||
|
// deterministic.
|
||||||
|
let mut extra_lifetime_params =
|
||||||
|
this.r.extra_lifetime_params_map.get(&fn_id).cloned().unwrap_or_default();
|
||||||
|
for rib in this.lifetime_ribs.iter().rev() {
|
||||||
|
extra_lifetime_params.extend(
|
||||||
|
rib.bindings
|
||||||
|
.iter()
|
||||||
|
.map(|(&ident, &(node_id, res))| (ident, node_id, res)),
|
||||||
|
);
|
||||||
|
match rib.kind {
|
||||||
|
LifetimeRibKind::Item => break,
|
||||||
|
LifetimeRibKind::AnonymousCreateParameter(id) => {
|
||||||
|
if let Some(earlier_fresh) =
|
||||||
|
this.r.extra_lifetime_params_map.get(&id)
|
||||||
|
{
|
||||||
|
extra_lifetime_params.extend(earlier_fresh);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.r.extra_lifetime_params_map.insert(async_node_id, extra_lifetime_params);
|
||||||
|
|
||||||
this.with_lifetime_rib(
|
this.with_lifetime_rib(
|
||||||
LifetimeRibKind::AnonymousPassThrough(async_node_id),
|
LifetimeRibKind::AnonymousPassThrough(async_node_id),
|
||||||
|this| visit::walk_fn_ret_ty(this, &declaration.output),
|
|this| visit::walk_fn_ret_ty(this, &declaration.output),
|
||||||
|
@ -1126,7 +1153,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
||||||
for i in &mut indices {
|
for i in &mut indices {
|
||||||
let rib = &self.lifetime_ribs[i];
|
let rib = &self.lifetime_ribs[i];
|
||||||
let normalized_ident = ident.normalize_to_macros_2_0();
|
let normalized_ident = ident.normalize_to_macros_2_0();
|
||||||
if let Some(®ion) = rib.bindings.get(&normalized_ident) {
|
if let Some(&(_, region)) = rib.bindings.get(&normalized_ident) {
|
||||||
self.record_lifetime_res(lifetime.id, region);
|
self.record_lifetime_res(lifetime.id, region);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1229,12 +1256,13 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
||||||
);
|
);
|
||||||
debug!(?def_id);
|
debug!(?def_id);
|
||||||
|
|
||||||
let region = LifetimeRes::Fresh {
|
let region = LifetimeRes::Fresh { param: def_id, binder: item_node_id };
|
||||||
param: def_id,
|
|
||||||
introducer: Some(def_node_id),
|
|
||||||
binder: item_node_id,
|
|
||||||
};
|
|
||||||
self.record_lifetime_res(id, region);
|
self.record_lifetime_res(id, region);
|
||||||
|
self.r.extra_lifetime_params_map.entry(item_node_id).or_insert_with(Vec::new).push((
|
||||||
|
ident,
|
||||||
|
def_node_id,
|
||||||
|
region,
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tracing::instrument(level = "debug", skip(self))]
|
#[tracing::instrument(level = "debug", skip(self))]
|
||||||
|
@ -1818,7 +1846,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
||||||
let LifetimeRibKind::Generics { parent, .. } = lifetime_kind else { panic!() };
|
let LifetimeRibKind::Generics { parent, .. } = lifetime_kind else { panic!() };
|
||||||
let res = LifetimeRes::Param { param: def_id, binder: parent };
|
let res = LifetimeRes::Param { param: def_id, binder: parent };
|
||||||
self.record_lifetime_res(param.id, res);
|
self.record_lifetime_res(param.id, res);
|
||||||
function_lifetime_rib.bindings.insert(ident, res);
|
function_lifetime_rib.bindings.insert(ident, (param.id, res));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -903,6 +903,8 @@ pub struct Resolver<'a> {
|
||||||
label_res_map: NodeMap<NodeId>,
|
label_res_map: NodeMap<NodeId>,
|
||||||
/// Resolutions for lifetimes.
|
/// Resolutions for lifetimes.
|
||||||
lifetimes_res_map: NodeMap<LifetimeRes>,
|
lifetimes_res_map: NodeMap<LifetimeRes>,
|
||||||
|
/// Lifetime parameters that lowering will have to introduce.
|
||||||
|
extra_lifetime_params_map: NodeMap<Vec<(Ident, NodeId, LifetimeRes)>>,
|
||||||
|
|
||||||
/// `CrateNum` resolutions of `extern crate` items.
|
/// `CrateNum` resolutions of `extern crate` items.
|
||||||
extern_crate_map: FxHashMap<LocalDefId, CrateNum>,
|
extern_crate_map: FxHashMap<LocalDefId, CrateNum>,
|
||||||
|
@ -1159,6 +1161,10 @@ impl ResolverAstLowering for Resolver<'_> {
|
||||||
self.lifetimes_res_map.get(&id).copied()
|
self.lifetimes_res_map.get(&id).copied()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn take_extra_lifetime_params(&mut self, id: NodeId) -> Vec<(Ident, NodeId, LifetimeRes)> {
|
||||||
|
self.extra_lifetime_params_map.remove(&id).unwrap_or_default()
|
||||||
|
}
|
||||||
|
|
||||||
fn create_stable_hashing_context(&self) -> StableHashingContext<'_> {
|
fn create_stable_hashing_context(&self) -> StableHashingContext<'_> {
|
||||||
StableHashingContext::new(self.session, &self.definitions, self.crate_loader.cstore())
|
StableHashingContext::new(self.session, &self.definitions, self.crate_loader.cstore())
|
||||||
}
|
}
|
||||||
|
@ -1308,6 +1314,7 @@ impl<'a> Resolver<'a> {
|
||||||
import_res_map: Default::default(),
|
import_res_map: Default::default(),
|
||||||
label_res_map: Default::default(),
|
label_res_map: Default::default(),
|
||||||
lifetimes_res_map: Default::default(),
|
lifetimes_res_map: Default::default(),
|
||||||
|
extra_lifetime_params_map: Default::default(),
|
||||||
extern_crate_map: Default::default(),
|
extern_crate_map: Default::default(),
|
||||||
reexport_map: FxHashMap::default(),
|
reexport_map: FxHashMap::default(),
|
||||||
trait_map: NodeMap::default(),
|
trait_map: NodeMap::default(),
|
||||||
|
|
Loading…
Reference in New Issue