X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=compiler%2Frustc_resolve%2Fsrc%2Flate.rs;h=e67f7f03516803c0a7cb7ca7acfb57b9f05f4846;hb=46b8e7488eae116722196e8390c1bd2ea2e396cf;hp=fbb1a868bdefd683103bb3b08196781f2d54606b;hpb=6f0acbcbd064d924afb0f3a04480fd0d69c5bc51;p=rust.git diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index fbb1a868bde..e67f7f03516 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -7,7 +7,7 @@ use RibKind::*; -use crate::{path_names_to_string, BindingError, CrateLint, NameBinding, ToNameBinding}; +use crate::{path_names_to_string, BindingError, CrateLint, LexicalScopeBinding}; use crate::{Module, ModuleOrUniformRoot, ParentScope, PathResult}; use crate::{ResolutionError, Resolver, Segment, UseError}; @@ -21,22 +21,27 @@ use rustc_hir::def::{self, CtorKind, DefKind, PartialRes, PerNS}; use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX}; use rustc_hir::{PrimTy, TraitCandidate}; -use rustc_middle::{bug, span_bug, ty}; +use rustc_middle::{bug, span_bug}; use rustc_session::lint; -use rustc_span::source_map::{respan, Spanned}; use rustc_span::symbol::{kw, sym, Ident, Symbol}; -use rustc_span::{Span, DUMMY_SP}; +use rustc_span::Span; use smallvec::{smallvec, SmallVec}; -use tracing::debug; +use rustc_span::source_map::{respan, Spanned}; use std::collections::{hash_map::Entry, BTreeSet}; use std::mem::{replace, take}; +use tracing::debug; mod diagnostics; crate mod lifetimes; type Res = def::Res; +type IdentMap = FxHashMap; + +/// Map from the name in a pattern to its binding mode. +type BindingMap = IdentMap; + #[derive(Copy, Clone, Debug)] struct BindingInfo { span: Span, @@ -167,8 +172,8 @@ impl RibKind<'_> { /// The resolution keeps a separate stack of ribs as it traverses the AST for each namespace. When /// resolving, the name is looked up from inside out. #[derive(Debug)] -crate struct Rib<'a, R = &'a NameBinding<'a>> { - pub bindings: FxHashMap, +crate struct Rib<'a, R = Res> { + pub bindings: IdentMap, pub kind: RibKind<'a>, } @@ -493,8 +498,8 @@ fn visit_poly_trait_ref(&mut self, tref: &'ast PolyTraitRef, m: &'ast TraitBound } fn visit_foreign_item(&mut self, foreign_item: &'ast ForeignItem) { match foreign_item.kind { - ForeignItemKind::Fn(box FnKind(_, _, ref generics, _)) - | ForeignItemKind::TyAlias(box TyAliasKind(_, ref generics, ..)) => { + ForeignItemKind::Fn(box Fn { ref generics, .. }) + | ForeignItemKind::TyAlias(box TyAlias { ref generics, .. }) => { self.with_generic_param_rib(generics, ItemRibKind(HasGenericParams::Yes), |this| { visit::walk_foreign_item(this, foreign_item); }); @@ -562,12 +567,12 @@ fn visit_generics(&mut self, generics: &'ast Generics) { GenericParamKind::Type { .. } => { forward_ty_ban_rib .bindings - .insert(Ident::with_dummy_span(param.ident.name), self.r.dummy_binding); + .insert(Ident::with_dummy_span(param.ident.name), Res::Err); } GenericParamKind::Const { .. } => { forward_const_ban_rib .bindings - .insert(Ident::with_dummy_span(param.ident.name), self.r.dummy_binding); + .insert(Ident::with_dummy_span(param.ident.name), Res::Err); } GenericParamKind::Lifetime => {} } @@ -584,9 +589,7 @@ fn visit_generics(&mut self, generics: &'ast Generics) { // such as in the case of `trait Add`.) if self.diagnostic_metadata.current_self_item.is_some() { // (`Some` if + only if we are in ADT's generics.) - forward_ty_ban_rib - .bindings - .insert(Ident::with_dummy_span(kw::SelfUpper), self.r.dummy_binding); + forward_ty_ban_rib.bindings.insert(Ident::with_dummy_span(kw::SelfUpper), Res::Err); } for param in &generics.params { @@ -734,17 +737,15 @@ fn resolve_ident_in_lexical_scope( ns: Namespace, record_used_id: Option, path_span: Span, - ) -> Option<&'a NameBinding<'a>> { - self.r - .resolve_ident_in_lexical_scope( - ident, - ns, - &self.parent_scope, - record_used_id, - path_span, - &self.ribs[ns], - ) - .ok() + ) -> Option> { + self.r.resolve_ident_in_lexical_scope( + ident, + ns, + &self.parent_scope, + record_used_id, + path_span, + &self.ribs[ns], + ) } fn resolve_path( @@ -902,10 +903,6 @@ fn resolve_adt(&mut self, item: &'ast Item, generics: &'ast Generics) { } fn future_proof_import(&mut self, use_tree: &UseTree) { - if !self.should_report_errs() { - return; - } - let segments = &use_tree.prefix.segments; if !segments.is_empty() { let ident = segments[0].ident; @@ -917,42 +914,31 @@ fn future_proof_import(&mut self, use_tree: &UseTree) { UseTreeKind::Simple(..) if segments.len() == 1 => &[TypeNS, ValueNS][..], _ => &[TypeNS], }; - - let from_ribs = |binding: &NameBinding<'_>| { - matches!( - binding.res(), - Res::Local(..) - | Res::SelfTy(..) - | Res::Def(DefKind::TyParam | DefKind::ConstParam, ..) - ) - }; let report_error = |this: &Self, ns| { let what = if ns == TypeNS { "type parameters" } else { "local variables" }; - let msg = format!("imports cannot refer to {what}"); - this.r.session.span_err(ident.span, &msg); + if this.should_report_errs() { + this.r + .session + .span_err(ident.span, &format!("imports cannot refer to {}", what)); + } }; for &ns in nss { - if let Some(binding) = - self.resolve_ident_in_lexical_scope(ident, ns, None, use_tree.prefix.span) - { - if from_ribs(binding) { + match self.resolve_ident_in_lexical_scope(ident, ns, None, use_tree.prefix.span) { + Some(LexicalScopeBinding::Res(..)) => { report_error(self, ns); - } else { + } + Some(LexicalScopeBinding::Item(binding)) => { let orig_unusable_binding = replace(&mut self.r.unusable_binding, Some(binding)); - if let Some(binding) = self.resolve_ident_in_lexical_scope( - ident, - ns, - None, - use_tree.prefix.span, - ) { - if from_ribs(binding) { - report_error(self, ns); - } + if let Some(LexicalScopeBinding::Res(..)) = self + .resolve_ident_in_lexical_scope(ident, ns, None, use_tree.prefix.span) + { + report_error(self, ns); } self.r.unusable_binding = orig_unusable_binding; } + None => {} } } } else if let UseTreeKind::Nested(use_trees) = &use_tree.kind { @@ -967,8 +953,8 @@ fn resolve_item(&mut self, item: &'ast Item) { debug!("(resolving item) resolving {} ({:?})", name, item.kind); match item.kind { - ItemKind::TyAlias(box TyAliasKind(_, ref generics, _, _)) - | ItemKind::Fn(box FnKind(_, _, ref generics, _)) => { + ItemKind::TyAlias(box TyAlias { ref generics, .. }) + | ItemKind::Fn(box Fn { ref generics, .. }) => { self.compute_num_lifetime_params(item.id, generics); self.with_generic_param_rib(generics, ItemRibKind(HasGenericParams::Yes), |this| { visit::walk_item(this, item) @@ -982,7 +968,7 @@ fn resolve_item(&mut self, item: &'ast Item) { self.resolve_adt(item, generics); } - ItemKind::Impl(box ImplKind { + ItemKind::Impl(box Impl { ref generics, ref of_trait, ref self_ty, @@ -993,7 +979,7 @@ fn resolve_item(&mut self, item: &'ast Item) { self.resolve_implementation(generics, of_trait, &self_ty, item.id, impl_items); } - ItemKind::Trait(box TraitKind(.., ref generics, ref bounds, ref trait_items)) => { + ItemKind::Trait(box Trait { ref generics, ref bounds, ref items, .. }) => { self.compute_num_lifetime_params(item.id, generics); // Create a new rib for the trait-wide type parameters. self.with_generic_param_rib(generics, ItemRibKind(HasGenericParams::Yes), |this| { @@ -1008,8 +994,8 @@ fn resolve_item(&mut self, item: &'ast Item) { }); }; - this.with_trait_items(trait_items, |this| { - for item in trait_items { + this.with_trait_items(items, |this| { + for item in items { match &item.kind { AssocItemKind::Const(_, ty, default) => { this.visit_ty(ty); @@ -1029,10 +1015,10 @@ fn resolve_item(&mut self, item: &'ast Item) { ); } } - AssocItemKind::Fn(box FnKind(_, _, generics, _)) => { + AssocItemKind::Fn(box Fn { generics, .. }) => { walk_assoc_item(this, generics, item); } - AssocItemKind::TyAlias(box TyAliasKind(_, generics, _, _)) => { + AssocItemKind::TyAlias(box TyAlias { generics, .. }) => { walk_assoc_item(this, generics, item); } AssocItemKind::MacCall(_) => { @@ -1149,12 +1135,8 @@ fn with_generic_param_rib<'c, F>(&'c mut self, generics: &'c Generics, kind: Rib _ => unreachable!(), }; let res = Res::Def(def_kind, self.r.local_def_id(param.id).to_def_id()); - let binding = - (res, ty::Visibility::Invisible, param.ident.span, self.parent_scope.expansion) - .to_name_binding(self.r.arenas); - self.r.record_partial_res(param.id, PartialRes::new(res)); - rib.bindings.insert(ident, binding); + rib.bindings.insert(ident, res); } self.ribs[ValueNS].push(function_value_rib); @@ -1274,12 +1256,10 @@ fn with_optional_trait_ref( } fn with_self_rib_ns(&mut self, ns: Namespace, self_res: Res, f: impl FnOnce(&mut Self)) { - let binding = (self_res, ty::Visibility::Invisible, DUMMY_SP, self.parent_scope.expansion) - .to_name_binding(self.r.arenas); let mut self_type_rib = Rib::new(NormalRibKind); // Plain insert (no renaming, since types are not currently hygienic) - self_type_rib.bindings.insert(Ident::with_dummy_span(kw::SelfUpper), binding); + self_type_rib.bindings.insert(Ident::with_dummy_span(kw::SelfUpper), self_res); self.ribs[ns].push(self_type_rib); f(self); self.ribs[ns].pop(); @@ -1358,7 +1338,7 @@ fn resolve_implementation( }, ); } - AssocItemKind::Fn(box FnKind(.., generics, _)) => { + AssocItemKind::Fn(box Fn { generics, .. }) => { debug!("resolve_implementation AssocItemKind::Fn"); // We also need a new scope for the impl item type parameters. this.with_generic_param_rib( @@ -1383,12 +1363,9 @@ fn resolve_implementation( }, ); } - AssocItemKind::TyAlias(box TyAliasKind( - _, - generics, - _, - _, - )) => { + AssocItemKind::TyAlias(box TyAlias { + generics, .. + }) => { debug!("resolve_implementation AssocItemKind::TyAlias"); // We also need a new scope for the impl item type parameters. this.with_generic_param_rib( @@ -1490,7 +1467,7 @@ fn resolve_local(&mut self, local: &'ast Local) { /// this is done hygienically. This could arise for a macro /// that expands into an or-pattern where one 'x' was from the /// user and one 'x' came from the macro. - fn binding_mode_map(&mut self, pat: &Pat) -> FxHashMap { + fn binding_mode_map(&mut self, pat: &Pat) -> BindingMap { let mut binding_map = FxHashMap::default(); pat.walk(&mut |pat| { @@ -1523,7 +1500,7 @@ fn is_base_res_local(&self, nid: NodeId) -> bool { /// Checks that all of the arms in an or-pattern have exactly the /// same set of bindings, with the same binding modes for each. - fn check_consistent_bindings(&mut self, pats: &[P]) -> Vec> { + fn check_consistent_bindings(&mut self, pats: &[P]) -> Vec { let mut missing_vars = FxHashMap::default(); let mut inconsistent_vars = FxHashMap::default(); @@ -1665,6 +1642,7 @@ fn resolve_pattern_inner( .try_resolve_as_non_binding(pat_src, pat, bmode, ident, has_sub) .unwrap_or_else(|| self.fresh_binding(ident, pat.id, pat_src, bindings)); self.r.record_partial_res(pat.id, PartialRes::new(res)); + self.r.record_pat_span(pat.id, pat.span); } PatKind::TupleStruct(ref qself, ref path, ref sub_patterns) => { self.smart_resolve_path( @@ -1754,24 +1732,18 @@ fn fresh_binding( if already_bound_or { // `Variant1(a) | Variant2(a)`, ok // Reuse definition from the first `a`. - self.innermost_rib_bindings(ValueNS)[&ident].res() + self.innermost_rib_bindings(ValueNS)[&ident] } else { let res = Res::Local(pat_id); if ident_valid { // A completely fresh binding add to the set if it's valid. - let binding = - (res, ty::Visibility::Invisible, ident.span, self.parent_scope.expansion) - .to_name_binding(self.r.arenas); - self.innermost_rib_bindings(ValueNS).insert(ident, binding); + self.innermost_rib_bindings(ValueNS).insert(ident, res); } res } } - fn innermost_rib_bindings( - &mut self, - ns: Namespace, - ) -> &mut FxHashMap> { + fn innermost_rib_bindings(&mut self, ns: Namespace) -> &mut IdentMap { &mut self.ribs[ns].last_mut().unwrap().bindings } @@ -1788,17 +1760,22 @@ fn try_resolve_as_non_binding( // also be interpreted as a path to e.g. a constant, variant, etc. let is_syntactic_ambiguity = !has_sub && bm == BindingMode::ByValue(Mutability::Not); - let binding = self.resolve_ident_in_lexical_scope(ident, ValueNS, None, pat.span)?; - if is_syntactic_ambiguity && binding.is_ambiguity() { - // For ambiguous bindings we don't know all their definitions and cannot check - // whether they can be shadowed by fresh bindings or not, so force an error. - // issues/33118#issuecomment-233962221 (see below) still applies here, - // but we have to ignore it for backward compatibility. - self.r.record_use(ident, binding, false); - return None; - } + let ls_binding = self.resolve_ident_in_lexical_scope(ident, ValueNS, None, pat.span)?; + let (res, binding) = match ls_binding { + LexicalScopeBinding::Item(binding) + if is_syntactic_ambiguity && binding.is_ambiguity() => + { + // For ambiguous bindings we don't know all their definitions and cannot check + // whether they can be shadowed by fresh bindings or not, so force an error. + // issues/33118#issuecomment-233962221 (see below) still applies here, + // but we have to ignore it for backward compatibility. + self.r.record_use(ident, binding, false); + return None; + } + LexicalScopeBinding::Item(binding) => (binding.res(), Some(binding)), + LexicalScopeBinding::Res(res) => (res, None), + }; - let res = binding.res(); match res { Res::SelfCtor(_) // See #70549. | Res::Def( @@ -1806,7 +1783,9 @@ fn try_resolve_as_non_binding( _, ) if is_syntactic_ambiguity => { // Disambiguate in favor of a unit struct/variant or constant pattern. - self.r.record_use(ident, binding, false); + if let Some(binding) = binding { + self.r.record_use(ident, binding, false); + } Some(res) } Res::Def(DefKind::Ctor(..) | DefKind::Const | DefKind::Static, _) => { @@ -1815,6 +1794,7 @@ fn try_resolve_as_non_binding( // to something unusable as a pattern (e.g., constructor function), // but we still conservatively report an error, see // issues/33118#issuecomment-233962221 for one reason why. + let binding = binding.expect("no binding for a ctor or static"); self.report_error( ident.span, ResolutionError::BindingShadowsSomethingUnacceptable { @@ -2054,15 +2034,19 @@ fn smart_resolve_path_fragment( } fn self_type_is_available(&mut self, span: Span) -> bool { - let ident = Ident::with_dummy_span(kw::SelfUpper); - self.resolve_ident_in_lexical_scope(ident, TypeNS, None, span) - .map_or(false, |binding| binding.res() != Res::Err) + let binding = self.resolve_ident_in_lexical_scope( + Ident::with_dummy_span(kw::SelfUpper), + TypeNS, + None, + span, + ); + if let Some(LexicalScopeBinding::Res(res)) = binding { res != Res::Err } else { false } } fn self_value_is_available(&mut self, self_span: Span, path_span: Span) -> bool { let ident = Ident::new(kw::SelfLower, self_span); - self.resolve_ident_in_lexical_scope(ident, ValueNS, None, path_span) - .map_or(false, |binding| binding.res() != Res::Err) + let binding = self.resolve_ident_in_lexical_scope(ident, ValueNS, None, path_span); + if let Some(LexicalScopeBinding::Res(res)) = binding { res != Res::Err } else { false } } /// A wrapper around [`Resolver::report_error`].