summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_resolve/src/late.rs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_resolve/src/late.rs')
-rw-r--r--compiler/rustc_resolve/src/late.rs366
1 files changed, 211 insertions, 155 deletions
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index d8d82e125..00eb768ad 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -19,7 +19,7 @@ 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, LifetimeRes, PartialRes, PerNS};
-use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID};
+use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID, LOCAL_CRATE};
use rustc_hir::{BindingAnnotation, PrimTy, TraitCandidate};
use rustc_middle::middle::resolve_lifetime::Set1;
use rustc_middle::ty::DefIdTree;
@@ -35,7 +35,6 @@ use std::collections::{hash_map::Entry, BTreeSet};
use std::mem::{replace, take};
mod diagnostics;
-pub(crate) mod lifetimes;
type Res = def::Res<NodeId>;
@@ -226,22 +225,14 @@ enum LifetimeUseSet {
#[derive(Copy, Clone, Debug)]
enum LifetimeRibKind {
- /// This rib acts as a barrier to forbid reference to lifetimes of a parent item.
- Item,
-
+ // -- Ribs introducing named lifetimes
+ //
/// This rib declares generic parameters.
+ /// Only for this kind the `LifetimeRib::bindings` field can be non-empty.
Generics { binder: NodeId, span: Span, kind: LifetimeBinderKind },
- /// FIXME(const_generics): This patches over an ICE caused by non-'static lifetimes in const
- /// generics. We are disallowing this until we can decide on how we want to handle non-'static
- /// lifetimes in const generics. See issue #74052 for discussion.
- ConstGeneric,
-
- /// Non-static lifetimes are prohibited in anonymous constants under `min_const_generics`.
- /// This function will emit an error if `generic_const_exprs` is not enabled, the body identified by
- /// `body_id` is an anonymous constant and `lifetime_ref` is non-static.
- AnonConst,
-
+ // -- Ribs introducing unnamed lifetimes
+ //
/// Create a new anonymous lifetime parameter and reference it.
///
/// If `report_in_path`, report an error when encountering lifetime elision in a path:
@@ -258,16 +249,31 @@ enum LifetimeRibKind {
/// ```
AnonymousCreateParameter { binder: NodeId, report_in_path: bool },
+ /// Replace all anonymous lifetimes by provided lifetime.
+ Elided(LifetimeRes),
+
+ // -- Barrier ribs that stop lifetime lookup, or continue it but produce an error later.
+ //
/// Give a hard error when either `&` or `'_` is written. Used to
/// rule out things like `where T: Foo<'_>`. Does not imply an
/// error on default object bounds (e.g., `Box<dyn Foo>`).
AnonymousReportError,
- /// Replace all anonymous lifetimes by provided lifetime.
- Elided(LifetimeRes),
-
/// Signal we cannot find which should be the anonymous lifetime.
ElisionFailure,
+
+ /// FIXME(const_generics): This patches over an ICE caused by non-'static lifetimes in const
+ /// generics. We are disallowing this until we can decide on how we want to handle non-'static
+ /// lifetimes in const generics. See issue #74052 for discussion.
+ ConstGeneric,
+
+ /// Non-static lifetimes are prohibited in anonymous constants under `min_const_generics`.
+ /// This function will emit an error if `generic_const_exprs` is not enabled, the body
+ /// identified by `body_id` is an anonymous constant and `lifetime_ref` is non-static.
+ AnonConst,
+
+ /// This rib acts as a barrier to forbid reference to lifetimes of a parent item.
+ Item,
}
#[derive(Copy, Clone, Debug)]
@@ -415,7 +421,8 @@ impl<'a> PathSource<'a> {
| DefKind::ForeignTy,
_,
) | Res::PrimTy(..)
- | Res::SelfTy { .. }
+ | Res::SelfTyParam { .. }
+ | Res::SelfTyAlias { .. }
),
PathSource::Trait(AliasPossibility::No) => matches!(res, Res::Def(DefKind::Trait, _)),
PathSource::Trait(AliasPossibility::Maybe) => {
@@ -449,7 +456,8 @@ impl<'a> PathSource<'a> {
| DefKind::TyAlias
| DefKind::AssocTy,
_,
- ) | Res::SelfTy { .. }
+ ) | Res::SelfTyParam { .. }
+ | Res::SelfTyAlias { .. }
),
PathSource::TraitItem(ns) => match res {
Res::Def(DefKind::AssocConst | DefKind::AssocFn, _) if ns == ValueNS => true,
@@ -517,6 +525,9 @@ struct DiagnosticMetadata<'ast> {
/// Used to detect possible `if let` written without `let` and to provide structured suggestion.
in_if_condition: Option<&'ast Expr>,
+ /// Used to detect possible new binding written without `let` and to provide structured suggestion.
+ in_assignment: Option<&'ast Expr>,
+
/// If we are currently in a trait object definition. Used to point at the bounds when
/// encountering a struct or enum.
current_trait_object: Option<&'ast [ast::GenericBound]>,
@@ -641,8 +652,7 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
// Check whether we should interpret this as a bare trait object.
if qself.is_none()
&& let Some(partial_res) = self.r.partial_res_map.get(&ty.id)
- && partial_res.unresolved_segments() == 0
- && let Res::Def(DefKind::Trait | DefKind::TraitAlias, _) = partial_res.base_res()
+ && let Some(Res::Def(DefKind::Trait | DefKind::TraitAlias, _)) = partial_res.full_res()
{
// This path is actually a bare trait object. In case of a bare `Fn`-trait
// object with anonymous lifetimes, we need this rib to correctly place the
@@ -749,35 +759,31 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
fn visit_foreign_item(&mut self, foreign_item: &'ast ForeignItem) {
match foreign_item.kind {
ForeignItemKind::TyAlias(box TyAlias { ref generics, .. }) => {
- self.with_lifetime_rib(LifetimeRibKind::Item, |this| {
- this.with_generic_param_rib(
- &generics.params,
- ItemRibKind(HasGenericParams::Yes(generics.span)),
- LifetimeRibKind::Generics {
- binder: foreign_item.id,
- kind: LifetimeBinderKind::Item,
- span: generics.span,
- },
- |this| visit::walk_foreign_item(this, foreign_item),
- )
- });
+ self.with_generic_param_rib(
+ &generics.params,
+ ItemRibKind(HasGenericParams::Yes(generics.span)),
+ LifetimeRibKind::Generics {
+ binder: foreign_item.id,
+ kind: LifetimeBinderKind::Item,
+ span: generics.span,
+ },
+ |this| visit::walk_foreign_item(this, foreign_item),
+ );
}
ForeignItemKind::Fn(box Fn { ref generics, .. }) => {
- self.with_lifetime_rib(LifetimeRibKind::Item, |this| {
- this.with_generic_param_rib(
- &generics.params,
- ItemRibKind(HasGenericParams::Yes(generics.span)),
- LifetimeRibKind::Generics {
- binder: foreign_item.id,
- kind: LifetimeBinderKind::Function,
- span: generics.span,
- },
- |this| visit::walk_foreign_item(this, foreign_item),
- )
- });
+ self.with_generic_param_rib(
+ &generics.params,
+ ItemRibKind(HasGenericParams::Yes(generics.span)),
+ LifetimeRibKind::Generics {
+ binder: foreign_item.id,
+ kind: LifetimeBinderKind::Function,
+ span: generics.span,
+ },
+ |this| visit::walk_foreign_item(this, foreign_item),
+ );
}
ForeignItemKind::Static(..) => {
- self.with_item_rib(|this| {
+ self.with_static_rib(|this| {
visit::walk_foreign_item(this, foreign_item);
});
}
@@ -806,7 +812,12 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
sig.decl.has_self(),
sig.decl.inputs.iter().map(|Param { ty, .. }| (None, &**ty)),
&sig.decl.output,
- )
+ );
+
+ this.record_lifetime_params_for_async(
+ fn_id,
+ sig.header.asyncness.opt_return_id(),
+ );
},
);
return;
@@ -848,41 +859,7 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
},
);
- // Construct the list of in-scope lifetime parameters for async lowering.
- // We include all lifetime parameters, either named or "Fresh".
- // The order of those parameters does not matter, as long as it is
- // deterministic.
- if let Some((async_node_id, _)) = async_node_id {
- 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 {
- binder, ..
- } => {
- if let Some(earlier_fresh) =
- this.r.extra_lifetime_params_map.get(&binder)
- {
- extra_lifetime_params.extend(earlier_fresh);
- }
- }
- _ => {}
- }
- }
- this.r
- .extra_lifetime_params_map
- .insert(async_node_id, extra_lifetime_params);
- }
+ this.record_lifetime_params_for_async(fn_id, async_node_id);
if let Some(body) = body {
// Ignore errors in function bodies if this is rustdoc
@@ -1421,9 +1398,8 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
return self.resolve_anonymous_lifetime(lifetime, false);
}
- let mut indices = (0..self.lifetime_ribs.len()).rev();
- for i in &mut indices {
- let rib = &self.lifetime_ribs[i];
+ let mut lifetime_rib_iter = self.lifetime_ribs.iter().rev();
+ while let Some(rib) = lifetime_rib_iter.next() {
let normalized_ident = ident.normalize_to_macros_2_0();
if let Some(&(_, res)) = rib.bindings.get(&normalized_ident) {
self.record_lifetime_res(lifetime.id, res, LifetimeElisionCandidate::Named);
@@ -1453,9 +1429,10 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
} else {
LifetimeUseSet::Many
}),
- LifetimeRibKind::Generics { .. }
- | LifetimeRibKind::ConstGeneric
- | LifetimeRibKind::AnonConst => None,
+ LifetimeRibKind::Generics { .. } => None,
+ LifetimeRibKind::ConstGeneric | LifetimeRibKind::AnonConst => {
+ span_bug!(ident.span, "unexpected rib kind: {:?}", rib.kind)
+ }
})
.unwrap_or(LifetimeUseSet::Many);
debug!(?use_ctxt, ?use_set);
@@ -1490,13 +1467,16 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
);
return;
}
- _ => {}
+ LifetimeRibKind::AnonymousCreateParameter { .. }
+ | LifetimeRibKind::Elided(_)
+ | LifetimeRibKind::Generics { .. }
+ | LifetimeRibKind::ElisionFailure
+ | LifetimeRibKind::AnonymousReportError => {}
}
}
let mut outer_res = None;
- for i in indices {
- let rib = &self.lifetime_ribs[i];
+ for rib in lifetime_rib_iter {
let normalized_ident = ident.normalize_to_macros_2_0();
if let Some((&outer, _)) = rib.bindings.get_key_value(&normalized_ident) {
outer_res = Some(outer);
@@ -1523,8 +1503,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
count: 1,
};
let elision_candidate = LifetimeElisionCandidate::Missing(missing_lifetime);
- for i in (0..self.lifetime_ribs.len()).rev() {
- let rib = &mut self.lifetime_ribs[i];
+ for rib in self.lifetime_ribs.iter().rev() {
debug!(?rib.kind);
match rib.kind {
LifetimeRibKind::AnonymousCreateParameter { binder, .. } => {
@@ -1564,9 +1543,11 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
return;
}
LifetimeRibKind::Item => break,
- LifetimeRibKind::Generics { .. }
- | LifetimeRibKind::ConstGeneric
- | LifetimeRibKind::AnonConst => {}
+ LifetimeRibKind::Generics { .. } | LifetimeRibKind::ConstGeneric => {}
+ LifetimeRibKind::AnonConst => {
+ // There is always an `Elided(LifetimeRes::Static)` inside an `AnonConst`.
+ span_bug!(lifetime.ident.span, "unexpected rib kind: {:?}", rib.kind)
+ }
}
}
self.record_lifetime_res(lifetime.id, LifetimeRes::Error, elision_candidate);
@@ -1781,9 +1762,11 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
self.report_missing_lifetime_specifiers(vec![missing_lifetime], None);
break;
}
- LifetimeRibKind::Generics { .. }
- | LifetimeRibKind::ConstGeneric
- | LifetimeRibKind::AnonConst => {}
+ LifetimeRibKind::Generics { .. } | LifetimeRibKind::ConstGeneric => {}
+ LifetimeRibKind::AnonConst => {
+ // There is always an `Elided(LifetimeRes::Static)` inside an `AnonConst`.
+ span_bug!(elided_lifetime_span, "unexpected rib kind: {:?}", rib.kind)
+ }
}
}
@@ -1896,9 +1879,11 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
let mut bindings = smallvec![(PatBoundCtx::Product, Default::default())];
for (index, (pat, ty)) in inputs.enumerate() {
debug!(?pat, ?ty);
- if let Some(pat) = pat {
- self.resolve_pattern(pat, PatternSource::FnParam, &mut bindings);
- }
+ self.with_lifetime_rib(LifetimeRibKind::Elided(LifetimeRes::Infer), |this| {
+ if let Some(pat) = pat {
+ this.resolve_pattern(pat, PatternSource::FnParam, &mut bindings);
+ }
+ });
// Record elision candidates only for this parameter.
debug_assert_matches!(self.lifetime_elision_candidates, None);
@@ -1992,11 +1977,11 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
match ty.kind {
TyKind::ImplicitSelf => true,
TyKind::Path(None, _) => {
- let path_res = self.r.partial_res_map[&ty.id].base_res();
- if let Res::SelfTy { .. } = path_res {
+ let path_res = self.r.partial_res_map[&ty.id].full_res();
+ if let Some(Res::SelfTyParam { .. } | Res::SelfTyAlias { .. }) = path_res {
return true;
}
- Some(path_res) == self.impl_self
+ self.impl_self.is_some() && path_res == self.impl_self
}
_ => false,
}
@@ -2033,7 +2018,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
None
}
})
- .map(|res| res.base_res())
+ .and_then(|res| res.full_res())
.filter(|res| {
// Permit the types that unambiguously always
// result in the same type constructor being used
@@ -2114,7 +2099,11 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|this| {
let item_def_id = this.r.local_def_id(item.id).to_def_id();
this.with_self_rib(
- Res::SelfTy { trait_: None, alias_to: Some((item_def_id, false)) },
+ Res::SelfTyAlias {
+ alias_to: item_def_id,
+ forbid_generic: false,
+ is_trait_impl: false,
+ },
|this| {
visit::walk_item(this, item);
},
@@ -2228,14 +2217,11 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
},
|this| {
let local_def_id = this.r.local_def_id(item.id).to_def_id();
- this.with_self_rib(
- Res::SelfTy { trait_: Some(local_def_id), alias_to: None },
- |this| {
- this.visit_generics(generics);
- walk_list!(this, visit_param_bound, bounds, BoundKind::SuperTraits);
- this.resolve_trait_items(items);
- },
- );
+ this.with_self_rib(Res::SelfTyParam { trait_: local_def_id }, |this| {
+ this.visit_generics(generics);
+ walk_list!(this, visit_param_bound, bounds, BoundKind::SuperTraits);
+ this.resolve_trait_items(items);
+ });
},
);
}
@@ -2252,13 +2238,10 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
},
|this| {
let local_def_id = this.r.local_def_id(item.id).to_def_id();
- this.with_self_rib(
- Res::SelfTy { trait_: Some(local_def_id), alias_to: None },
- |this| {
- this.visit_generics(generics);
- walk_list!(this, visit_param_bound, bounds, BoundKind::Bound);
- },
- );
+ this.with_self_rib(Res::SelfTyParam { trait_: local_def_id }, |this| {
+ this.visit_generics(generics);
+ walk_list!(this, visit_param_bound, bounds, BoundKind::Bound);
+ });
},
);
}
@@ -2270,7 +2253,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
}
ItemKind::Static(ref ty, _, ref expr) | ItemKind::Const(_, ref ty, ref expr) => {
- self.with_item_rib(|this| {
+ self.with_static_rib(|this| {
this.with_lifetime_rib(LifetimeRibKind::Elided(LifetimeRes::Static), |this| {
this.visit_ty(ty);
});
@@ -2465,11 +2448,9 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
self.label_ribs.pop();
}
- fn with_item_rib(&mut self, f: impl FnOnce(&mut Self)) {
+ fn with_static_rib(&mut self, f: impl FnOnce(&mut Self)) {
let kind = ItemRibKind(HasGenericParams::No);
- self.with_lifetime_rib(LifetimeRibKind::Item, |this| {
- this.with_rib(ValueNS, kind, |this| this.with_rib(TypeNS, kind, f))
- })
+ self.with_rib(ValueNS, kind, |this| this.with_rib(TypeNS, kind, f))
}
// HACK(min_const_generics,const_evaluatable_unchecked): We
@@ -2562,7 +2543,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
AssocItemKind::Fn(box Fn { generics, .. }) => {
walk_assoc_item(self, generics, LifetimeBinderKind::Function, item);
}
- AssocItemKind::TyAlias(box TyAlias { generics, .. }) => self
+ AssocItemKind::Type(box TyAlias { generics, .. }) => self
.with_lifetime_rib(LifetimeRibKind::AnonymousReportError, |this| {
walk_assoc_item(this, generics, LifetimeBinderKind::Item, item)
}),
@@ -2595,7 +2576,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
Finalize::new(trait_ref.ref_id, trait_ref.path.span),
);
self.diagnostic_metadata.currently_processing_impl_trait = None;
- if let Some(def_id) = res.base_res().opt_def_id() {
+ if let Some(def_id) = res.expect_full_res().opt_def_id() {
new_id = Some(def_id);
new_val = Some((self.r.expect_module(def_id), trait_ref.clone()));
}
@@ -2640,7 +2621,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
},
|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_self_rib(Res::SelfTyParam { trait_: LOCAL_CRATE.as_def_id() }, |this| {
this.with_lifetime_rib(
LifetimeRibKind::AnonymousCreateParameter {
binder: item_id,
@@ -2664,9 +2645,10 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
}
let item_def_id = item_def_id.to_def_id();
- let res = Res::SelfTy {
- trait_: trait_id,
- alias_to: Some((item_def_id, false)),
+ let res = Res::SelfTyAlias {
+ alias_to: item_def_id,
+ forbid_generic: false,
+ is_trait_impl: trait_id.is_some()
};
this.with_self_rib(res, |this| {
if let Some(trait_ref) = opt_trait_reference.as_ref() {
@@ -2682,8 +2664,9 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
this.with_current_self_type(self_type, |this| {
this.with_self_rib_ns(ValueNS, Res::SelfCtor(item_def_id), |this| {
debug!("resolve_implementation with_self_rib_ns(ValueNS, ...)");
+ let mut seen_trait_items = Default::default();
for item in impl_items {
- this.resolve_impl_item(&**item);
+ this.resolve_impl_item(&**item, &mut seen_trait_items);
}
});
});
@@ -2697,7 +2680,11 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
);
}
- fn resolve_impl_item(&mut self, item: &'ast AssocItem) {
+ fn resolve_impl_item(
+ &mut self,
+ item: &'ast AssocItem,
+ seen_trait_items: &mut FxHashMap<DefId, Span>,
+ ) {
use crate::ResolutionError::*;
match &item.kind {
AssocItemKind::Const(_, ty, default) => {
@@ -2710,6 +2697,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
&item.kind,
ValueNS,
item.span,
+ seen_trait_items,
|i, s, c| ConstNotMemberOfTrait(i, s, c),
);
@@ -2750,6 +2738,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
&item.kind,
ValueNS,
item.span,
+ seen_trait_items,
|i, s, c| MethodNotMemberOfTrait(i, s, c),
);
@@ -2757,8 +2746,8 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
},
);
}
- AssocItemKind::TyAlias(box TyAlias { generics, .. }) => {
- debug!("resolve_implementation AssocItemKind::TyAlias");
+ AssocItemKind::Type(box TyAlias { generics, .. }) => {
+ debug!("resolve_implementation AssocItemKind::Type");
// We also need a new scope for the impl item type parameters.
self.with_generic_param_rib(
&generics.params,
@@ -2778,6 +2767,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
&item.kind,
TypeNS,
item.span,
+ seen_trait_items,
|i, s, c| TypeNotMemberOfTrait(i, s, c),
);
@@ -2799,6 +2789,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
kind: &AssocItemKind,
ns: Namespace,
span: Span,
+ seen_trait_items: &mut FxHashMap<DefId, Span>,
err: F,
) where
F: FnOnce(Ident, String, Option<Symbol>) -> ResolutionError<'a>,
@@ -2831,9 +2822,27 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
};
let res = binding.res();
- let Res::Def(def_kind, _) = res else { bug!() };
+ let Res::Def(def_kind, id_in_trait) = res else { bug!() };
+
+ match seen_trait_items.entry(id_in_trait) {
+ Entry::Occupied(entry) => {
+ self.report_error(
+ span,
+ ResolutionError::TraitImplDuplicate {
+ name: ident.name,
+ old_span: *entry.get(),
+ trait_item_span: binding.span,
+ },
+ );
+ return;
+ }
+ Entry::Vacant(entry) => {
+ entry.insert(span);
+ }
+ };
+
match (def_kind, kind) {
- (DefKind::AssocTy, AssocItemKind::TyAlias(..))
+ (DefKind::AssocTy, AssocItemKind::Type(..))
| (DefKind::AssocFn, AssocItemKind::Fn(..))
| (DefKind::AssocConst, AssocItemKind::Const(..)) => {
self.r.record_partial_res(id, PartialRes::new(res));
@@ -2847,7 +2856,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
let (code, kind) = match kind {
AssocItemKind::Const(..) => (rustc_errors::error_code!(E0323), "const"),
AssocItemKind::Fn(..) => (rustc_errors::error_code!(E0324), "method"),
- AssocItemKind::TyAlias(..) => (rustc_errors::error_code!(E0325), "type"),
+ AssocItemKind::Type(..) => (rustc_errors::error_code!(E0325), "type"),
AssocItemKind::MacCall(..) => span_bug!(span, "unexpanded macro"),
};
let trait_path = path_names_to_string(path);
@@ -2865,10 +2874,13 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
fn resolve_params(&mut self, params: &'ast [Param]) {
let mut bindings = smallvec![(PatBoundCtx::Product, Default::default())];
- for Param { pat, ty, .. } in params {
- self.resolve_pattern(pat, PatternSource::FnParam, &mut bindings);
+ self.with_lifetime_rib(LifetimeRibKind::Elided(LifetimeRes::Infer), |this| {
+ for Param { pat, .. } in params {
+ this.resolve_pattern(pat, PatternSource::FnParam, &mut bindings);
+ }
+ });
+ for Param { ty, .. } in params {
self.visit_ty(ty);
- debug!("(resolving function / closure) recorded parameter");
}
}
@@ -2923,7 +2935,10 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
}
fn is_base_res_local(&self, nid: NodeId) -> bool {
- matches!(self.r.partial_res_map.get(&nid).map(|res| res.base_res()), Some(Res::Local(..)))
+ matches!(
+ self.r.partial_res_map.get(&nid).map(|res| res.expect_full_res()),
+ Some(Res::Local(..))
+ )
}
/// Checks that all of the arms in an or-pattern have exactly the
@@ -3326,6 +3341,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
instead,
suggestion,
path: path.into(),
+ is_call: source.is_call(),
});
}
@@ -3390,6 +3406,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
instead: false,
suggestion: None,
path: path.into(),
+ is_call: source.is_call(),
});
} else {
err.cancel();
@@ -3408,12 +3425,11 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
source.defer_to_typeck(),
finalize,
) {
- Ok(Some(partial_res)) if partial_res.unresolved_segments() == 0 => {
- if source.is_expected(partial_res.base_res()) || partial_res.base_res() == Res::Err
- {
+ Ok(Some(partial_res)) if let Some(res) = partial_res.full_res() => {
+ if source.is_expected(res) || res == Res::Err {
partial_res
} else {
- report_errors(self, Some(partial_res.base_res()))
+ report_errors(self, Some(res))
}
}
@@ -3621,20 +3637,21 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
};
if path.len() > 1
- && result.base_res() != Res::Err
+ && let Some(res) = result.full_res()
+ && res != Res::Err
&& path[0].ident.name != kw::PathRoot
&& path[0].ident.name != kw::DollarCrate
{
let unqualified_result = {
match self.resolve_path(&[*path.last().unwrap()], Some(ns), None) {
- PathResult::NonModule(path_res) => path_res.base_res(),
+ PathResult::NonModule(path_res) => path_res.expect_full_res(),
PathResult::Module(ModuleOrUniformRoot::Module(module)) => {
module.res().unwrap()
}
_ => return Ok(Some(result)),
}
};
- if result.base_res() == unqualified_result {
+ if res == unqualified_result {
let lint = lint::builtin::UNUSED_QUALIFICATIONS;
self.r.lint_buffer.buffer_lint(
lint,
@@ -3828,9 +3845,8 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
ExprKind::Field(ref subexpression, _) => {
self.resolve_expr(subexpression, Some(expr));
}
- ExprKind::MethodCall(ref segment, ref arguments, _) => {
- let mut arguments = arguments.iter();
- self.resolve_expr(arguments.next().unwrap(), Some(expr));
+ ExprKind::MethodCall(ref segment, ref receiver, ref arguments, _) => {
+ self.resolve_expr(receiver, Some(expr));
for argument in arguments {
self.resolve_expr(argument, None);
}
@@ -3927,6 +3943,11 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
self.resolve_expr(elem, Some(expr));
self.visit_expr(idx);
}
+ ExprKind::Assign(..) => {
+ let old = self.diagnostic_metadata.in_assignment.replace(expr);
+ visit::walk_expr(self, expr);
+ self.diagnostic_metadata.in_assignment = old;
+ }
_ => {
visit::walk_expr(self, expr);
}
@@ -3962,6 +3983,41 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
Some((ident.name, ns)),
)
}
+
+ /// 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.
+ fn record_lifetime_params_for_async(
+ &mut self,
+ fn_id: NodeId,
+ async_node_id: Option<(NodeId, Span)>,
+ ) {
+ if let Some((async_node_id, span)) = async_node_id {
+ let mut extra_lifetime_params =
+ self.r.extra_lifetime_params_map.get(&fn_id).cloned().unwrap_or_default();
+ for rib in self.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 { binder, .. } => {
+ if let Some(earlier_fresh) = self.r.extra_lifetime_params_map.get(&binder) {
+ extra_lifetime_params.extend(earlier_fresh);
+ }
+ }
+ LifetimeRibKind::Generics { .. } => {}
+ _ => {
+ // We are in a function definition. We should only find `Generics`
+ // and `AnonymousCreateParameter` inside the innermost `Item`.
+ span_bug!(span, "unexpected rib kind: {:?}", rib.kind)
+ }
+ }
+ }
+ self.r.extra_lifetime_params_map.insert(async_node_id, extra_lifetime_params);
+ }
+ }
}
struct LifetimeCountVisitor<'a, 'b> {