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
|
@ -14,13 +14,15 @@ use crate::{ResolutionError, Resolver, Segment, UseError};
|
|||
use rustc_ast::ptr::P;
|
||||
use rustc_ast::visit::{self, AssocCtxt, BoundKind, FnCtxt, FnKind, Visitor};
|
||||
use rustc_ast::*;
|
||||
use rustc_ast_lowering::ResolverAstLowering;
|
||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||
use rustc_ast_lowering::{LifetimeRes, ResolverAstLowering};
|
||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap};
|
||||
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,8 @@ impl LifetimeBinderKind {
|
|||
#[derive(Debug)]
|
||||
struct LifetimeRib {
|
||||
kind: LifetimeRibKind,
|
||||
bindings: IdentMap<()>,
|
||||
// We need to preserve insertion order for async fns.
|
||||
bindings: FxIndexMap<Ident, (NodeId, LifetimeRes)>,
|
||||
}
|
||||
|
||||
impl LifetimeRib {
|
||||
|
@ -581,12 +584,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 +614,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 +639,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 +653,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 +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 {
|
||||
// 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 +707,50 @@ 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)
|
||||
});
|
||||
// Construct the list of in-scope lifetime parameters for async lowering.
|
||||
// We include all lifetime parameters, either named or "Fresh".
|
||||
// The order of those parameters does not matter, as long as it is
|
||||
// deterministic.
|
||||
let mut extra_lifetime_params =
|
||||
this.r.extra_lifetime_params_map.get(&fn_id).cloned().unwrap_or_default();
|
||||
for rib in this.lifetime_ribs.iter().rev() {
|
||||
extra_lifetime_params.extend(
|
||||
rib.bindings
|
||||
.iter()
|
||||
.map(|(&ident, &(node_id, res))| (ident, node_id, res)),
|
||||
);
|
||||
match rib.kind {
|
||||
LifetimeRibKind::Item => break,
|
||||
LifetimeRibKind::AnonymousCreateParameter(id) => {
|
||||
if let Some(earlier_fresh) =
|
||||
this.r.extra_lifetime_params_map.get(&id)
|
||||
{
|
||||
extra_lifetime_params.extend(earlier_fresh);
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
this.r.extra_lifetime_params_map.insert(async_node_id, extra_lifetime_params);
|
||||
|
||||
this.with_lifetime_rib(
|
||||
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 +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.
|
||||
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 +846,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 +875,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 +1141,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 +1153,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(&(_, region)) = rib.bindings.get(&normalized_ident) {
|
||||
self.record_lifetime_res(lifetime.id, region);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1123,6 +1174,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 +1184,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 +1207,64 @@ 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, 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))]
|
||||
fn resolve_elided_lifetimes_in_path(
|
||||
&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 '_
|
||||
// async fn foo(_: std::cell::Ref<u32>) { ... }
|
||||
LifetimeRibKind::AnonymousCreateParameter => {
|
||||
LifetimeRibKind::AnonymousCreateParameter(_) => {
|
||||
error = true;
|
||||
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
|
||||
// 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 +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
|
||||
/// 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 +1502,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 +1573,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 +1586,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 +1616,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 +1636,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 +1705,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 +1843,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, (param.id, res));
|
||||
continue;
|
||||
}
|
||||
};
|
||||
|
@ -1849,10 +1987,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 +2014,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 +2059,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 +2088,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
|
||||
|
@ -2655,9 +2793,9 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
|||
if !matches!(source, PathSource::TraitItem(..)) {
|
||||
// Avoid recording definition of `A::B` in `<T as A>::B::C`.
|
||||
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
|
||||
}
|
||||
|
||||
|
|
|
@ -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,10 @@ 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>,
|
||||
/// Lifetime parameters that lowering will have to introduce.
|
||||
extra_lifetime_params_map: NodeMap<Vec<(Ident, NodeId, LifetimeRes)>>,
|
||||
|
||||
/// `CrateNum` resolutions of `extern crate` items.
|
||||
extern_crate_map: FxHashMap<LocalDefId, CrateNum>,
|
||||
|
@ -1154,6 +1158,14 @@ 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 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<'_> {
|
||||
StableHashingContext::new(self.session, &self.definitions, self.crate_loader.cstore())
|
||||
}
|
||||
|
@ -1302,6 +1314,8 @@ impl<'a> Resolver<'a> {
|
|||
partial_res_map: Default::default(),
|
||||
import_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(),
|
||||
reexport_map: FxHashMap::default(),
|
||||
trait_map: NodeMap::default(),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue