Use LifetimeRes during lowering.
This commit is contained in:
parent
69985f0175
commit
f385f856cd
9 changed files with 709 additions and 799 deletions
|
@ -53,7 +53,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
e.span,
|
||||
seg,
|
||||
ParamMode::Optional,
|
||||
0,
|
||||
ParenthesizedGenericArgs::Err,
|
||||
ImplTraitContext::Disallowed(ImplTraitPosition::Path),
|
||||
));
|
||||
|
|
|
@ -30,6 +30,7 @@ pub(super) struct NodeCollector<'a, 'hir> {
|
|||
definitions: &'a definitions::Definitions,
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "debug", skip(sess, definitions, bodies))]
|
||||
pub(super) fn index_hir<'hir>(
|
||||
sess: &Session,
|
||||
definitions: &definitions::Definitions,
|
||||
|
@ -65,6 +66,7 @@ pub(super) fn index_hir<'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>) {
|
||||
debug_assert_eq!(self.owner, hir_id.owner);
|
||||
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>) {
|
||||
debug!("visit_item: {:?}", i);
|
||||
debug_assert_eq!(i.def_id, self.owner);
|
||||
self.with_parent(i.hir_id(), |this| {
|
||||
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>) {
|
||||
debug_assert_eq!(fi.def_id, self.owner);
|
||||
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>) {
|
||||
debug_assert_eq!(ti.def_id, self.owner);
|
||||
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>) {
|
||||
debug_assert_eq!(ii.def_id, self.owner);
|
||||
self.with_parent(ii.hir_id(), |this| {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use super::{AnonymousLifetimeMode, LoweringContext, ParamMode};
|
||||
use super::{AstOwner, ImplTraitContext, ImplTraitPosition, ResolverAstLowering};
|
||||
use super::{LoweringContext, ParamMode};
|
||||
use crate::{Arena, FnDeclKind};
|
||||
|
||||
use rustc_ast::ptr::P;
|
||||
|
@ -81,13 +81,13 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> {
|
|||
is_in_loop_condition: false,
|
||||
is_in_trait_impl: false,
|
||||
is_in_dyn_type: false,
|
||||
anonymous_lifetime_mode: AnonymousLifetimeMode::PassThrough,
|
||||
generator_kind: None,
|
||||
task_context: None,
|
||||
current_item: None,
|
||||
lifetimes_to_define: Vec::new(),
|
||||
lifetimes_to_define: Default::default(),
|
||||
is_collecting_anonymous_lifetimes: None,
|
||||
in_scope_lifetimes: Vec::new(),
|
||||
captured_lifetimes: None,
|
||||
allow_try_trait: Some([sym::try_trait_v2][..].into()),
|
||||
allow_gen_future: Some([sym::gen_future][..].into()),
|
||||
allow_into_future: Some([sym::into_future][..].into()),
|
||||
|
@ -143,12 +143,12 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> {
|
|||
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| {
|
||||
// Evaluate with the lifetimes in `params` in-scope.
|
||||
// This is used to track which lifetimes have already been defined,
|
||||
// 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, .. }) => {
|
||||
lctx.is_in_trait_impl = of_trait.is_some();
|
||||
lctx.in_scope_lifetimes = generics
|
||||
|
@ -157,7 +157,12 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> {
|
|||
.filter(|param| {
|
||||
matches!(param.kind, hir::GenericParamKind::Lifetime { .. })
|
||||
})
|
||||
.map(|param| param.name)
|
||||
.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, ..) => {
|
||||
|
@ -167,7 +172,12 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> {
|
|||
.filter(|param| {
|
||||
matches!(param.kind, hir::GenericParamKind::Lifetime { .. })
|
||||
})
|
||||
.map(|param| param.name)
|
||||
.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();
|
||||
}
|
||||
_ => {}
|
||||
|
@ -288,20 +298,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
let body_id =
|
||||
this.lower_maybe_async_body(span, &decl, asyncness, body.as_deref());
|
||||
|
||||
let (generics, decl) = this.add_in_band_defs(
|
||||
generics,
|
||||
fn_def_id,
|
||||
AnonymousLifetimeMode::PassThrough,
|
||||
|this, idty| {
|
||||
let (generics, decl) =
|
||||
this.add_in_band_defs(generics, fn_def_id, |this, idty| {
|
||||
let ret_id = asyncness.opt_return_id();
|
||||
this.lower_fn_decl(
|
||||
&decl,
|
||||
Some((fn_def_id, idty)),
|
||||
FnDeclKind::Fn,
|
||||
ret_id,
|
||||
)
|
||||
},
|
||||
);
|
||||
this.lower_fn_decl(&decl, Some((id, idty)), FnDeclKind::Fn, ret_id)
|
||||
});
|
||||
let sig = hir::FnSig {
|
||||
decl,
|
||||
header: this.lower_fn_header(header),
|
||||
|
@ -420,11 +421,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
// lifetime to be added, but rather a reference to a
|
||||
// parent lifetime.
|
||||
let lowered_trait_def_id = hir_id.expect_owner();
|
||||
let (generics, (trait_ref, lowered_ty)) = self.add_in_band_defs(
|
||||
ast_generics,
|
||||
lowered_trait_def_id,
|
||||
AnonymousLifetimeMode::CreateParameter,
|
||||
|this, _| {
|
||||
let (generics, (trait_ref, lowered_ty)) =
|
||||
self.add_in_band_defs(ast_generics, lowered_trait_def_id, |this, _| {
|
||||
let trait_ref = trait_ref.as_ref().map(|trait_ref| {
|
||||
this.lower_trait_ref(
|
||||
trait_ref,
|
||||
|
@ -436,8 +434,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
.lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::Type));
|
||||
|
||||
(trait_ref, lowered_ty)
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
let new_impl_items =
|
||||
self.with_in_scope_lifetime_defs(&ast_generics.params, |this| {
|
||||
|
@ -750,18 +747,14 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
kind: match i.kind {
|
||||
ForeignItemKind::Fn(box Fn { ref sig, ref generics, .. }) => {
|
||||
let fdec = &sig.decl;
|
||||
let (generics, (fn_dec, fn_args)) = self.add_in_band_defs(
|
||||
generics,
|
||||
def_id,
|
||||
AnonymousLifetimeMode::PassThrough,
|
||||
|this, _| {
|
||||
let (generics, (fn_dec, fn_args)) =
|
||||
self.add_in_band_defs(generics, def_id, |this, _| {
|
||||
(
|
||||
// Disallow `impl Trait` in foreign items.
|
||||
this.lower_fn_decl(fdec, None, FnDeclKind::ExternFn, None),
|
||||
this.lower_fn_params_to_names(fdec),
|
||||
)
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
hir::ForeignItemKind::Fn(fn_dec, fn_args, generics)
|
||||
}
|
||||
|
@ -868,13 +861,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
}
|
||||
AssocItemKind::Fn(box Fn { ref sig, ref generics, body: None, .. }) => {
|
||||
let names = self.lower_fn_params_to_names(&sig.decl);
|
||||
let (generics, sig) = self.lower_method_sig(
|
||||
generics,
|
||||
sig,
|
||||
trait_item_def_id,
|
||||
FnDeclKind::Trait,
|
||||
None,
|
||||
);
|
||||
let (generics, sig) =
|
||||
self.lower_method_sig(generics, sig, i.id, FnDeclKind::Trait, None);
|
||||
(generics, hir::TraitItemKind::Fn(sig, hir::TraitFn::Required(names)))
|
||||
}
|
||||
AssocItemKind::Fn(box Fn { ref sig, ref generics, body: Some(ref body), .. }) => {
|
||||
|
@ -884,7 +872,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
let (generics, sig) = self.lower_method_sig(
|
||||
generics,
|
||||
sig,
|
||||
trait_item_def_id,
|
||||
i.id,
|
||||
FnDeclKind::Trait,
|
||||
asyncness.opt_return_id(),
|
||||
);
|
||||
|
@ -958,8 +946,6 @@ impl<'hir> LoweringContext<'_, '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 {
|
||||
AssocItemKind::Const(_, ty, expr) => {
|
||||
let ty = self.lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::Type));
|
||||
|
@ -976,7 +962,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
let (generics, sig) = self.lower_method_sig(
|
||||
generics,
|
||||
sig,
|
||||
impl_item_def_id,
|
||||
i.id,
|
||||
if self.is_in_trait_impl { FnDeclKind::Impl } else { FnDeclKind::Inherent },
|
||||
asyncness.opt_return_id(),
|
||||
);
|
||||
|
@ -1363,17 +1349,15 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
&mut self,
|
||||
generics: &Generics,
|
||||
sig: &FnSig,
|
||||
fn_def_id: LocalDefId,
|
||||
id: NodeId,
|
||||
kind: FnDeclKind,
|
||||
is_async: Option<NodeId>,
|
||||
) -> (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 (generics, decl) = self.add_in_band_defs(
|
||||
generics,
|
||||
fn_def_id,
|
||||
AnonymousLifetimeMode::PassThrough,
|
||||
|this, idty| this.lower_fn_decl(&sig.decl, Some((fn_def_id, idty)), kind, is_async),
|
||||
);
|
||||
let (generics, decl) = self.add_in_band_defs(generics, fn_def_id, |this, idty| {
|
||||
this.lower_fn_decl(&sig.decl, Some((id, idty)), kind, is_async)
|
||||
});
|
||||
(generics, hir::FnSig { header, decl, span: self.lower_span(sig.span) })
|
||||
}
|
||||
|
||||
|
@ -1498,14 +1482,12 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
}
|
||||
|
||||
fn lower_where_clause(&mut self, wc: &WhereClause) -> hir::WhereClause<'hir> {
|
||||
self.with_anonymous_lifetime_mode(AnonymousLifetimeMode::ReportError, |this| {
|
||||
hir::WhereClause {
|
||||
predicates: this.arena.alloc_from_iter(
|
||||
wc.predicates.iter().map(|predicate| this.lower_where_predicate(predicate)),
|
||||
),
|
||||
span: this.lower_span(wc.span),
|
||||
}
|
||||
})
|
||||
hir::WhereClause {
|
||||
predicates: self.arena.alloc_from_iter(
|
||||
wc.predicates.iter().map(|predicate| self.lower_where_predicate(predicate)),
|
||||
),
|
||||
span: self.lower_span(wc.span),
|
||||
}
|
||||
}
|
||||
|
||||
fn lower_where_predicate(&mut self, pred: &WherePredicate) -> hir::WherePredicate<'hir> {
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,15 +1,14 @@
|
|||
use crate::ImplTraitPosition;
|
||||
|
||||
use super::{AnonymousLifetimeMode, ImplTraitContext, LoweringContext, ParamMode};
|
||||
use super::{GenericArgsCtor, ParenthesizedGenericArgs};
|
||||
use super::{GenericArgsCtor, LifetimeRes, ParenthesizedGenericArgs};
|
||||
use super::{ImplTraitContext, LoweringContext, ParamMode};
|
||||
|
||||
use rustc_ast::{self as ast, *};
|
||||
use rustc_errors::{struct_span_err, Applicability};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::{DefKind, PartialRes, Res};
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_hir::GenericArg;
|
||||
use rustc_span::symbol::Ident;
|
||||
use rustc_span::symbol::{kw, Ident};
|
||||
use rustc_span::{BytePos, Span, DUMMY_SP};
|
||||
|
||||
use smallvec::smallvec;
|
||||
|
@ -47,30 +46,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
_ => 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() {
|
||||
// `a::b::Trait(Args)`
|
||||
Res::Def(DefKind::Trait, _) if i + 1 == proj_start => {
|
||||
|
@ -90,13 +65,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
_ => 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(
|
||||
p.span,
|
||||
segment,
|
||||
param_mode,
|
||||
num_lifetimes,
|
||||
parenthesized_generic_args,
|
||||
itctx.reborrow(),
|
||||
)
|
||||
|
@ -143,7 +115,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
p.span,
|
||||
segment,
|
||||
param_mode,
|
||||
0,
|
||||
ParenthesizedGenericArgs::Err,
|
||||
itctx.reborrow(),
|
||||
));
|
||||
|
@ -184,7 +155,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
p.span,
|
||||
segment,
|
||||
param_mode,
|
||||
0,
|
||||
ParenthesizedGenericArgs::Err,
|
||||
ImplTraitContext::Disallowed(ImplTraitPosition::Path),
|
||||
)
|
||||
|
@ -209,14 +179,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
path_span: Span,
|
||||
segment: &PathSegment,
|
||||
param_mode: ParamMode,
|
||||
expected_lifetimes: usize,
|
||||
parenthesized_generic_args: ParenthesizedGenericArgs,
|
||||
itctx: ImplTraitContext<'_, 'hir>,
|
||||
) -> hir::PathSegment<'hir> {
|
||||
debug!(
|
||||
"path_span: {:?}, lower_path_segment(segment: {:?}, expected_lifetimes: {:?})",
|
||||
path_span, segment, expected_lifetimes
|
||||
);
|
||||
debug!("path_span: {:?}, lower_path_segment(segment: {:?})", path_span, segment,);
|
||||
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";
|
||||
match **generic_args {
|
||||
|
@ -224,7 +190,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
self.lower_angle_bracketed_parameter_data(data, param_mode, itctx)
|
||||
}
|
||||
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 => {
|
||||
let mut err = struct_span_err!(self.sess, data.span, E0214, "{}", msg);
|
||||
err.span_label(data.span, "only `Fn` traits may use parentheses");
|
||||
|
@ -274,33 +242,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
|
||||
let has_lifetimes =
|
||||
generic_args.args.iter().any(|arg| matches!(arg, GenericArg::Lifetime(_)));
|
||||
if !generic_args.parenthesized && !has_lifetimes && expected_lifetimes > 0 {
|
||||
// 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 = 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");
|
||||
}
|
||||
if !generic_args.parenthesized && !has_lifetimes {
|
||||
self.maybe_insert_elided_lifetimes_in_path(
|
||||
path_span,
|
||||
segment.id,
|
||||
segment.ident.span,
|
||||
&mut generic_args,
|
||||
);
|
||||
}
|
||||
|
||||
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(
|
||||
&mut self,
|
||||
data: &AngleBracketedArgs,
|
||||
|
@ -354,6 +345,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
|
||||
fn lower_parenthesized_parameter_data(
|
||||
&mut self,
|
||||
id: NodeId,
|
||||
data: &ParenthesizedArgs,
|
||||
) -> (GenericArgsCtor<'hir>, bool) {
|
||||
// Switch to `PassThrough` mode for anonymous lifetimes; this
|
||||
|
@ -361,31 +353,33 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
// a hidden lifetime parameter. This is needed for backwards
|
||||
// compatibility, even in contexts like an impl header where
|
||||
// we generally don't permit such things (see #51008).
|
||||
self.with_anonymous_lifetime_mode(AnonymousLifetimeMode::PassThrough, |this| {
|
||||
let ParenthesizedArgs { span, inputs, inputs_span, output } = data;
|
||||
let inputs = this.arena.alloc_from_iter(inputs.iter().map(|ty| {
|
||||
this.lower_ty_direct(
|
||||
ty,
|
||||
ImplTraitContext::Disallowed(ImplTraitPosition::FnTraitParam),
|
||||
)
|
||||
}));
|
||||
let output_ty = match output {
|
||||
FnRetTy::Ty(ty) => this
|
||||
.lower_ty(&ty, ImplTraitContext::Disallowed(ImplTraitPosition::FnTraitReturn)),
|
||||
FnRetTy::Default(_) => this.arena.alloc(this.ty_tup(*span, &[])),
|
||||
};
|
||||
let args = smallvec![GenericArg::Type(this.ty_tup(*inputs_span, inputs))];
|
||||
let binding = this.output_ty_binding(output_ty.span, output_ty);
|
||||
(
|
||||
GenericArgsCtor {
|
||||
args,
|
||||
bindings: arena_vec![this; binding],
|
||||
parenthesized: true,
|
||||
span: data.inputs_span,
|
||||
},
|
||||
false,
|
||||
)
|
||||
})
|
||||
if let Some((_, _, binders)) = &mut self.captured_lifetimes {
|
||||
binders.insert(id);
|
||||
}
|
||||
let ParenthesizedArgs { span, inputs, inputs_span, output } = data;
|
||||
let inputs = self.arena.alloc_from_iter(inputs.iter().map(|ty| {
|
||||
self.lower_ty_direct(ty, ImplTraitContext::Disallowed(ImplTraitPosition::FnTraitParam))
|
||||
}));
|
||||
let output_ty = match output {
|
||||
FnRetTy::Ty(ty) => {
|
||||
self.lower_ty(&ty, ImplTraitContext::Disallowed(ImplTraitPosition::FnTraitReturn))
|
||||
}
|
||||
FnRetTy::Default(_) => self.arena.alloc(self.ty_tup(*span, &[])),
|
||||
};
|
||||
let args = smallvec![GenericArg::Type(self.ty_tup(*inputs_span, inputs))];
|
||||
let binding = self.output_ty_binding(output_ty.span, output_ty);
|
||||
if let Some((_, _, binders)) = &mut self.captured_lifetimes {
|
||||
binders.remove(&id);
|
||||
}
|
||||
(
|
||||
GenericArgsCtor {
|
||||
args,
|
||||
bindings: arena_vec![self; binding],
|
||||
parenthesized: true,
|
||||
span: data.inputs_span,
|
||||
},
|
||||
false,
|
||||
)
|
||||
}
|
||||
|
||||
/// An associated type binding `Output = $ty`.
|
||||
|
|
|
@ -442,9 +442,6 @@ pub enum GenericBound<'hir> {
|
|||
Outlives(Lifetime),
|
||||
}
|
||||
|
||||
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
|
||||
rustc_data_structures::static_assert_size!(GenericBound<'_>, 48);
|
||||
|
||||
impl GenericBound<'_> {
|
||||
pub fn trait_ref(&self) -> Option<&TraitRef<'_>> {
|
||||
match self {
|
||||
|
@ -3347,6 +3344,7 @@ mod size_asserts {
|
|||
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::Ty<'static>, 72);
|
||||
rustc_data_structures::static_assert_size!(super::GenericBound<'_>, 48);
|
||||
|
||||
rustc_data_structures::static_assert_size!(super::Item<'static>, 184);
|
||||
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::visit::{self, AssocCtxt, FnCtxt, FnKind, Visitor};
|
||||
use rustc_ast::*;
|
||||
use rustc_ast_lowering::ResolverAstLowering;
|
||||
use rustc_ast_lowering::{LifetimeRes, ResolverAstLowering};
|
||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||
use rustc_errors::DiagnosticId;
|
||||
use rustc_hir::def::Namespace::{self, *};
|
||||
use rustc_hir::def::{self, CtorKind, DefKind, PartialRes, PerNS};
|
||||
use rustc_hir::def_id::{DefId, CRATE_DEF_ID};
|
||||
use rustc_hir::definitions::DefPathData;
|
||||
use rustc_hir::{PrimTy, TraitCandidate};
|
||||
use rustc_index::vec::Idx;
|
||||
use rustc_middle::ty::DefIdTree;
|
||||
use rustc_middle::{bug, span_bug};
|
||||
use rustc_session::lint;
|
||||
|
@ -195,7 +197,7 @@ enum LifetimeRibKind {
|
|||
Item,
|
||||
|
||||
/// 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
|
||||
/// and reference that.
|
||||
|
@ -204,7 +206,7 @@ enum LifetimeRibKind {
|
|||
/// `resolve_lifetime` code.
|
||||
///
|
||||
/// For **Deprecated** cases, report an error.
|
||||
AnonymousCreateParameter,
|
||||
AnonymousCreateParameter(NodeId),
|
||||
|
||||
/// Give a hard error when either `&` or `'_` is written. Used to
|
||||
/// rule out things like `where T: Foo<'_>`. Does not imply an
|
||||
|
@ -212,7 +214,7 @@ enum LifetimeRibKind {
|
|||
AnonymousReportError,
|
||||
|
||||
/// Pass responsibility to `resolve_lifetime` code for all cases.
|
||||
AnonymousPassThrough,
|
||||
AnonymousPassThrough(NodeId),
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
|
@ -242,7 +244,7 @@ impl LifetimeBinderKind {
|
|||
#[derive(Debug)]
|
||||
struct LifetimeRib {
|
||||
kind: LifetimeRibKind,
|
||||
bindings: IdentMap<()>,
|
||||
bindings: IdentMap<LifetimeRes>,
|
||||
}
|
||||
|
||||
impl LifetimeRib {
|
||||
|
@ -581,12 +583,19 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
|
|||
self.with_generic_param_rib(
|
||||
&bare_fn.generic_params,
|
||||
NormalRibKind,
|
||||
LifetimeRibKind::Generics { kind: LifetimeBinderKind::BareFnType, span },
|
||||
LifetimeRibKind::Generics {
|
||||
parent: ty.id,
|
||||
kind: LifetimeBinderKind::BareFnType,
|
||||
span,
|
||||
},
|
||||
|this| {
|
||||
this.with_lifetime_rib(LifetimeRibKind::AnonymousPassThrough, |this| {
|
||||
this.visit_generic_param_vec(&bare_fn.generic_params, false);
|
||||
visit::walk_fn_decl(this, &bare_fn.decl);
|
||||
});
|
||||
this.with_lifetime_rib(
|
||||
LifetimeRibKind::AnonymousPassThrough(ty.id),
|
||||
|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;
|
||||
|
@ -604,7 +613,11 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
|
|||
self.with_generic_param_rib(
|
||||
&tref.bound_generic_params,
|
||||
NormalRibKind,
|
||||
LifetimeRibKind::Generics { kind: LifetimeBinderKind::PolyTrait, span },
|
||||
LifetimeRibKind::Generics {
|
||||
parent: tref.trait_ref.ref_id,
|
||||
kind: LifetimeBinderKind::PolyTrait,
|
||||
span,
|
||||
},
|
||||
|this| {
|
||||
this.visit_generic_param_vec(&tref.bound_generic_params, false);
|
||||
this.smart_resolve_path(
|
||||
|
@ -625,6 +638,7 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
|
|||
&generics.params,
|
||||
ItemRibKind(HasGenericParams::Yes),
|
||||
LifetimeRibKind::Generics {
|
||||
parent: foreign_item.id,
|
||||
kind: LifetimeBinderKind::Item,
|
||||
span: generics.span,
|
||||
},
|
||||
|
@ -638,6 +652,7 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
|
|||
&generics.params,
|
||||
ItemRibKind(HasGenericParams::Yes),
|
||||
LifetimeRibKind::Generics {
|
||||
parent: foreign_item.id,
|
||||
kind: LifetimeBinderKind::Function,
|
||||
span: generics.span,
|
||||
},
|
||||
|
@ -655,13 +670,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 {
|
||||
// Bail if the function is foreign, and thus cannot validly have
|
||||
// a body, or if there's no body for some other reason.
|
||||
FnKind::Fn(FnCtxt::Foreign, _, sig, _, generics, _)
|
||||
| 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
|
||||
// they are not possible for foreign or bodiless functions.
|
||||
this.visit_fn_header(&sig.header);
|
||||
|
@ -691,20 +706,24 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
|
|||
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
|
||||
// must be transformed into fresh generic parameters so that
|
||||
// they can be applied to the opaque `impl Trait` return type.
|
||||
this.with_lifetime_rib(LifetimeRibKind::AnonymousCreateParameter, |this| {
|
||||
// Add each argument to the rib.
|
||||
this.resolve_params(&declaration.inputs)
|
||||
});
|
||||
this.with_lifetime_rib(
|
||||
LifetimeRibKind::AnonymousCreateParameter(fn_id),
|
||||
|this| {
|
||||
// Add each argument to the rib.
|
||||
this.resolve_params(&declaration.inputs)
|
||||
},
|
||||
);
|
||||
|
||||
this.with_lifetime_rib(LifetimeRibKind::AnonymousPassThrough, |this| {
|
||||
visit::walk_fn_ret_ty(this, &declaration.output)
|
||||
});
|
||||
this.with_lifetime_rib(
|
||||
LifetimeRibKind::AnonymousPassThrough(async_node_id),
|
||||
|this| visit::walk_fn_ret_ty(this, &declaration.output),
|
||||
);
|
||||
} else {
|
||||
this.with_lifetime_rib(LifetimeRibKind::AnonymousPassThrough, |this| {
|
||||
this.with_lifetime_rib(LifetimeRibKind::AnonymousPassThrough(fn_id), |this| {
|
||||
// Add each argument to the rib.
|
||||
this.resolve_params(&declaration.inputs);
|
||||
|
||||
|
@ -716,13 +735,12 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
|
|||
// Be sure not to set this until the function signature has been resolved.
|
||||
let previous_state = replace(&mut this.in_func_body, true);
|
||||
// Resolve the function body, potentially inside the body of an async closure
|
||||
this.with_lifetime_rib(
|
||||
LifetimeRibKind::AnonymousPassThrough,
|
||||
|this| match fn_kind {
|
||||
this.with_lifetime_rib(LifetimeRibKind::AnonymousPassThrough(fn_id), |this| {
|
||||
match fn_kind {
|
||||
FnKind::Fn(.., body) => walk_list!(this, visit_block, body),
|
||||
FnKind::Closure(_, body) => this.visit_expr(body),
|
||||
},
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
debug!("(resolving function) leaving function");
|
||||
this.in_func_body = previous_state;
|
||||
|
@ -801,10 +819,10 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
|
|||
if let Some(ref args) = path_segment.args {
|
||||
match &**args {
|
||||
GenericArgs::AngleBracketed(..) => visit::walk_generic_args(self, path_span, args),
|
||||
GenericArgs::Parenthesized(..) => self
|
||||
.with_lifetime_rib(LifetimeRibKind::AnonymousPassThrough, |this| {
|
||||
visit::walk_generic_args(this, path_span, args)
|
||||
}),
|
||||
GenericArgs::Parenthesized(..) => self.with_lifetime_rib(
|
||||
LifetimeRibKind::AnonymousPassThrough(path_segment.id),
|
||||
|this| visit::walk_generic_args(this, path_span, args),
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -830,7 +848,11 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
|
|||
this.with_generic_param_rib(
|
||||
&bound_generic_params,
|
||||
NormalRibKind,
|
||||
LifetimeRibKind::Generics { kind: LifetimeBinderKind::WhereBound, span },
|
||||
LifetimeRibKind::Generics {
|
||||
parent: bounded_ty.id,
|
||||
kind: LifetimeBinderKind::WhereBound,
|
||||
span,
|
||||
},
|
||||
|this| {
|
||||
this.visit_generic_param_vec(&bound_generic_params, false);
|
||||
this.visit_ty(bounded_ty);
|
||||
|
@ -1092,6 +1114,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
|||
let ident = lifetime.ident;
|
||||
|
||||
if ident.name == kw::StaticLifetime {
|
||||
self.record_lifetime_res(lifetime.id, LifetimeRes::Static);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1103,7 +1126,8 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
|||
for i in &mut indices {
|
||||
let rib = &self.lifetime_ribs[i];
|
||||
let normalized_ident = ident.normalize_to_macros_2_0();
|
||||
if let Some(_) = rib.bindings.get_key_value(&normalized_ident) {
|
||||
if let Some(®ion) = rib.bindings.get(&normalized_ident) {
|
||||
self.record_lifetime_res(lifetime.id, region);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1123,6 +1147,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
|||
}
|
||||
|
||||
self.emit_undeclared_lifetime_error(lifetime, outer_res);
|
||||
self.record_lifetime_res(lifetime.id, LifetimeRes::Error);
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "debug", skip(self))]
|
||||
|
@ -1132,6 +1157,10 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
|||
for i in (0..self.lifetime_ribs.len()).rev() {
|
||||
let rib = &mut self.lifetime_ribs[i];
|
||||
match rib.kind {
|
||||
LifetimeRibKind::AnonymousCreateParameter(item_node_id) => {
|
||||
self.create_fresh_lifetime(lifetime.id, lifetime.ident, item_node_id);
|
||||
return;
|
||||
}
|
||||
LifetimeRibKind::AnonymousReportError => {
|
||||
let (msg, note) = if elided {
|
||||
(
|
||||
|
@ -1151,23 +1180,63 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
|||
.span_label(lifetime.ident.span, note)
|
||||
.emit();
|
||||
|
||||
self.record_lifetime_res(lifetime.id, LifetimeRes::Error);
|
||||
return;
|
||||
}
|
||||
LifetimeRibKind::AnonymousCreateParameter
|
||||
| LifetimeRibKind::AnonymousPassThrough
|
||||
| LifetimeRibKind::Item => return,
|
||||
LifetimeRibKind::AnonymousPassThrough(node_id) => {
|
||||
self.record_lifetime_res(
|
||||
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))]
|
||||
fn resolve_elided_lifetime(&mut self, anchor_id: NodeId, span: Span) {
|
||||
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) };
|
||||
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,
|
||||
introducer: Some(def_node_id),
|
||||
binder: item_node_id,
|
||||
};
|
||||
self.record_lifetime_res(id, region);
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "debug", skip(self))]
|
||||
fn resolve_elided_lifetimes_in_path(
|
||||
&mut self,
|
||||
|
@ -1231,7 +1300,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
|||
//
|
||||
// impl Foo for std::cell::Ref<u32> // note lack of '_
|
||||
// async fn foo(_: std::cell::Ref<u32>) { ... }
|
||||
LifetimeRibKind::AnonymousCreateParameter => {
|
||||
LifetimeRibKind::AnonymousCreateParameter(_) => {
|
||||
error = true;
|
||||
break;
|
||||
}
|
||||
|
@ -1241,13 +1310,29 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
|||
// `PathSegment`, for which there is no associated `'_` or `&T` with no explicit
|
||||
// lifetime. Instead, we simply create an implicit lifetime, which will be checked
|
||||
// later, at which point a suitable error will be emitted.
|
||||
LifetimeRibKind::AnonymousPassThrough
|
||||
LifetimeRibKind::AnonymousPassThrough(..)
|
||||
| LifetimeRibKind::AnonymousReportError
|
||||
| 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 {
|
||||
continue;
|
||||
}
|
||||
|
@ -1296,6 +1381,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
|
||||
/// label and reports an error if the label is not found or is unreachable.
|
||||
fn resolve_label(&self, mut label: Ident) -> Option<NodeId> {
|
||||
|
@ -1379,7 +1474,11 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
|||
this.with_generic_param_rib(
|
||||
&generics.params,
|
||||
ItemRibKind(HasGenericParams::Yes),
|
||||
LifetimeRibKind::Generics { kind: LifetimeBinderKind::Item, span: generics.span },
|
||||
LifetimeRibKind::Generics {
|
||||
parent: item.id,
|
||||
kind: LifetimeBinderKind::Item,
|
||||
span: generics.span,
|
||||
},
|
||||
|this| {
|
||||
let item_def_id = this.r.local_def_id(item.id).to_def_id();
|
||||
this.with_self_rib(
|
||||
|
@ -1446,6 +1545,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
|||
&generics.params,
|
||||
ItemRibKind(HasGenericParams::Yes),
|
||||
LifetimeRibKind::Generics {
|
||||
parent: item.id,
|
||||
kind: LifetimeBinderKind::Item,
|
||||
span: generics.span,
|
||||
},
|
||||
|
@ -1458,6 +1558,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
|||
&generics.params,
|
||||
ItemRibKind(HasGenericParams::Yes),
|
||||
LifetimeRibKind::Generics {
|
||||
parent: item.id,
|
||||
kind: LifetimeBinderKind::Function,
|
||||
span: generics.span,
|
||||
},
|
||||
|
@ -1487,6 +1588,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
|||
&generics.params,
|
||||
ItemRibKind(HasGenericParams::Yes),
|
||||
LifetimeRibKind::Generics {
|
||||
parent: item.id,
|
||||
kind: LifetimeBinderKind::Item,
|
||||
span: generics.span,
|
||||
},
|
||||
|
@ -1506,7 +1608,11 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
|||
this.with_generic_param_rib(
|
||||
&generics.params,
|
||||
AssocItemRibKind,
|
||||
LifetimeRibKind::Generics { span: generics.span, kind },
|
||||
LifetimeRibKind::Generics {
|
||||
parent: item.id,
|
||||
span: generics.span,
|
||||
kind,
|
||||
},
|
||||
|this| {
|
||||
visit::walk_assoc_item(this, item, AssocCtxt::Trait)
|
||||
},
|
||||
|
@ -1571,6 +1677,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
|||
&generics.params,
|
||||
ItemRibKind(HasGenericParams::Yes),
|
||||
LifetimeRibKind::Generics {
|
||||
parent: item.id,
|
||||
kind: LifetimeBinderKind::Item,
|
||||
span: generics.span,
|
||||
},
|
||||
|
@ -1708,7 +1815,10 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
|||
GenericParamKind::Type { .. } => (&mut function_type_rib, DefKind::TyParam),
|
||||
GenericParamKind::Const { .. } => (&mut function_value_rib, DefKind::ConstParam),
|
||||
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, res);
|
||||
continue;
|
||||
}
|
||||
};
|
||||
|
@ -1849,10 +1959,10 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
|||
) {
|
||||
debug!("resolve_implementation");
|
||||
// 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.
|
||||
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.
|
||||
this.with_optional_trait_ref(opt_trait_reference.as_ref(), |this, trait_id| {
|
||||
let item_def_id = this.r.local_def_id(item_id);
|
||||
|
@ -1876,7 +1986,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
|||
this.visit_generics(generics);
|
||||
|
||||
// Resolve the items within the impl.
|
||||
this.with_lifetime_rib(LifetimeRibKind::AnonymousPassThrough,
|
||||
this.with_lifetime_rib(LifetimeRibKind::AnonymousPassThrough(item_id),
|
||||
|this| {
|
||||
this.with_current_self_type(self_type, |this| {
|
||||
this.with_self_rib_ns(ValueNS, Res::SelfCtor(item_def_id), |this| {
|
||||
|
@ -1921,7 +2031,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
|||
this.with_generic_param_rib(
|
||||
&generics.params,
|
||||
AssocItemRibKind,
|
||||
LifetimeRibKind::Generics { span: generics.span, kind: LifetimeBinderKind::Function },
|
||||
LifetimeRibKind::Generics { parent: item.id, span: generics.span, kind: LifetimeBinderKind::Function },
|
||||
|this| {
|
||||
// If this is a trait impl, ensure the method
|
||||
// exists in trait
|
||||
|
@ -1950,7 +2060,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
|||
this.with_generic_param_rib(
|
||||
&generics.params,
|
||||
AssocItemRibKind,
|
||||
LifetimeRibKind::Generics { span: generics.span, kind: LifetimeBinderKind::Item },
|
||||
LifetimeRibKind::Generics { parent: item.id, span: generics.span, kind: LifetimeBinderKind::Item },
|
||||
|this| {
|
||||
// If this is a trait impl, ensure the type
|
||||
// exists in trait
|
||||
|
|
|
@ -1824,7 +1824,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
|
|||
|
||||
for rib in self.lifetime_ribs.iter().rev() {
|
||||
match rib.kind {
|
||||
LifetimeRibKind::Generics { span, kind } => {
|
||||
LifetimeRibKind::Generics { parent: _, span, kind } => {
|
||||
if !span.can_be_used_for_suggestions() && suggest_note {
|
||||
suggest_note = false; // Avoid displaying the same help multiple times.
|
||||
err.span_label(
|
||||
|
|
|
@ -29,7 +29,7 @@ use rustc_arena::{DroplessArena, TypedArena};
|
|||
use rustc_ast::node_id::NodeMap;
|
||||
use rustc_ast::{self as ast, NodeId, CRATE_NODE_ID};
|
||||
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::intern::Interned;
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
|
@ -901,6 +901,8 @@ pub struct Resolver<'a> {
|
|||
import_res_map: NodeMap<PerNS<Option<Res>>>,
|
||||
/// Resolutions for labels (node IDs of their corresponding blocks or loops).
|
||||
label_res_map: NodeMap<NodeId>,
|
||||
/// Resolutions for lifetimes.
|
||||
lifetimes_res_map: NodeMap<LifetimeRes>,
|
||||
|
||||
/// `CrateNum` resolutions of `extern crate` items.
|
||||
extern_crate_map: FxHashMap<LocalDefId, CrateNum>,
|
||||
|
@ -1153,6 +1155,10 @@ impl ResolverAstLowering for Resolver<'_> {
|
|||
self.label_res_map.get(&id).cloned()
|
||||
}
|
||||
|
||||
fn get_lifetime_res(&self, id: NodeId) -> Option<LifetimeRes> {
|
||||
self.lifetimes_res_map.get(&id).copied()
|
||||
}
|
||||
|
||||
fn create_stable_hashing_context(&self) -> StableHashingContext<'_> {
|
||||
StableHashingContext::new(self.session, &self.definitions, self.crate_loader.cstore())
|
||||
}
|
||||
|
@ -1301,6 +1307,7 @@ impl<'a> Resolver<'a> {
|
|||
partial_res_map: Default::default(),
|
||||
import_res_map: Default::default(),
|
||||
label_res_map: Default::default(),
|
||||
lifetimes_res_map: Default::default(),
|
||||
extern_crate_map: Default::default(),
|
||||
reexport_map: FxHashMap::default(),
|
||||
trait_map: NodeMap::default(),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue