Auto merge of #91557 - cjgillot:ast-lifetimes-named, r=petrochenkov
Perform lifetime resolution on the AST for lowering Lifetime resolution is currently implemented several times. Once during lowering in order to introduce in-band lifetimes, and once in the resolve_lifetimes query. However, due to the global nature of lifetime resolution and how it interferes with hygiene, it is better suited on the AST. This PR implements a first draft of lifetime resolution on the AST. For now, we specifically target named lifetimes and everything we need to remove lifetime resolution from lowering. Some diagnostics have already been ported, and sometimes made more precise using available hygiene information. Follow-up PRs will address in particular the resolution of anonymous lifetimes on the AST. We reuse the rib design of the current resolution framework. Specific `LifetimeRib` and `LifetimeRibKind` types are introduced. The most important variant is `LifetimeRibKind::Generics`, which happens each time we encounter something which may introduce generic lifetime parameters. It can be an item or a `for<...>` binder. The `LifetimeBinderKind` specifies how this rib behaves with respect to in-band lifetimes. r? `@petrochenkov`
This commit is contained in:
commit
c95346b8ac
12 changed files with 761 additions and 985 deletions
|
@ -53,7 +53,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
e.span,
|
e.span,
|
||||||
seg,
|
seg,
|
||||||
ParamMode::Optional,
|
ParamMode::Optional,
|
||||||
0,
|
|
||||||
ParenthesizedGenericArgs::Err,
|
ParenthesizedGenericArgs::Err,
|
||||||
ImplTraitContext::Disallowed(ImplTraitPosition::Path),
|
ImplTraitContext::Disallowed(ImplTraitPosition::Path),
|
||||||
));
|
));
|
||||||
|
|
|
@ -30,6 +30,7 @@ pub(super) struct NodeCollector<'a, 'hir> {
|
||||||
definitions: &'a definitions::Definitions,
|
definitions: &'a definitions::Definitions,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tracing::instrument(level = "debug", skip(sess, definitions, bodies))]
|
||||||
pub(super) fn index_hir<'hir>(
|
pub(super) fn index_hir<'hir>(
|
||||||
sess: &Session,
|
sess: &Session,
|
||||||
definitions: &definitions::Definitions,
|
definitions: &definitions::Definitions,
|
||||||
|
@ -65,6 +66,7 @@ pub(super) fn index_hir<'hir>(
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'hir> NodeCollector<'a, 'hir> {
|
impl<'a, 'hir> NodeCollector<'a, 'hir> {
|
||||||
|
#[tracing::instrument(level = "debug", skip(self))]
|
||||||
fn insert(&mut self, span: Span, hir_id: HirId, node: Node<'hir>) {
|
fn insert(&mut self, span: Span, hir_id: HirId, node: Node<'hir>) {
|
||||||
debug_assert_eq!(self.owner, hir_id.owner);
|
debug_assert_eq!(self.owner, hir_id.owner);
|
||||||
debug_assert_ne!(hir_id.local_id.as_u32(), 0);
|
debug_assert_ne!(hir_id.local_id.as_u32(), 0);
|
||||||
|
@ -138,8 +140,8 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tracing::instrument(level = "debug", skip(self))]
|
||||||
fn visit_item(&mut self, i: &'hir Item<'hir>) {
|
fn visit_item(&mut self, i: &'hir Item<'hir>) {
|
||||||
debug!("visit_item: {:?}", i);
|
|
||||||
debug_assert_eq!(i.def_id, self.owner);
|
debug_assert_eq!(i.def_id, self.owner);
|
||||||
self.with_parent(i.hir_id(), |this| {
|
self.with_parent(i.hir_id(), |this| {
|
||||||
if let ItemKind::Struct(ref struct_def, _) = i.kind {
|
if let ItemKind::Struct(ref struct_def, _) = i.kind {
|
||||||
|
@ -152,6 +154,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tracing::instrument(level = "debug", skip(self))]
|
||||||
fn visit_foreign_item(&mut self, fi: &'hir ForeignItem<'hir>) {
|
fn visit_foreign_item(&mut self, fi: &'hir ForeignItem<'hir>) {
|
||||||
debug_assert_eq!(fi.def_id, self.owner);
|
debug_assert_eq!(fi.def_id, self.owner);
|
||||||
self.with_parent(fi.hir_id(), |this| {
|
self.with_parent(fi.hir_id(), |this| {
|
||||||
|
@ -170,6 +173,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tracing::instrument(level = "debug", skip(self))]
|
||||||
fn visit_trait_item(&mut self, ti: &'hir TraitItem<'hir>) {
|
fn visit_trait_item(&mut self, ti: &'hir TraitItem<'hir>) {
|
||||||
debug_assert_eq!(ti.def_id, self.owner);
|
debug_assert_eq!(ti.def_id, self.owner);
|
||||||
self.with_parent(ti.hir_id(), |this| {
|
self.with_parent(ti.hir_id(), |this| {
|
||||||
|
@ -177,6 +181,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tracing::instrument(level = "debug", skip(self))]
|
||||||
fn visit_impl_item(&mut self, ii: &'hir ImplItem<'hir>) {
|
fn visit_impl_item(&mut self, ii: &'hir ImplItem<'hir>) {
|
||||||
debug_assert_eq!(ii.def_id, self.owner);
|
debug_assert_eq!(ii.def_id, self.owner);
|
||||||
self.with_parent(ii.hir_id(), |this| {
|
self.with_parent(ii.hir_id(), |this| {
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
use super::{AnonymousLifetimeMode, LoweringContext, ParamMode};
|
|
||||||
use super::{AstOwner, ImplTraitContext, ImplTraitPosition, ResolverAstLowering};
|
use super::{AstOwner, ImplTraitContext, ImplTraitPosition, ResolverAstLowering};
|
||||||
|
use super::{LoweringContext, ParamMode};
|
||||||
use crate::{Arena, FnDeclKind};
|
use crate::{Arena, FnDeclKind};
|
||||||
|
|
||||||
use rustc_ast::ptr::P;
|
use rustc_ast::ptr::P;
|
||||||
use rustc_ast::visit::AssocCtxt;
|
use rustc_ast::visit::AssocCtxt;
|
||||||
use rustc_ast::*;
|
use rustc_ast::*;
|
||||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
use rustc_data_structures::fx::FxHashMap;
|
||||||
use rustc_data_structures::sorted_map::SortedMap;
|
use rustc_data_structures::sorted_map::SortedMap;
|
||||||
use rustc_errors::struct_span_err;
|
use rustc_errors::struct_span_err;
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
|
@ -81,13 +81,10 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> {
|
||||||
is_in_loop_condition: false,
|
is_in_loop_condition: false,
|
||||||
is_in_trait_impl: false,
|
is_in_trait_impl: false,
|
||||||
is_in_dyn_type: false,
|
is_in_dyn_type: false,
|
||||||
anonymous_lifetime_mode: AnonymousLifetimeMode::PassThrough,
|
|
||||||
generator_kind: None,
|
generator_kind: None,
|
||||||
task_context: None,
|
task_context: None,
|
||||||
current_item: None,
|
current_item: None,
|
||||||
lifetimes_to_define: Vec::new(),
|
captured_lifetimes: None,
|
||||||
is_collecting_anonymous_lifetimes: None,
|
|
||||||
in_scope_lifetimes: Vec::new(),
|
|
||||||
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()),
|
||||||
allow_into_future: Some([sym::into_future][..].into()),
|
allow_into_future: Some([sym::into_future][..].into()),
|
||||||
|
@ -143,32 +140,14 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> {
|
||||||
LocalDefId { local_def_index }
|
LocalDefId { local_def_index }
|
||||||
};
|
};
|
||||||
|
|
||||||
let parent_hir = self.lower_node(parent_id).unwrap().node().expect_item();
|
let parent_hir = self.lower_node(parent_id).unwrap();
|
||||||
self.with_lctx(item.id, |lctx| {
|
self.with_lctx(item.id, |lctx| {
|
||||||
// Evaluate with the lifetimes in `params` in-scope.
|
// Evaluate with the lifetimes in `params` in-scope.
|
||||||
// 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.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| param.name)
|
|
||||||
.collect();
|
|
||||||
}
|
|
||||||
hir::ItemKind::Trait(_, _, ref generics, ..) => {
|
|
||||||
lctx.in_scope_lifetimes = generics
|
|
||||||
.params
|
|
||||||
.iter()
|
|
||||||
.filter(|param| {
|
|
||||||
matches!(param.kind, hir::GenericParamKind::Lifetime { .. })
|
|
||||||
})
|
|
||||||
.map(|param| param.name)
|
|
||||||
.collect();
|
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
};
|
};
|
||||||
|
@ -276,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);
|
||||||
|
|
||||||
|
@ -288,20 +266,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
let body_id =
|
let body_id =
|
||||||
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) = this.add_in_band_defs(
|
let (generics, decl) =
|
||||||
generics,
|
this.add_implicit_generics(generics, id, |this, idty| {
|
||||||
fn_def_id,
|
|
||||||
AnonymousLifetimeMode::PassThrough,
|
|
||||||
|this, idty| {
|
|
||||||
let ret_id = asyncness.opt_return_id();
|
let ret_id = asyncness.opt_return_id();
|
||||||
this.lower_fn_decl(
|
this.lower_fn_decl(&decl, Some((id, idty)), FnDeclKind::Fn, ret_id)
|
||||||
&decl,
|
});
|
||||||
Some((fn_def_id, idty)),
|
|
||||||
FnDeclKind::Fn,
|
|
||||||
ret_id,
|
|
||||||
)
|
|
||||||
},
|
|
||||||
);
|
|
||||||
let sig = hir::FnSig {
|
let sig = hir::FnSig {
|
||||||
decl,
|
decl,
|
||||||
header: this.lower_fn_header(header),
|
header: this.lower_fn_header(header),
|
||||||
|
@ -339,12 +308,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
//
|
//
|
||||||
// type Foo = Foo1
|
// type Foo = Foo1
|
||||||
// opaque type Foo1: Trait
|
// opaque type Foo1: Trait
|
||||||
let ty = self.lower_ty(
|
let ty = self.lower_ty(ty, ImplTraitContext::TypeAliasesOpaqueTy);
|
||||||
ty,
|
|
||||||
ImplTraitContext::TypeAliasesOpaqueTy {
|
|
||||||
capturable_lifetimes: &mut FxHashSet::default(),
|
|
||||||
},
|
|
||||||
);
|
|
||||||
let mut generics = generics.clone();
|
let mut generics = generics.clone();
|
||||||
add_ty_alias_where_clause(&mut generics, where_clauses, true);
|
add_ty_alias_where_clause(&mut generics, where_clauses, true);
|
||||||
let generics = self.lower_generics(
|
let generics = self.lower_generics(
|
||||||
|
@ -419,12 +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_in_band_defs(
|
self.add_implicit_generics(ast_generics, id, |this, _| {
|
||||||
ast_generics,
|
|
||||||
lowered_trait_def_id,
|
|
||||||
AnonymousLifetimeMode::CreateParameter,
|
|
||||||
|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,
|
||||||
|
@ -436,16 +396,12 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
.lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::Type));
|
.lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::Type));
|
||||||
|
|
||||||
(trait_ref, lowered_ty)
|
(trait_ref, lowered_ty)
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
let new_impl_items =
|
|
||||||
self.with_in_scope_lifetime_defs(&ast_generics.params, |this| {
|
|
||||||
this.arena.alloc_from_iter(
|
|
||||||
impl_items.iter().map(|item| this.lower_impl_item_ref(item)),
|
|
||||||
)
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let new_impl_items = self
|
||||||
|
.arena
|
||||||
|
.alloc_from_iter(impl_items.iter().map(|item| self.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.
|
||||||
let has_val = true;
|
let has_val = true;
|
||||||
|
@ -692,18 +648,14 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
kind: match i.kind {
|
kind: match i.kind {
|
||||||
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)) = self.add_in_band_defs(
|
let (generics, (fn_dec, fn_args)) =
|
||||||
generics,
|
self.add_implicit_generics(generics, i.id, |this, _| {
|
||||||
def_id,
|
|
||||||
AnonymousLifetimeMode::PassThrough,
|
|
||||||
|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),
|
||||||
this.lower_fn_params_to_names(fdec),
|
this.lower_fn_params_to_names(fdec),
|
||||||
)
|
)
|
||||||
},
|
});
|
||||||
);
|
|
||||||
|
|
||||||
hir::ForeignItemKind::Fn(fn_dec, fn_args, generics)
|
hir::ForeignItemKind::Fn(fn_dec, fn_args, generics)
|
||||||
}
|
}
|
||||||
|
@ -810,13 +762,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
}
|
}
|
||||||
AssocItemKind::Fn(box Fn { ref sig, ref generics, body: None, .. }) => {
|
AssocItemKind::Fn(box Fn { ref sig, ref generics, body: None, .. }) => {
|
||||||
let names = self.lower_fn_params_to_names(&sig.decl);
|
let names = self.lower_fn_params_to_names(&sig.decl);
|
||||||
let (generics, sig) = self.lower_method_sig(
|
let (generics, sig) =
|
||||||
generics,
|
self.lower_method_sig(generics, sig, i.id, FnDeclKind::Trait, None);
|
||||||
sig,
|
|
||||||
trait_item_def_id,
|
|
||||||
FnDeclKind::Trait,
|
|
||||||
None,
|
|
||||||
);
|
|
||||||
(generics, hir::TraitItemKind::Fn(sig, hir::TraitFn::Required(names)))
|
(generics, hir::TraitItemKind::Fn(sig, hir::TraitFn::Required(names)))
|
||||||
}
|
}
|
||||||
AssocItemKind::Fn(box Fn { ref sig, ref generics, body: Some(ref body), .. }) => {
|
AssocItemKind::Fn(box Fn { ref sig, ref generics, body: Some(ref body), .. }) => {
|
||||||
|
@ -826,7 +773,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
let (generics, sig) = self.lower_method_sig(
|
let (generics, sig) = self.lower_method_sig(
|
||||||
generics,
|
generics,
|
||||||
sig,
|
sig,
|
||||||
trait_item_def_id,
|
i.id,
|
||||||
FnDeclKind::Trait,
|
FnDeclKind::Trait,
|
||||||
asyncness.opt_return_id(),
|
asyncness.opt_return_id(),
|
||||||
);
|
);
|
||||||
|
@ -900,8 +847,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lower_impl_item(&mut self, i: &AssocItem) -> &'hir hir::ImplItem<'hir> {
|
fn lower_impl_item(&mut self, i: &AssocItem) -> &'hir hir::ImplItem<'hir> {
|
||||||
let impl_item_def_id = self.resolver.local_def_id(i.id);
|
|
||||||
|
|
||||||
let (generics, kind) = match &i.kind {
|
let (generics, kind) = match &i.kind {
|
||||||
AssocItemKind::Const(_, ty, expr) => {
|
AssocItemKind::Const(_, ty, expr) => {
|
||||||
let ty = self.lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::Type));
|
let ty = self.lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::Type));
|
||||||
|
@ -918,7 +863,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
let (generics, sig) = self.lower_method_sig(
|
let (generics, sig) = self.lower_method_sig(
|
||||||
generics,
|
generics,
|
||||||
sig,
|
sig,
|
||||||
impl_item_def_id,
|
i.id,
|
||||||
if self.is_in_trait_impl { FnDeclKind::Impl } else { FnDeclKind::Inherent },
|
if self.is_in_trait_impl { FnDeclKind::Impl } else { FnDeclKind::Inherent },
|
||||||
asyncness.opt_return_id(),
|
asyncness.opt_return_id(),
|
||||||
);
|
);
|
||||||
|
@ -938,12 +883,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
hir::ImplItemKind::TyAlias(ty)
|
hir::ImplItemKind::TyAlias(ty)
|
||||||
}
|
}
|
||||||
Some(ty) => {
|
Some(ty) => {
|
||||||
let ty = self.lower_ty(
|
let ty = self.lower_ty(ty, ImplTraitContext::TypeAliasesOpaqueTy);
|
||||||
ty,
|
|
||||||
ImplTraitContext::TypeAliasesOpaqueTy {
|
|
||||||
capturable_lifetimes: &mut FxHashSet::default(),
|
|
||||||
},
|
|
||||||
);
|
|
||||||
hir::ImplItemKind::TyAlias(ty)
|
hir::ImplItemKind::TyAlias(ty)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -1283,17 +1223,14 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
&mut self,
|
&mut self,
|
||||||
generics: &Generics,
|
generics: &Generics,
|
||||||
sig: &FnSig,
|
sig: &FnSig,
|
||||||
fn_def_id: LocalDefId,
|
id: NodeId,
|
||||||
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 header = self.lower_fn_header(sig.header);
|
let header = self.lower_fn_header(sig.header);
|
||||||
let (generics, decl) = self.add_in_band_defs(
|
let (generics, decl) = self.add_implicit_generics(generics, id, |this, idty| {
|
||||||
generics,
|
this.lower_fn_decl(&sig.decl, Some((id, idty)), kind, is_async)
|
||||||
fn_def_id,
|
});
|
||||||
AnonymousLifetimeMode::PassThrough,
|
|
||||||
|this, idty| this.lower_fn_decl(&sig.decl, Some((fn_def_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) })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1418,14 +1355,12 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lower_where_clause(&mut self, wc: &WhereClause) -> hir::WhereClause<'hir> {
|
fn lower_where_clause(&mut self, wc: &WhereClause) -> hir::WhereClause<'hir> {
|
||||||
self.with_anonymous_lifetime_mode(AnonymousLifetimeMode::ReportError, |this| {
|
hir::WhereClause {
|
||||||
hir::WhereClause {
|
predicates: self.arena.alloc_from_iter(
|
||||||
predicates: this.arena.alloc_from_iter(
|
wc.predicates.iter().map(|predicate| self.lower_where_predicate(predicate)),
|
||||||
wc.predicates.iter().map(|predicate| this.lower_where_predicate(predicate)),
|
),
|
||||||
),
|
span: self.lower_span(wc.span),
|
||||||
span: this.lower_span(wc.span),
|
}
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lower_where_predicate(&mut self, pred: &WherePredicate) -> hir::WherePredicate<'hir> {
|
fn lower_where_predicate(&mut self, pred: &WherePredicate) -> hir::WherePredicate<'hir> {
|
||||||
|
@ -1435,24 +1370,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: self
|
||||||
bounded_ty: this.lower_ty(
|
.lower_ty(bounded_ty, ImplTraitContext::Disallowed(ImplTraitPosition::Type)),
|
||||||
bounded_ty,
|
bounds: self.arena.alloc_from_iter(bounds.iter().map(|bound| {
|
||||||
ImplTraitContext::Disallowed(ImplTraitPosition::Type),
|
self.lower_param_bound(
|
||||||
),
|
bound,
|
||||||
bounds: this.arena.alloc_from_iter(bounds.iter().map(|bound| {
|
ImplTraitContext::Disallowed(ImplTraitPosition::Bound),
|
||||||
this.lower_param_bound(
|
)
|
||||||
bound,
|
})),
|
||||||
ImplTraitContext::Disallowed(ImplTraitPosition::Bound),
|
span: self.lower_span(span),
|
||||||
)
|
|
||||||
})),
|
|
||||||
span: this.lower_span(span),
|
|
||||||
})
|
|
||||||
}),
|
}),
|
||||||
WherePredicate::RegionPredicate(WhereRegionPredicate {
|
WherePredicate::RegionPredicate(WhereRegionPredicate {
|
||||||
ref lifetime,
|
ref lifetime,
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,15 +1,14 @@
|
||||||
use crate::ImplTraitPosition;
|
use crate::ImplTraitPosition;
|
||||||
|
|
||||||
use super::{AnonymousLifetimeMode, ImplTraitContext, LoweringContext, ParamMode};
|
use super::{GenericArgsCtor, LifetimeRes, ParenthesizedGenericArgs};
|
||||||
use super::{GenericArgsCtor, ParenthesizedGenericArgs};
|
use super::{ImplTraitContext, LoweringContext, ParamMode};
|
||||||
|
|
||||||
use rustc_ast::{self as ast, *};
|
use rustc_ast::{self as ast, *};
|
||||||
use rustc_errors::{struct_span_err, Applicability};
|
use rustc_errors::{struct_span_err, Applicability};
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_hir::def::{DefKind, PartialRes, Res};
|
use rustc_hir::def::{DefKind, PartialRes, Res};
|
||||||
use rustc_hir::def_id::DefId;
|
|
||||||
use rustc_hir::GenericArg;
|
use rustc_hir::GenericArg;
|
||||||
use rustc_span::symbol::Ident;
|
use rustc_span::symbol::{kw, Ident};
|
||||||
use rustc_span::{BytePos, Span, DUMMY_SP};
|
use rustc_span::{BytePos, Span, DUMMY_SP};
|
||||||
|
|
||||||
use smallvec::smallvec;
|
use smallvec::smallvec;
|
||||||
|
@ -47,30 +46,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||||
_ => param_mode,
|
_ => param_mode,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Figure out if this is a type/trait segment,
|
|
||||||
// which may need lifetime elision performed.
|
|
||||||
let parent_def_id = |this: &mut Self, def_id: DefId| DefId {
|
|
||||||
krate: def_id.krate,
|
|
||||||
index: this.resolver.def_key(def_id).parent.expect("missing parent"),
|
|
||||||
};
|
|
||||||
let type_def_id = match partial_res.base_res() {
|
|
||||||
Res::Def(DefKind::AssocTy, def_id) if i + 2 == proj_start => {
|
|
||||||
Some(parent_def_id(self, def_id))
|
|
||||||
}
|
|
||||||
Res::Def(DefKind::Variant, def_id) if i + 1 == proj_start => {
|
|
||||||
Some(parent_def_id(self, def_id))
|
|
||||||
}
|
|
||||||
Res::Def(DefKind::Struct, def_id)
|
|
||||||
| Res::Def(DefKind::Union, def_id)
|
|
||||||
| Res::Def(DefKind::Enum, def_id)
|
|
||||||
| Res::Def(DefKind::TyAlias, def_id)
|
|
||||||
| Res::Def(DefKind::Trait, def_id)
|
|
||||||
if i + 1 == proj_start =>
|
|
||||||
{
|
|
||||||
Some(def_id)
|
|
||||||
}
|
|
||||||
_ => None,
|
|
||||||
};
|
|
||||||
let parenthesized_generic_args = match partial_res.base_res() {
|
let parenthesized_generic_args = match partial_res.base_res() {
|
||||||
// `a::b::Trait(Args)`
|
// `a::b::Trait(Args)`
|
||||||
Res::Def(DefKind::Trait, _) if i + 1 == proj_start => {
|
Res::Def(DefKind::Trait, _) if i + 1 == proj_start => {
|
||||||
|
@ -90,13 +65,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||||
_ => ParenthesizedGenericArgs::Err,
|
_ => ParenthesizedGenericArgs::Err,
|
||||||
};
|
};
|
||||||
|
|
||||||
let num_lifetimes = type_def_id
|
|
||||||
.map_or(0, |def_id| self.resolver.item_generics_num_lifetimes(def_id));
|
|
||||||
self.lower_path_segment(
|
self.lower_path_segment(
|
||||||
p.span,
|
p.span,
|
||||||
segment,
|
segment,
|
||||||
param_mode,
|
param_mode,
|
||||||
num_lifetimes,
|
|
||||||
parenthesized_generic_args,
|
parenthesized_generic_args,
|
||||||
itctx.reborrow(),
|
itctx.reborrow(),
|
||||||
)
|
)
|
||||||
|
@ -143,7 +115,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||||
p.span,
|
p.span,
|
||||||
segment,
|
segment,
|
||||||
param_mode,
|
param_mode,
|
||||||
0,
|
|
||||||
ParenthesizedGenericArgs::Err,
|
ParenthesizedGenericArgs::Err,
|
||||||
itctx.reborrow(),
|
itctx.reborrow(),
|
||||||
));
|
));
|
||||||
|
@ -184,7 +155,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||||
p.span,
|
p.span,
|
||||||
segment,
|
segment,
|
||||||
param_mode,
|
param_mode,
|
||||||
0,
|
|
||||||
ParenthesizedGenericArgs::Err,
|
ParenthesizedGenericArgs::Err,
|
||||||
ImplTraitContext::Disallowed(ImplTraitPosition::Path),
|
ImplTraitContext::Disallowed(ImplTraitPosition::Path),
|
||||||
)
|
)
|
||||||
|
@ -209,14 +179,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||||
path_span: Span,
|
path_span: Span,
|
||||||
segment: &PathSegment,
|
segment: &PathSegment,
|
||||||
param_mode: ParamMode,
|
param_mode: ParamMode,
|
||||||
expected_lifetimes: usize,
|
|
||||||
parenthesized_generic_args: ParenthesizedGenericArgs,
|
parenthesized_generic_args: ParenthesizedGenericArgs,
|
||||||
itctx: ImplTraitContext<'_, 'hir>,
|
itctx: ImplTraitContext<'_, 'hir>,
|
||||||
) -> hir::PathSegment<'hir> {
|
) -> hir::PathSegment<'hir> {
|
||||||
debug!(
|
debug!("path_span: {:?}, lower_path_segment(segment: {:?})", path_span, segment,);
|
||||||
"path_span: {:?}, lower_path_segment(segment: {:?}, expected_lifetimes: {:?})",
|
|
||||||
path_span, segment, expected_lifetimes
|
|
||||||
);
|
|
||||||
let (mut generic_args, infer_args) = if let Some(ref generic_args) = segment.args {
|
let (mut generic_args, infer_args) = if let Some(ref generic_args) = segment.args {
|
||||||
let msg = "parenthesized type parameters may only be used with a `Fn` trait";
|
let msg = "parenthesized type parameters may only be used with a `Fn` trait";
|
||||||
match **generic_args {
|
match **generic_args {
|
||||||
|
@ -224,7 +190,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||||
self.lower_angle_bracketed_parameter_data(data, param_mode, itctx)
|
self.lower_angle_bracketed_parameter_data(data, param_mode, itctx)
|
||||||
}
|
}
|
||||||
GenericArgs::Parenthesized(ref data) => match parenthesized_generic_args {
|
GenericArgs::Parenthesized(ref data) => match parenthesized_generic_args {
|
||||||
ParenthesizedGenericArgs::Ok => self.lower_parenthesized_parameter_data(data),
|
ParenthesizedGenericArgs::Ok => {
|
||||||
|
self.lower_parenthesized_parameter_data(segment.id, data)
|
||||||
|
}
|
||||||
ParenthesizedGenericArgs::Err => {
|
ParenthesizedGenericArgs::Err => {
|
||||||
let mut err = struct_span_err!(self.sess, data.span, E0214, "{}", msg);
|
let mut err = struct_span_err!(self.sess, data.span, E0214, "{}", msg);
|
||||||
err.span_label(data.span, "only `Fn` traits may use parentheses");
|
err.span_label(data.span, "only `Fn` traits may use parentheses");
|
||||||
|
@ -274,33 +242,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||||
|
|
||||||
let has_lifetimes =
|
let has_lifetimes =
|
||||||
generic_args.args.iter().any(|arg| matches!(arg, GenericArg::Lifetime(_)));
|
generic_args.args.iter().any(|arg| matches!(arg, GenericArg::Lifetime(_)));
|
||||||
if !generic_args.parenthesized && !has_lifetimes && expected_lifetimes > 0 {
|
if !generic_args.parenthesized && !has_lifetimes {
|
||||||
// Note: these spans are used for diagnostics when they can't be inferred.
|
self.maybe_insert_elided_lifetimes_in_path(
|
||||||
// See rustc_resolve::late::lifetimes::LifetimeContext::add_missing_lifetime_specifiers_label
|
path_span,
|
||||||
let elided_lifetime_span = if generic_args.span.is_empty() {
|
segment.id,
|
||||||
// If there are no brackets, use the identifier span.
|
segment.ident.span,
|
||||||
// HACK: we use find_ancestor_inside to properly suggest elided spans in paths
|
&mut generic_args,
|
||||||
// originating from macros, since the segment's span might be from a macro arg.
|
);
|
||||||
segment.ident.span.find_ancestor_inside(path_span).unwrap_or(path_span)
|
|
||||||
} else if generic_args.is_empty() {
|
|
||||||
// If there are brackets, but not generic arguments, then use the opening bracket
|
|
||||||
generic_args.span.with_hi(generic_args.span.lo() + BytePos(1))
|
|
||||||
} else {
|
|
||||||
// Else use an empty span right after the opening bracket.
|
|
||||||
generic_args.span.with_lo(generic_args.span.lo() + BytePos(1)).shrink_to_lo()
|
|
||||||
};
|
|
||||||
generic_args.args = self
|
|
||||||
.elided_path_lifetimes(elided_lifetime_span, expected_lifetimes)
|
|
||||||
.map(GenericArg::Lifetime)
|
|
||||||
.chain(generic_args.args.into_iter())
|
|
||||||
.collect();
|
|
||||||
if let (ParamMode::Explicit, AnonymousLifetimeMode::CreateParameter) =
|
|
||||||
(param_mode, self.anonymous_lifetime_mode)
|
|
||||||
{
|
|
||||||
// Late resolver should have issued the error.
|
|
||||||
self.sess
|
|
||||||
.delay_span_bug(elided_lifetime_span, "implicit lifetime not allowed here");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let res = self.expect_full_res(segment.id);
|
let res = self.expect_full_res(segment.id);
|
||||||
|
@ -323,6 +271,49 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn maybe_insert_elided_lifetimes_in_path(
|
||||||
|
&mut self,
|
||||||
|
path_span: Span,
|
||||||
|
segment_id: NodeId,
|
||||||
|
segment_ident_span: Span,
|
||||||
|
generic_args: &mut GenericArgsCtor<'hir>,
|
||||||
|
) {
|
||||||
|
let (start, end) = match self.resolver.get_lifetime_res(segment_id) {
|
||||||
|
Some(LifetimeRes::ElidedAnchor { start, end }) => (start, end),
|
||||||
|
None => return,
|
||||||
|
Some(_) => panic!(),
|
||||||
|
};
|
||||||
|
let expected_lifetimes = end.as_usize() - start.as_usize();
|
||||||
|
debug!(expected_lifetimes);
|
||||||
|
|
||||||
|
// Note: these spans are used for diagnostics when they can't be inferred.
|
||||||
|
// See rustc_resolve::late::lifetimes::LifetimeContext::add_missing_lifetime_specifiers_label
|
||||||
|
let elided_lifetime_span = if generic_args.span.is_empty() {
|
||||||
|
// If there are no brackets, use the identifier span.
|
||||||
|
// HACK: we use find_ancestor_inside to properly suggest elided spans in paths
|
||||||
|
// originating from macros, since the segment's span might be from a macro arg.
|
||||||
|
segment_ident_span.find_ancestor_inside(path_span).unwrap_or(path_span)
|
||||||
|
} else if generic_args.is_empty() {
|
||||||
|
// If there are brackets, but not generic arguments, then use the opening bracket
|
||||||
|
generic_args.span.with_hi(generic_args.span.lo() + BytePos(1))
|
||||||
|
} else {
|
||||||
|
// Else use an empty span right after the opening bracket.
|
||||||
|
generic_args.span.with_lo(generic_args.span.lo() + BytePos(1)).shrink_to_lo()
|
||||||
|
};
|
||||||
|
|
||||||
|
generic_args.args.insert_many(
|
||||||
|
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::UnderscoreLifetime, elided_lifetime_span),
|
||||||
|
});
|
||||||
|
GenericArg::Lifetime(l)
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn lower_angle_bracketed_parameter_data(
|
pub(crate) fn lower_angle_bracketed_parameter_data(
|
||||||
&mut self,
|
&mut self,
|
||||||
data: &AngleBracketedArgs,
|
data: &AngleBracketedArgs,
|
||||||
|
@ -354,6 +345,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||||
|
|
||||||
fn lower_parenthesized_parameter_data(
|
fn lower_parenthesized_parameter_data(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
id: NodeId,
|
||||||
data: &ParenthesizedArgs,
|
data: &ParenthesizedArgs,
|
||||||
) -> (GenericArgsCtor<'hir>, bool) {
|
) -> (GenericArgsCtor<'hir>, bool) {
|
||||||
// Switch to `PassThrough` mode for anonymous lifetimes; this
|
// Switch to `PassThrough` mode for anonymous lifetimes; this
|
||||||
|
@ -361,7 +353,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||||
// a hidden lifetime parameter. This is needed for backwards
|
// a hidden lifetime parameter. This is needed for backwards
|
||||||
// compatibility, even in contexts like an impl header where
|
// compatibility, even in contexts like an impl header where
|
||||||
// we generally don't permit such things (see #51008).
|
// we generally don't permit such things (see #51008).
|
||||||
self.with_anonymous_lifetime_mode(AnonymousLifetimeMode::PassThrough, |this| {
|
self.with_lifetime_binder(id, |this| {
|
||||||
let ParenthesizedArgs { span, inputs, inputs_span, output } = data;
|
let ParenthesizedArgs { span, inputs, inputs_span, output } = data;
|
||||||
let inputs = this.arena.alloc_from_iter(inputs.iter().map(|ty| {
|
let inputs = this.arena.alloc_from_iter(inputs.iter().map(|ty| {
|
||||||
this.lower_ty_direct(
|
this.lower_ty_direct(
|
||||||
|
|
|
@ -93,8 +93,6 @@ pub enum LifetimeName {
|
||||||
Param(ParamName),
|
Param(ParamName),
|
||||||
|
|
||||||
/// User wrote nothing (e.g., the lifetime in `&u32`).
|
/// User wrote nothing (e.g., the lifetime in `&u32`).
|
||||||
///
|
|
||||||
/// The bool indicates whether the user should have written something.
|
|
||||||
Implicit,
|
Implicit,
|
||||||
|
|
||||||
/// Implicit lifetime in a context like `dyn Foo`. This is
|
/// Implicit lifetime in a context like `dyn Foo`. This is
|
||||||
|
@ -444,9 +442,6 @@ pub enum GenericBound<'hir> {
|
||||||
Outlives(Lifetime),
|
Outlives(Lifetime),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
|
|
||||||
rustc_data_structures::static_assert_size!(GenericBound<'_>, 48);
|
|
||||||
|
|
||||||
impl GenericBound<'_> {
|
impl GenericBound<'_> {
|
||||||
pub fn trait_ref(&self) -> Option<&TraitRef<'_>> {
|
pub fn trait_ref(&self) -> Option<&TraitRef<'_>> {
|
||||||
match self {
|
match self {
|
||||||
|
@ -3330,6 +3325,7 @@ mod size_asserts {
|
||||||
rustc_data_structures::static_assert_size!(super::Pat<'static>, 88);
|
rustc_data_structures::static_assert_size!(super::Pat<'static>, 88);
|
||||||
rustc_data_structures::static_assert_size!(super::QPath<'static>, 24);
|
rustc_data_structures::static_assert_size!(super::QPath<'static>, 24);
|
||||||
rustc_data_structures::static_assert_size!(super::Ty<'static>, 72);
|
rustc_data_structures::static_assert_size!(super::Ty<'static>, 72);
|
||||||
|
rustc_data_structures::static_assert_size!(super::GenericBound<'_>, 48);
|
||||||
|
|
||||||
rustc_data_structures::static_assert_size!(super::Item<'static>, 160);
|
rustc_data_structures::static_assert_size!(super::Item<'static>, 160);
|
||||||
rustc_data_structures::static_assert_size!(super::TraitItem<'static>, 128);
|
rustc_data_structures::static_assert_size!(super::TraitItem<'static>, 128);
|
||||||
|
|
|
@ -14,13 +14,15 @@ use crate::{ResolutionError, Resolver, Segment, UseError};
|
||||||
use rustc_ast::ptr::P;
|
use rustc_ast::ptr::P;
|
||||||
use rustc_ast::visit::{self, AssocCtxt, BoundKind, FnCtxt, FnKind, Visitor};
|
use rustc_ast::visit::{self, AssocCtxt, BoundKind, FnCtxt, FnKind, Visitor};
|
||||||
use rustc_ast::*;
|
use rustc_ast::*;
|
||||||
use rustc_ast_lowering::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};
|
||||||
use rustc_hir::def_id::{DefId, CRATE_DEF_ID};
|
use rustc_hir::def_id::{DefId, CRATE_DEF_ID};
|
||||||
|
use rustc_hir::definitions::DefPathData;
|
||||||
use rustc_hir::{PrimTy, TraitCandidate};
|
use rustc_hir::{PrimTy, TraitCandidate};
|
||||||
|
use rustc_index::vec::Idx;
|
||||||
use rustc_middle::ty::DefIdTree;
|
use rustc_middle::ty::DefIdTree;
|
||||||
use rustc_middle::{bug, span_bug};
|
use rustc_middle::{bug, span_bug};
|
||||||
use rustc_session::lint;
|
use rustc_session::lint;
|
||||||
|
@ -195,7 +197,7 @@ enum LifetimeRibKind {
|
||||||
Item,
|
Item,
|
||||||
|
|
||||||
/// This rib declares generic parameters.
|
/// This rib declares generic parameters.
|
||||||
Generics { span: Span, kind: LifetimeBinderKind },
|
Generics { parent: NodeId, span: Span, kind: LifetimeBinderKind },
|
||||||
|
|
||||||
/// For **Modern** cases, create a new anonymous region parameter
|
/// For **Modern** cases, create a new anonymous region parameter
|
||||||
/// and reference that.
|
/// and reference that.
|
||||||
|
@ -204,7 +206,7 @@ enum LifetimeRibKind {
|
||||||
/// `resolve_lifetime` code.
|
/// `resolve_lifetime` code.
|
||||||
///
|
///
|
||||||
/// For **Deprecated** cases, report an error.
|
/// For **Deprecated** cases, report an error.
|
||||||
AnonymousCreateParameter,
|
AnonymousCreateParameter(NodeId),
|
||||||
|
|
||||||
/// Give a hard error when either `&` or `'_` is written. Used to
|
/// Give a hard error when either `&` or `'_` is written. Used to
|
||||||
/// rule out things like `where T: Foo<'_>`. Does not imply an
|
/// rule out things like `where T: Foo<'_>`. Does not imply an
|
||||||
|
@ -212,7 +214,7 @@ enum LifetimeRibKind {
|
||||||
AnonymousReportError,
|
AnonymousReportError,
|
||||||
|
|
||||||
/// Pass responsibility to `resolve_lifetime` code for all cases.
|
/// Pass responsibility to `resolve_lifetime` code for all cases.
|
||||||
AnonymousPassThrough,
|
AnonymousPassThrough(NodeId),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug)]
|
#[derive(Copy, Clone, Debug)]
|
||||||
|
@ -242,7 +244,8 @@ impl LifetimeBinderKind {
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct LifetimeRib {
|
struct LifetimeRib {
|
||||||
kind: LifetimeRibKind,
|
kind: LifetimeRibKind,
|
||||||
bindings: IdentMap<()>,
|
// We need to preserve insertion order for async fns.
|
||||||
|
bindings: FxIndexMap<Ident, (NodeId, LifetimeRes)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LifetimeRib {
|
impl LifetimeRib {
|
||||||
|
@ -581,12 +584,19 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
|
||||||
self.with_generic_param_rib(
|
self.with_generic_param_rib(
|
||||||
&bare_fn.generic_params,
|
&bare_fn.generic_params,
|
||||||
NormalRibKind,
|
NormalRibKind,
|
||||||
LifetimeRibKind::Generics { kind: LifetimeBinderKind::BareFnType, span },
|
LifetimeRibKind::Generics {
|
||||||
|
parent: ty.id,
|
||||||
|
kind: LifetimeBinderKind::BareFnType,
|
||||||
|
span,
|
||||||
|
},
|
||||||
|this| {
|
|this| {
|
||||||
this.with_lifetime_rib(LifetimeRibKind::AnonymousPassThrough, |this| {
|
this.with_lifetime_rib(
|
||||||
this.visit_generic_param_vec(&bare_fn.generic_params, false);
|
LifetimeRibKind::AnonymousPassThrough(ty.id),
|
||||||
visit::walk_fn_decl(this, &bare_fn.decl);
|
|this| {
|
||||||
});
|
this.visit_generic_param_vec(&bare_fn.generic_params, false);
|
||||||
|
visit::walk_fn_decl(this, &bare_fn.decl);
|
||||||
|
},
|
||||||
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
self.diagnostic_metadata.current_trait_object = prev;
|
self.diagnostic_metadata.current_trait_object = prev;
|
||||||
|
@ -604,7 +614,11 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
|
||||||
self.with_generic_param_rib(
|
self.with_generic_param_rib(
|
||||||
&tref.bound_generic_params,
|
&tref.bound_generic_params,
|
||||||
NormalRibKind,
|
NormalRibKind,
|
||||||
LifetimeRibKind::Generics { kind: LifetimeBinderKind::PolyTrait, span },
|
LifetimeRibKind::Generics {
|
||||||
|
parent: tref.trait_ref.ref_id,
|
||||||
|
kind: LifetimeBinderKind::PolyTrait,
|
||||||
|
span,
|
||||||
|
},
|
||||||
|this| {
|
|this| {
|
||||||
this.visit_generic_param_vec(&tref.bound_generic_params, false);
|
this.visit_generic_param_vec(&tref.bound_generic_params, false);
|
||||||
this.smart_resolve_path(
|
this.smart_resolve_path(
|
||||||
|
@ -625,6 +639,7 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
|
||||||
&generics.params,
|
&generics.params,
|
||||||
ItemRibKind(HasGenericParams::Yes),
|
ItemRibKind(HasGenericParams::Yes),
|
||||||
LifetimeRibKind::Generics {
|
LifetimeRibKind::Generics {
|
||||||
|
parent: foreign_item.id,
|
||||||
kind: LifetimeBinderKind::Item,
|
kind: LifetimeBinderKind::Item,
|
||||||
span: generics.span,
|
span: generics.span,
|
||||||
},
|
},
|
||||||
|
@ -638,6 +653,7 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
|
||||||
&generics.params,
|
&generics.params,
|
||||||
ItemRibKind(HasGenericParams::Yes),
|
ItemRibKind(HasGenericParams::Yes),
|
||||||
LifetimeRibKind::Generics {
|
LifetimeRibKind::Generics {
|
||||||
|
parent: foreign_item.id,
|
||||||
kind: LifetimeBinderKind::Function,
|
kind: LifetimeBinderKind::Function,
|
||||||
span: generics.span,
|
span: generics.span,
|
||||||
},
|
},
|
||||||
|
@ -655,13 +671,13 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn visit_fn(&mut self, fn_kind: FnKind<'ast>, sp: Span, _: NodeId) {
|
fn visit_fn(&mut self, fn_kind: FnKind<'ast>, sp: Span, fn_id: NodeId) {
|
||||||
let rib_kind = match fn_kind {
|
let rib_kind = match fn_kind {
|
||||||
// Bail if the function is foreign, and thus cannot validly have
|
// Bail if the function is foreign, and thus cannot validly have
|
||||||
// a body, or if there's no body for some other reason.
|
// a body, or if there's no body for some other reason.
|
||||||
FnKind::Fn(FnCtxt::Foreign, _, sig, _, generics, _)
|
FnKind::Fn(FnCtxt::Foreign, _, sig, _, generics, _)
|
||||||
| FnKind::Fn(_, _, sig, _, generics, None) => {
|
| FnKind::Fn(_, _, sig, _, generics, None) => {
|
||||||
self.with_lifetime_rib(LifetimeRibKind::AnonymousPassThrough, |this| {
|
self.with_lifetime_rib(LifetimeRibKind::AnonymousPassThrough(fn_id), |this| {
|
||||||
// We don't need to deal with patterns in parameters, because
|
// We don't need to deal with patterns in parameters, because
|
||||||
// they are not possible for foreign or bodiless functions.
|
// they are not possible for foreign or bodiless functions.
|
||||||
this.visit_fn_header(&sig.header);
|
this.visit_fn_header(&sig.header);
|
||||||
|
@ -691,20 +707,50 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
|
||||||
this.visit_generics(generics);
|
this.visit_generics(generics);
|
||||||
}
|
}
|
||||||
|
|
||||||
if async_node_id.is_some() {
|
if let Some(async_node_id) = async_node_id {
|
||||||
// In `async fn`, argument-position elided lifetimes
|
// In `async fn`, argument-position elided lifetimes
|
||||||
// must be transformed into fresh generic parameters so that
|
// must be transformed into fresh generic parameters so that
|
||||||
// they can be applied to the opaque `impl Trait` return type.
|
// they can be applied to the opaque `impl Trait` return type.
|
||||||
this.with_lifetime_rib(LifetimeRibKind::AnonymousCreateParameter, |this| {
|
this.with_lifetime_rib(
|
||||||
// Add each argument to the rib.
|
LifetimeRibKind::AnonymousCreateParameter(fn_id),
|
||||||
this.resolve_params(&declaration.inputs)
|
|this| {
|
||||||
});
|
// Add each argument to the rib.
|
||||||
|
this.resolve_params(&declaration.inputs)
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
this.with_lifetime_rib(LifetimeRibKind::AnonymousPassThrough, |this| {
|
// Construct the list of in-scope lifetime parameters for async lowering.
|
||||||
visit::walk_fn_ret_ty(this, &declaration.output)
|
// 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(
|
||||||
|
LifetimeRibKind::AnonymousPassThrough(async_node_id),
|
||||||
|
|this| visit::walk_fn_ret_ty(this, &declaration.output),
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
this.with_lifetime_rib(LifetimeRibKind::AnonymousPassThrough, |this| {
|
this.with_lifetime_rib(LifetimeRibKind::AnonymousPassThrough(fn_id), |this| {
|
||||||
// Add each argument to the rib.
|
// Add each argument to the rib.
|
||||||
this.resolve_params(&declaration.inputs);
|
this.resolve_params(&declaration.inputs);
|
||||||
|
|
||||||
|
@ -716,13 +762,12 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
|
||||||
// Be sure not to set this until the function signature has been resolved.
|
// Be sure not to set this until the function signature has been resolved.
|
||||||
let previous_state = replace(&mut this.in_func_body, true);
|
let previous_state = replace(&mut this.in_func_body, true);
|
||||||
// Resolve the function body, potentially inside the body of an async closure
|
// Resolve the function body, potentially inside the body of an async closure
|
||||||
this.with_lifetime_rib(
|
this.with_lifetime_rib(LifetimeRibKind::AnonymousPassThrough(fn_id), |this| {
|
||||||
LifetimeRibKind::AnonymousPassThrough,
|
match fn_kind {
|
||||||
|this| match fn_kind {
|
|
||||||
FnKind::Fn(.., body) => walk_list!(this, visit_block, body),
|
FnKind::Fn(.., body) => walk_list!(this, visit_block, body),
|
||||||
FnKind::Closure(_, body) => this.visit_expr(body),
|
FnKind::Closure(_, body) => this.visit_expr(body),
|
||||||
},
|
}
|
||||||
);
|
});
|
||||||
|
|
||||||
debug!("(resolving function) leaving function");
|
debug!("(resolving function) leaving function");
|
||||||
this.in_func_body = previous_state;
|
this.in_func_body = previous_state;
|
||||||
|
@ -801,10 +846,10 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
|
||||||
if let Some(ref args) = path_segment.args {
|
if let Some(ref args) = path_segment.args {
|
||||||
match &**args {
|
match &**args {
|
||||||
GenericArgs::AngleBracketed(..) => visit::walk_generic_args(self, path_span, args),
|
GenericArgs::AngleBracketed(..) => visit::walk_generic_args(self, path_span, args),
|
||||||
GenericArgs::Parenthesized(..) => self
|
GenericArgs::Parenthesized(..) => self.with_lifetime_rib(
|
||||||
.with_lifetime_rib(LifetimeRibKind::AnonymousPassThrough, |this| {
|
LifetimeRibKind::AnonymousPassThrough(path_segment.id),
|
||||||
visit::walk_generic_args(this, path_span, args)
|
|this| visit::walk_generic_args(this, path_span, args),
|
||||||
}),
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -830,7 +875,11 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
|
||||||
this.with_generic_param_rib(
|
this.with_generic_param_rib(
|
||||||
&bound_generic_params,
|
&bound_generic_params,
|
||||||
NormalRibKind,
|
NormalRibKind,
|
||||||
LifetimeRibKind::Generics { kind: LifetimeBinderKind::WhereBound, span },
|
LifetimeRibKind::Generics {
|
||||||
|
parent: bounded_ty.id,
|
||||||
|
kind: LifetimeBinderKind::WhereBound,
|
||||||
|
span,
|
||||||
|
},
|
||||||
|this| {
|
|this| {
|
||||||
this.visit_generic_param_vec(&bound_generic_params, false);
|
this.visit_generic_param_vec(&bound_generic_params, false);
|
||||||
this.visit_ty(bounded_ty);
|
this.visit_ty(bounded_ty);
|
||||||
|
@ -1092,6 +1141,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
||||||
let ident = lifetime.ident;
|
let ident = lifetime.ident;
|
||||||
|
|
||||||
if ident.name == kw::StaticLifetime {
|
if ident.name == kw::StaticLifetime {
|
||||||
|
self.record_lifetime_res(lifetime.id, LifetimeRes::Static);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1103,7 +1153,8 @@ 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(_) = rib.bindings.get_key_value(&normalized_ident) {
|
if let Some(&(_, region)) = rib.bindings.get(&normalized_ident) {
|
||||||
|
self.record_lifetime_res(lifetime.id, region);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1123,6 +1174,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
||||||
}
|
}
|
||||||
|
|
||||||
self.emit_undeclared_lifetime_error(lifetime, outer_res);
|
self.emit_undeclared_lifetime_error(lifetime, outer_res);
|
||||||
|
self.record_lifetime_res(lifetime.id, LifetimeRes::Error);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tracing::instrument(level = "debug", skip(self))]
|
#[tracing::instrument(level = "debug", skip(self))]
|
||||||
|
@ -1132,6 +1184,10 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
||||||
for i in (0..self.lifetime_ribs.len()).rev() {
|
for i in (0..self.lifetime_ribs.len()).rev() {
|
||||||
let rib = &mut self.lifetime_ribs[i];
|
let rib = &mut self.lifetime_ribs[i];
|
||||||
match rib.kind {
|
match rib.kind {
|
||||||
|
LifetimeRibKind::AnonymousCreateParameter(item_node_id) => {
|
||||||
|
self.create_fresh_lifetime(lifetime.id, lifetime.ident, item_node_id);
|
||||||
|
return;
|
||||||
|
}
|
||||||
LifetimeRibKind::AnonymousReportError => {
|
LifetimeRibKind::AnonymousReportError => {
|
||||||
let (msg, note) = if elided {
|
let (msg, note) = if elided {
|
||||||
(
|
(
|
||||||
|
@ -1151,23 +1207,64 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
||||||
.span_label(lifetime.ident.span, note)
|
.span_label(lifetime.ident.span, note)
|
||||||
.emit();
|
.emit();
|
||||||
|
|
||||||
|
self.record_lifetime_res(lifetime.id, LifetimeRes::Error);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
LifetimeRibKind::AnonymousCreateParameter
|
LifetimeRibKind::AnonymousPassThrough(node_id) => {
|
||||||
| LifetimeRibKind::AnonymousPassThrough
|
self.record_lifetime_res(
|
||||||
| LifetimeRibKind::Item => return,
|
lifetime.id,
|
||||||
|
LifetimeRes::Anonymous { binder: node_id, elided },
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
LifetimeRibKind::Item => break,
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// This resolution is wrong, it passes the work to HIR lifetime resolution.
|
||||||
|
// We cannot use `LifetimeRes::Error` because we do not emit a diagnostic.
|
||||||
|
self.record_lifetime_res(
|
||||||
|
lifetime.id,
|
||||||
|
LifetimeRes::Anonymous { binder: DUMMY_NODE_ID, elided },
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tracing::instrument(level = "debug", skip(self))]
|
#[tracing::instrument(level = "debug", skip(self))]
|
||||||
fn resolve_elided_lifetime(&mut self, anchor_id: NodeId, span: Span) {
|
fn resolve_elided_lifetime(&mut self, anchor_id: NodeId, span: Span) {
|
||||||
let id = self.r.next_node_id();
|
let id = self.r.next_node_id();
|
||||||
|
self.record_lifetime_res(
|
||||||
|
anchor_id,
|
||||||
|
LifetimeRes::ElidedAnchor { start: id, end: NodeId::from_u32(id.as_u32() + 1) },
|
||||||
|
);
|
||||||
|
|
||||||
let lt = Lifetime { id, ident: Ident::new(kw::UnderscoreLifetime, span) };
|
let lt = Lifetime { id, ident: Ident::new(kw::UnderscoreLifetime, span) };
|
||||||
self.resolve_anonymous_lifetime(<, true);
|
self.resolve_anonymous_lifetime(<, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tracing::instrument(level = "debug", skip(self))]
|
||||||
|
fn create_fresh_lifetime(&mut self, id: NodeId, ident: Ident, item_node_id: NodeId) {
|
||||||
|
debug_assert_eq!(ident.name, kw::UnderscoreLifetime);
|
||||||
|
debug!(?ident.span);
|
||||||
|
let item_def_id = self.r.local_def_id(item_node_id);
|
||||||
|
let def_node_id = self.r.next_node_id();
|
||||||
|
let def_id = self.r.create_def(
|
||||||
|
item_def_id,
|
||||||
|
def_node_id,
|
||||||
|
DefPathData::LifetimeNs(kw::UnderscoreLifetime),
|
||||||
|
self.parent_scope.expansion.to_expn_id(),
|
||||||
|
ident.span,
|
||||||
|
);
|
||||||
|
debug!(?def_id);
|
||||||
|
|
||||||
|
let region = LifetimeRes::Fresh { param: def_id, binder: item_node_id };
|
||||||
|
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))]
|
||||||
fn resolve_elided_lifetimes_in_path(
|
fn resolve_elided_lifetimes_in_path(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
@ -1231,7 +1328,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
||||||
//
|
//
|
||||||
// impl Foo for std::cell::Ref<u32> // note lack of '_
|
// impl Foo for std::cell::Ref<u32> // note lack of '_
|
||||||
// async fn foo(_: std::cell::Ref<u32>) { ... }
|
// async fn foo(_: std::cell::Ref<u32>) { ... }
|
||||||
LifetimeRibKind::AnonymousCreateParameter => {
|
LifetimeRibKind::AnonymousCreateParameter(_) => {
|
||||||
error = true;
|
error = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1241,13 +1338,29 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
||||||
// `PathSegment`, for which there is no associated `'_` or `&T` with no explicit
|
// `PathSegment`, for which there is no associated `'_` or `&T` with no explicit
|
||||||
// lifetime. Instead, we simply create an implicit lifetime, which will be checked
|
// lifetime. Instead, we simply create an implicit lifetime, which will be checked
|
||||||
// later, at which point a suitable error will be emitted.
|
// later, at which point a suitable error will be emitted.
|
||||||
LifetimeRibKind::AnonymousPassThrough
|
LifetimeRibKind::AnonymousPassThrough(..)
|
||||||
| LifetimeRibKind::AnonymousReportError
|
| LifetimeRibKind::AnonymousReportError
|
||||||
| LifetimeRibKind::Item => break,
|
| LifetimeRibKind::Item => break,
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let res = if error {
|
||||||
|
LifetimeRes::Error
|
||||||
|
} else {
|
||||||
|
LifetimeRes::Anonymous { binder: segment_id, elided: true }
|
||||||
|
};
|
||||||
|
|
||||||
|
let node_ids = self.r.next_node_ids(expected_lifetimes);
|
||||||
|
self.record_lifetime_res(
|
||||||
|
segment_id,
|
||||||
|
LifetimeRes::ElidedAnchor { start: node_ids.start, end: node_ids.end },
|
||||||
|
);
|
||||||
|
for i in 0..expected_lifetimes {
|
||||||
|
let id = node_ids.start.plus(i);
|
||||||
|
self.record_lifetime_res(id, res);
|
||||||
|
}
|
||||||
|
|
||||||
if !missing {
|
if !missing {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -1296,6 +1409,16 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tracing::instrument(level = "debug", skip(self))]
|
||||||
|
fn record_lifetime_res(&mut self, id: NodeId, res: LifetimeRes) {
|
||||||
|
if let Some(prev_res) = self.r.lifetimes_res_map.insert(id, res) {
|
||||||
|
panic!(
|
||||||
|
"lifetime {:?} resolved multiple times ({:?} before, {:?} now)",
|
||||||
|
id, prev_res, res
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Searches the current set of local scopes for labels. Returns the `NodeId` of the resolved
|
/// Searches the current set of local scopes for labels. Returns the `NodeId` of the resolved
|
||||||
/// label and reports an error if the label is not found or is unreachable.
|
/// label and reports an error if the label is not found or is unreachable.
|
||||||
fn resolve_label(&self, mut label: Ident) -> Option<NodeId> {
|
fn resolve_label(&self, mut label: Ident) -> Option<NodeId> {
|
||||||
|
@ -1379,7 +1502,11 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
||||||
this.with_generic_param_rib(
|
this.with_generic_param_rib(
|
||||||
&generics.params,
|
&generics.params,
|
||||||
ItemRibKind(HasGenericParams::Yes),
|
ItemRibKind(HasGenericParams::Yes),
|
||||||
LifetimeRibKind::Generics { kind: LifetimeBinderKind::Item, span: generics.span },
|
LifetimeRibKind::Generics {
|
||||||
|
parent: item.id,
|
||||||
|
kind: LifetimeBinderKind::Item,
|
||||||
|
span: generics.span,
|
||||||
|
},
|
||||||
|this| {
|
|this| {
|
||||||
let item_def_id = this.r.local_def_id(item.id).to_def_id();
|
let item_def_id = this.r.local_def_id(item.id).to_def_id();
|
||||||
this.with_self_rib(
|
this.with_self_rib(
|
||||||
|
@ -1446,6 +1573,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
||||||
&generics.params,
|
&generics.params,
|
||||||
ItemRibKind(HasGenericParams::Yes),
|
ItemRibKind(HasGenericParams::Yes),
|
||||||
LifetimeRibKind::Generics {
|
LifetimeRibKind::Generics {
|
||||||
|
parent: item.id,
|
||||||
kind: LifetimeBinderKind::Item,
|
kind: LifetimeBinderKind::Item,
|
||||||
span: generics.span,
|
span: generics.span,
|
||||||
},
|
},
|
||||||
|
@ -1458,6 +1586,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
||||||
&generics.params,
|
&generics.params,
|
||||||
ItemRibKind(HasGenericParams::Yes),
|
ItemRibKind(HasGenericParams::Yes),
|
||||||
LifetimeRibKind::Generics {
|
LifetimeRibKind::Generics {
|
||||||
|
parent: item.id,
|
||||||
kind: LifetimeBinderKind::Function,
|
kind: LifetimeBinderKind::Function,
|
||||||
span: generics.span,
|
span: generics.span,
|
||||||
},
|
},
|
||||||
|
@ -1487,6 +1616,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
||||||
&generics.params,
|
&generics.params,
|
||||||
ItemRibKind(HasGenericParams::Yes),
|
ItemRibKind(HasGenericParams::Yes),
|
||||||
LifetimeRibKind::Generics {
|
LifetimeRibKind::Generics {
|
||||||
|
parent: item.id,
|
||||||
kind: LifetimeBinderKind::Item,
|
kind: LifetimeBinderKind::Item,
|
||||||
span: generics.span,
|
span: generics.span,
|
||||||
},
|
},
|
||||||
|
@ -1506,7 +1636,11 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
||||||
this.with_generic_param_rib(
|
this.with_generic_param_rib(
|
||||||
&generics.params,
|
&generics.params,
|
||||||
AssocItemRibKind,
|
AssocItemRibKind,
|
||||||
LifetimeRibKind::Generics { span: generics.span, kind },
|
LifetimeRibKind::Generics {
|
||||||
|
parent: item.id,
|
||||||
|
span: generics.span,
|
||||||
|
kind,
|
||||||
|
},
|
||||||
|this| {
|
|this| {
|
||||||
visit::walk_assoc_item(this, item, AssocCtxt::Trait)
|
visit::walk_assoc_item(this, item, AssocCtxt::Trait)
|
||||||
},
|
},
|
||||||
|
@ -1571,6 +1705,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
||||||
&generics.params,
|
&generics.params,
|
||||||
ItemRibKind(HasGenericParams::Yes),
|
ItemRibKind(HasGenericParams::Yes),
|
||||||
LifetimeRibKind::Generics {
|
LifetimeRibKind::Generics {
|
||||||
|
parent: item.id,
|
||||||
kind: LifetimeBinderKind::Item,
|
kind: LifetimeBinderKind::Item,
|
||||||
span: generics.span,
|
span: generics.span,
|
||||||
},
|
},
|
||||||
|
@ -1708,7 +1843,10 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
||||||
GenericParamKind::Type { .. } => (&mut function_type_rib, DefKind::TyParam),
|
GenericParamKind::Type { .. } => (&mut function_type_rib, DefKind::TyParam),
|
||||||
GenericParamKind::Const { .. } => (&mut function_value_rib, DefKind::ConstParam),
|
GenericParamKind::Const { .. } => (&mut function_value_rib, DefKind::ConstParam),
|
||||||
GenericParamKind::Lifetime => {
|
GenericParamKind::Lifetime => {
|
||||||
function_lifetime_rib.bindings.insert(ident, ());
|
let LifetimeRibKind::Generics { parent, .. } = lifetime_kind else { panic!() };
|
||||||
|
let res = LifetimeRes::Param { param: def_id, binder: parent };
|
||||||
|
self.record_lifetime_res(param.id, res);
|
||||||
|
function_lifetime_rib.bindings.insert(ident, (param.id, res));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -1849,10 +1987,10 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
||||||
) {
|
) {
|
||||||
debug!("resolve_implementation");
|
debug!("resolve_implementation");
|
||||||
// If applicable, create a rib for the type parameters.
|
// If applicable, create a rib for the type parameters.
|
||||||
self.with_generic_param_rib(&generics.params, ItemRibKind(HasGenericParams::Yes), LifetimeRibKind::Generics { span: generics.span, kind: LifetimeBinderKind::ImplBlock }, |this| {
|
self.with_generic_param_rib(&generics.params, ItemRibKind(HasGenericParams::Yes), LifetimeRibKind::Generics { span: generics.span, parent: item_id, kind: LifetimeBinderKind::ImplBlock }, |this| {
|
||||||
// Dummy self type for better errors if `Self` is used in the trait path.
|
// Dummy self type for better errors if `Self` is used in the trait path.
|
||||||
this.with_self_rib(Res::SelfTy { trait_: None, alias_to: None }, |this| {
|
this.with_self_rib(Res::SelfTy { trait_: None, alias_to: None }, |this| {
|
||||||
this.with_lifetime_rib(LifetimeRibKind::AnonymousCreateParameter, |this| {
|
this.with_lifetime_rib(LifetimeRibKind::AnonymousCreateParameter(item_id), |this| {
|
||||||
// Resolve the trait reference, if necessary.
|
// Resolve the trait reference, if necessary.
|
||||||
this.with_optional_trait_ref(opt_trait_reference.as_ref(), |this, trait_id| {
|
this.with_optional_trait_ref(opt_trait_reference.as_ref(), |this, trait_id| {
|
||||||
let item_def_id = this.r.local_def_id(item_id);
|
let item_def_id = this.r.local_def_id(item_id);
|
||||||
|
@ -1876,7 +2014,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
||||||
this.visit_generics(generics);
|
this.visit_generics(generics);
|
||||||
|
|
||||||
// Resolve the items within the impl.
|
// Resolve the items within the impl.
|
||||||
this.with_lifetime_rib(LifetimeRibKind::AnonymousPassThrough,
|
this.with_lifetime_rib(LifetimeRibKind::AnonymousPassThrough(item_id),
|
||||||
|this| {
|
|this| {
|
||||||
this.with_current_self_type(self_type, |this| {
|
this.with_current_self_type(self_type, |this| {
|
||||||
this.with_self_rib_ns(ValueNS, Res::SelfCtor(item_def_id), |this| {
|
this.with_self_rib_ns(ValueNS, Res::SelfCtor(item_def_id), |this| {
|
||||||
|
@ -1921,7 +2059,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
||||||
this.with_generic_param_rib(
|
this.with_generic_param_rib(
|
||||||
&generics.params,
|
&generics.params,
|
||||||
AssocItemRibKind,
|
AssocItemRibKind,
|
||||||
LifetimeRibKind::Generics { span: generics.span, kind: LifetimeBinderKind::Function },
|
LifetimeRibKind::Generics { parent: item.id, span: generics.span, kind: LifetimeBinderKind::Function },
|
||||||
|this| {
|
|this| {
|
||||||
// If this is a trait impl, ensure the method
|
// If this is a trait impl, ensure the method
|
||||||
// exists in trait
|
// exists in trait
|
||||||
|
@ -1950,7 +2088,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
||||||
this.with_generic_param_rib(
|
this.with_generic_param_rib(
|
||||||
&generics.params,
|
&generics.params,
|
||||||
AssocItemRibKind,
|
AssocItemRibKind,
|
||||||
LifetimeRibKind::Generics { span: generics.span, kind: LifetimeBinderKind::Item },
|
LifetimeRibKind::Generics { parent: item.id, span: generics.span, kind: LifetimeBinderKind::Item },
|
||||||
|this| {
|
|this| {
|
||||||
// If this is a trait impl, ensure the type
|
// If this is a trait impl, ensure the type
|
||||||
// exists in trait
|
// exists in trait
|
||||||
|
@ -2655,9 +2793,9 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
||||||
if !matches!(source, PathSource::TraitItem(..)) {
|
if !matches!(source, PathSource::TraitItem(..)) {
|
||||||
// Avoid recording definition of `A::B` in `<T as A>::B::C`.
|
// Avoid recording definition of `A::B` in `<T as A>::B::C`.
|
||||||
self.r.record_partial_res(id, partial_res);
|
self.r.record_partial_res(id, partial_res);
|
||||||
|
self.resolve_elided_lifetimes_in_path(id, partial_res, path, source, finalize);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.resolve_elided_lifetimes_in_path(id, partial_res, path, source, finalize);
|
|
||||||
partial_res
|
partial_res
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1824,7 +1824,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
|
||||||
|
|
||||||
for rib in self.lifetime_ribs.iter().rev() {
|
for rib in self.lifetime_ribs.iter().rev() {
|
||||||
match rib.kind {
|
match rib.kind {
|
||||||
LifetimeRibKind::Generics { span, kind } => {
|
LifetimeRibKind::Generics { parent: _, span, kind } => {
|
||||||
if !span.can_be_used_for_suggestions() && suggest_note {
|
if !span.can_be_used_for_suggestions() && suggest_note {
|
||||||
suggest_note = false; // Avoid displaying the same help multiple times.
|
suggest_note = false; // Avoid displaying the same help multiple times.
|
||||||
err.span_label(
|
err.span_label(
|
||||||
|
|
|
@ -29,7 +29,7 @@ use rustc_arena::{DroplessArena, TypedArena};
|
||||||
use rustc_ast::node_id::NodeMap;
|
use rustc_ast::node_id::NodeMap;
|
||||||
use rustc_ast::{self as ast, NodeId, CRATE_NODE_ID};
|
use rustc_ast::{self as ast, NodeId, CRATE_NODE_ID};
|
||||||
use rustc_ast::{AngleBracketedArg, Crate, Expr, ExprKind, GenericArg, GenericArgs, LitKind, Path};
|
use rustc_ast::{AngleBracketedArg, Crate, Expr, ExprKind, GenericArg, GenericArgs, LitKind, Path};
|
||||||
use rustc_ast_lowering::ResolverAstLowering;
|
use rustc_ast_lowering::{LifetimeRes, ResolverAstLowering};
|
||||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap};
|
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap};
|
||||||
use rustc_data_structures::intern::Interned;
|
use rustc_data_structures::intern::Interned;
|
||||||
use rustc_data_structures::sync::Lrc;
|
use rustc_data_structures::sync::Lrc;
|
||||||
|
@ -901,6 +901,10 @@ pub struct Resolver<'a> {
|
||||||
import_res_map: NodeMap<PerNS<Option<Res>>>,
|
import_res_map: NodeMap<PerNS<Option<Res>>>,
|
||||||
/// Resolutions for labels (node IDs of their corresponding blocks or loops).
|
/// Resolutions for labels (node IDs of their corresponding blocks or loops).
|
||||||
label_res_map: NodeMap<NodeId>,
|
label_res_map: NodeMap<NodeId>,
|
||||||
|
/// Resolutions for lifetimes.
|
||||||
|
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>,
|
||||||
|
@ -1154,6 +1158,14 @@ impl ResolverAstLowering for Resolver<'_> {
|
||||||
self.label_res_map.get(&id).cloned()
|
self.label_res_map.get(&id).cloned()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_lifetime_res(&self, id: NodeId) -> Option<LifetimeRes> {
|
||||||
|
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())
|
||||||
}
|
}
|
||||||
|
@ -1302,6 +1314,8 @@ impl<'a> Resolver<'a> {
|
||||||
partial_res_map: Default::default(),
|
partial_res_map: Default::default(),
|
||||||
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(),
|
||||||
|
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(),
|
||||||
|
|
|
@ -46,6 +46,7 @@ where
|
||||||
|
|
||||||
fn create_doc() -> impl Document<Cursor<'_> = DocCursorImpl<'_>> {
|
fn create_doc() -> impl Document<Cursor<'_> = DocCursorImpl<'_>> {
|
||||||
//~^ ERROR: missing lifetime specifier
|
//~^ ERROR: missing lifetime specifier
|
||||||
|
//~| ERROR: missing lifetime specifier
|
||||||
DocumentImpl {}
|
DocumentImpl {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,18 @@ help: consider using the `'static` lifetime
|
||||||
LL | fn create_doc() -> impl Document<Cursor<'static> = DocCursorImpl<'_>> {
|
LL | fn create_doc() -> impl Document<Cursor<'static> = DocCursorImpl<'_>> {
|
||||||
| ~~~~~~~
|
| ~~~~~~~
|
||||||
|
|
||||||
error: aborting due to previous error
|
error[E0106]: missing lifetime specifier
|
||||||
|
--> $DIR/issue-70304.rs:47:61
|
||||||
|
|
|
||||||
|
LL | fn create_doc() -> impl Document<Cursor<'_> = DocCursorImpl<'_>> {
|
||||||
|
| ^^ expected named lifetime parameter
|
||||||
|
|
|
||||||
|
= help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
|
||||||
|
help: consider using the `'static` lifetime
|
||||||
|
|
|
||||||
|
LL | fn create_doc() -> impl Document<Cursor<'_> = DocCursorImpl<'static>> {
|
||||||
|
| ~~~~~~~
|
||||||
|
|
||||||
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0106`.
|
For more information about this error, try `rustc --explain E0106`.
|
||||||
|
|
|
@ -27,16 +27,16 @@ type TransactionFuture<'__, O> = impl '__ + Future<Output = TransactionResult<O>
|
||||||
|
|
||||||
fn execute_transaction_fut<'f, F, O>(
|
fn execute_transaction_fut<'f, F, O>(
|
||||||
f: F,
|
f: F,
|
||||||
) -> impl FnOnce(&mut dyn Transaction) -> TransactionFuture<O>
|
) -> impl FnOnce(&mut dyn Transaction) -> TransactionFuture<'_, O>
|
||||||
where
|
where
|
||||||
F: FnOnce(&mut dyn Transaction) -> TransactionFuture<O> + 'f
|
F: FnOnce(&mut dyn Transaction) -> TransactionFuture<'_, O> + 'f
|
||||||
{
|
{
|
||||||
f
|
f
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Context {
|
impl Context {
|
||||||
async fn do_transaction<O>(
|
async fn do_transaction<O>(
|
||||||
&self, f: impl FnOnce(&mut dyn Transaction) -> TransactionFuture<O>
|
&self, f: impl FnOnce(&mut dyn Transaction) -> TransactionFuture<'_, O>
|
||||||
) -> TransactionResult<O>
|
) -> TransactionResult<O>
|
||||||
{
|
{
|
||||||
let mut conn = Connection {};
|
let mut conn = Connection {};
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue