From c1e8fc8c97831ac1d167e54c3d7b84305c697b87 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sat, 18 Sep 2021 23:41:41 +0300 Subject: [PATCH] resolve: Use `NameBinding` for local variables and generic parameters --- compiler/rustc_resolve/src/late.rs | 161 ++++++++------- .../rustc_resolve/src/late/diagnostics.rs | 3 +- compiler/rustc_resolve/src/lib.rs | 194 +++++------------- 3 files changed, 145 insertions(+), 213 deletions(-) diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 9563325796538..a52dbe4f54024 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, LexicalScopeBinding}; +use crate::{path_names_to_string, BindingError, CrateLint, NameBinding, ToNameBinding}; use crate::{Module, ModuleOrUniformRoot, ParentScope, PathResult}; use crate::{ResolutionError, Resolver, Segment, UseError}; @@ -21,27 +21,22 @@ use rustc_hir::def::Namespace::{self, *}; 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}; +use rustc_middle::{bug, span_bug, ty}; use rustc_session::lint; +use rustc_span::source_map::{respan, Spanned}; use rustc_span::symbol::{kw, sym, Ident, Symbol}; -use rustc_span::Span; +use rustc_span::{Span, DUMMY_SP}; 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, @@ -172,8 +167,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 = Res> { - pub bindings: IdentMap, +crate struct Rib<'a, R = &'a NameBinding<'a>> { + pub bindings: FxHashMap, pub kind: RibKind<'a>, } @@ -567,12 +562,12 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> { GenericParamKind::Type { .. } => { forward_ty_ban_rib .bindings - .insert(Ident::with_dummy_span(param.ident.name), Res::Err); + .insert(Ident::with_dummy_span(param.ident.name), self.r.dummy_binding); } GenericParamKind::Const { .. } => { forward_const_ban_rib .bindings - .insert(Ident::with_dummy_span(param.ident.name), Res::Err); + .insert(Ident::with_dummy_span(param.ident.name), self.r.dummy_binding); } GenericParamKind::Lifetime => {} } @@ -589,7 +584,9 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> { // 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), Res::Err); + forward_ty_ban_rib + .bindings + .insert(Ident::with_dummy_span(kw::SelfUpper), self.r.dummy_binding); } for param in &generics.params { @@ -737,15 +734,17 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { ns: Namespace, record_used_id: Option, path_span: Span, - ) -> Option> { - self.r.resolve_ident_in_lexical_scope( - ident, - ns, - &self.parent_scope, - record_used_id, - path_span, - &self.ribs[ns], - ) + ) -> 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() } fn resolve_path( @@ -903,6 +902,10 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { } 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; @@ -914,31 +917,42 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { 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" }; - if this.should_report_errs() { - this.r - .session - .span_err(ident.span, &format!("imports cannot refer to {}", what)); - } + let msg = format!("imports cannot refer to {what}"); + this.r.session.span_err(ident.span, &msg); }; for &ns in nss { - match self.resolve_ident_in_lexical_scope(ident, ns, None, use_tree.prefix.span) { - Some(LexicalScopeBinding::Res(..)) => { + 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); - } - Some(LexicalScopeBinding::Item(binding)) => { + } else { let orig_unusable_binding = replace(&mut self.r.unusable_binding, Some(binding)); - if let Some(LexicalScopeBinding::Res(..)) = self - .resolve_ident_in_lexical_scope(ident, ns, None, use_tree.prefix.span) - { - report_error(self, ns); + 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); + } } self.r.unusable_binding = orig_unusable_binding; } - None => {} } } } else if let UseTreeKind::Nested(use_trees) = &use_tree.kind { @@ -1135,8 +1149,12 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { _ => 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, res); + rib.bindings.insert(ident, binding); } self.ribs[ValueNS].push(function_value_rib); @@ -1256,10 +1274,12 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { } 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), self_res); + self_type_rib.bindings.insert(Ident::with_dummy_span(kw::SelfUpper), binding); self.ribs[ns].push(self_type_rib); f(self); self.ribs[ns].pop(); @@ -1470,7 +1490,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { /// 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) -> BindingMap { + fn binding_mode_map(&mut self, pat: &Pat) -> FxHashMap { let mut binding_map = FxHashMap::default(); pat.walk(&mut |pat| { @@ -1503,7 +1523,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { /// 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(); @@ -1645,7 +1665,6 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { .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( @@ -1735,18 +1754,24 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { if already_bound_or { // `Variant1(a) | Variant2(a)`, ok // Reuse definition from the first `a`. - self.innermost_rib_bindings(ValueNS)[&ident] + self.innermost_rib_bindings(ValueNS)[&ident].res() } else { let res = Res::Local(pat_id); if ident_valid { // A completely fresh binding add to the set if it's valid. - self.innermost_rib_bindings(ValueNS).insert(ident, res); + 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); } res } } - fn innermost_rib_bindings(&mut self, ns: Namespace) -> &mut IdentMap { + fn innermost_rib_bindings( + &mut self, + ns: Namespace, + ) -> &mut FxHashMap> { &mut self.ribs[ns].last_mut().unwrap().bindings } @@ -1763,22 +1788,17 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { // 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 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 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 res = binding.res(); match res { Res::SelfCtor(_) // See #70549. | Res::Def( @@ -1786,9 +1806,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { _, ) if is_syntactic_ambiguity => { // Disambiguate in favor of a unit struct/variant or constant pattern. - if let Some(binding) = binding { - self.r.record_use(ident, binding, false); - } + self.r.record_use(ident, binding, false); Some(res) } Res::Def(DefKind::Ctor(..) | DefKind::Const | DefKind::Static, _) => { @@ -1797,7 +1815,6 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { // 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 { @@ -2037,19 +2054,15 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { } fn self_type_is_available(&mut self, span: Span) -> bool { - 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 } + 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) } fn self_value_is_available(&mut self, self_span: Span, path_span: Span) -> bool { let ident = Ident::new(kw::SelfLower, self_span); - 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 } + self.resolve_ident_in_lexical_scope(ident, ValueNS, None, path_span) + .map_or(false, |binding| binding.res() != Res::Err) } /// A wrapper around [`Resolver::report_error`]. diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 1748a9be8e13e..506f154975383 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -1294,7 +1294,8 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { // Walk backwards up the ribs in scope and collect candidates. for rib in self.ribs[ns].iter().rev() { // Locals and type parameters - for (ident, &res) in &rib.bindings { + for (ident, binding) in &rib.bindings { + let res = binding.res(); if filter_fn(res) { names.push(TypoSuggestion::typo_from_res(ident.name, res)); } diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 9652c483686f0..0c69a666a7ed4 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -371,26 +371,6 @@ impl<'tcx> Visitor<'tcx> for UsePlacementFinder { } } -/// An intermediate resolution result. -/// -/// This refers to the thing referred by a name. The difference between `Res` and `Item` is that -/// items are visible in their whole block, while `Res`es only from the place they are defined -/// forward. -#[derive(Debug)] -enum LexicalScopeBinding<'a> { - Item(&'a NameBinding<'a>), - Res(Res), -} - -impl<'a> LexicalScopeBinding<'a> { - fn res(self) -> Res { - match self { - LexicalScopeBinding::Item(binding) => binding.res(), - LexicalScopeBinding::Res(res) => res, - } - } -} - #[derive(Copy, Clone, Debug)] enum ModuleOrUniformRoot<'a> { /// Regular module. @@ -916,10 +896,6 @@ pub struct Resolver<'a> { /// "self-confirming" import resolutions during import validation. unusable_binding: Option<&'a NameBinding<'a>>, - // Spans for local variables found during pattern resolution. - // Used for suggestions during error reporting. - pat_span_map: NodeMap, - /// Resolutions for nodes that have a single resolution. partial_res_map: NodeMap, /// Resolutions for import nodes, which have multiple resolutions in different namespaces. @@ -1357,7 +1333,6 @@ impl<'a> Resolver<'a> { last_import_segment: false, unusable_binding: None, - pat_span_map: Default::default(), partial_res_map: Default::default(), import_res_map: Default::default(), label_res_map: Default::default(), @@ -1383,13 +1358,8 @@ impl<'a> Resolver<'a> { macro_expanded_macro_export_errors: BTreeSet::new(), arenas, - dummy_binding: arenas.alloc_name_binding(NameBinding { - kind: NameBindingKind::Res(Res::Err, false), - ambiguity: None, - expansion: LocalExpnId::ROOT, - span: DUMMY_SP, - vis: ty::Visibility::Public, - }), + dummy_binding: (Res::Err, ty::Visibility::Public, DUMMY_SP, LocalExpnId::ROOT) + .to_name_binding(arenas), crate_loader: CrateLoader::new(session, metadata_loader, crate_name), macro_names: FxHashSet::default(), @@ -1953,11 +1923,11 @@ impl<'a> Resolver<'a> { record_used_id: Option, path_span: Span, ribs: &[Rib<'a>], - ) -> Option> { + ) -> Result<&'a NameBinding<'a>, Determinacy> { assert!(ns == TypeNS || ns == ValueNS); let orig_ident = ident; if ident.name == kw::Empty { - return Some(LexicalScopeBinding::Res(Res::Err)); + return Ok(self.dummy_binding); } let (general_span, normalized_span) = if ident.name == kw::SelfUpper { // FIXME(jseyfried) improve `Self` hygiene @@ -1980,18 +1950,30 @@ impl<'a> Resolver<'a> { // Use the rib kind to determine whether we are resolving parameters // (macro 2.0 hygiene) or local variables (`macro_rules` hygiene). let rib_ident = if ribs[i].kind.contains_params() { normalized_ident } else { ident }; - if let Some((original_rib_ident_def, res)) = ribs[i].bindings.get_key_value(&rib_ident) + if let Some((&original_rib_ident_def, &binding)) = + ribs[i].bindings.get_key_value(&rib_ident) { // The ident resolves to a type parameter or local variable. - return Some(LexicalScopeBinding::Res(self.validate_res_from_ribs( + let res = self.validate_res_from_ribs( i, rib_ident, - *res, + binding.res(), record_used, path_span, - *original_rib_ident_def, + original_rib_ident_def, ribs, - ))); + ); + + // We have to create a new binding in case of validation errors, + // or in case of const generic hack changing the resolution. + return Ok(if res != binding.res() { + self.arenas.alloc_name_binding(NameBinding { + kind: NameBindingKind::Res(res, false), + ..binding.clone() + }) + } else { + binding + }); } module = match ribs[i].kind { @@ -2010,7 +1992,7 @@ impl<'a> Resolver<'a> { _ => break, } - let item = self.resolve_ident_in_module_unadjusted( + let binding = self.resolve_ident_in_module_unadjusted( ModuleOrUniformRoot::Module(module), ident, ns, @@ -2018,9 +2000,9 @@ impl<'a> Resolver<'a> { record_used, path_span, ); - if let Ok(binding) = item { + if binding.is_ok() { // The ident resolves to an item. - return Some(LexicalScopeBinding::Item(binding)); + return binding; } } self.early_resolve_ident_in_lexical_scope( @@ -2031,8 +2013,6 @@ impl<'a> Resolver<'a> { record_used, path_span, ) - .ok() - .map(LexicalScopeBinding::Item) } fn hygienic_lexical_parent( @@ -2257,16 +2237,6 @@ impl<'a> Resolver<'a> { for (i, &Segment { ident, id, has_generic_args: _ }) in path.iter().enumerate() { debug!("resolve_path ident {} {:?} {:?}", i, ident, id); - let record_segment_res = |this: &mut Self, res| { - if record_used { - if let Some(id) = id { - if !this.partial_res_map.contains_key(&id) { - assert!(id != ast::DUMMY_NODE_ID, "Trying to resolve dummy id"); - this.record_partial_res(id, PartialRes::new(res)); - } - } - } - }; let is_last = i == path.len() - 1; let ns = if is_last { opt_ns.unwrap_or(TypeNS) } else { TypeNS }; @@ -2345,12 +2315,8 @@ impl<'a> Resolver<'a> { }; } - enum FindBindingResult<'a> { - Binding(Result<&'a NameBinding<'a>, Determinacy>), - PathResult(PathResult<'a>), - } let find_binding_in_ns = |this: &mut Self, ns| { - let binding = if let Some(module) = module { + if let Some(module) = module { this.resolve_ident_in_module( module, ident, @@ -2375,44 +2341,34 @@ impl<'a> Resolver<'a> { } else { None }; - match this.resolve_ident_in_lexical_scope( + this.resolve_ident_in_lexical_scope( ident, ns, parent_scope, record_used_id, path_span, &ribs.unwrap()[ns], - ) { - // we found a locally-imported or available item/module - Some(LexicalScopeBinding::Item(binding)) => Ok(binding), - // we found a local variable or type param - Some(LexicalScopeBinding::Res(res)) - if opt_ns == Some(TypeNS) || opt_ns == Some(ValueNS) => - { - record_segment_res(this, res); - return FindBindingResult::PathResult(PathResult::NonModule( - PartialRes::with_unresolved_segments(res, path.len() - 1), - )); - } - _ => Err(Determinacy::determined(record_used)), - } - }; - FindBindingResult::Binding(binding) - }; - let binding = match find_binding_in_ns(self, ns) { - FindBindingResult::PathResult(x) => return x, - FindBindingResult::Binding(binding) => binding, + ) + } }; - match binding { + + match find_binding_in_ns(self, ns) { Ok(binding) => { if i == 1 { second_binding = Some(binding); } let res = binding.res(); + if record_used { + if let Some(id) = id { + if !self.partial_res_map.contains_key(&id) { + assert!(id != ast::DUMMY_NODE_ID, "Trying to resolve dummy id"); + self.record_partial_res(id, PartialRes::new(res)); + } + } + } let maybe_assoc = opt_ns != Some(MacroNS) && PathSource::Type.is_expected(res); if let Some(next_module) = binding.module() { module = Some(ModuleOrUniformRoot::Module(next_module)); - record_segment_res(self, res); } else if res == Res::ToolMod && i + 1 != path.len() { if binding.is_import() { self.session @@ -2502,56 +2458,25 @@ impl<'a> Resolver<'a> { .map_or(false, |c| c.is_ascii_uppercase()) { // Check whether the name refers to an item in the value namespace. - let suggestion = if ribs.is_some() { - let match_span = match self.resolve_ident_in_lexical_scope( - ident, - ValueNS, - parent_scope, - None, - path_span, - &ribs.unwrap()[ValueNS], - ) { - // Name matches a local variable. For example: - // ``` - // fn f() { - // let Foo: &str = ""; - // println!("{}", Foo::Bar); // Name refers to local - // // variable `Foo`. - // } - // ``` - Some(LexicalScopeBinding::Res(Res::Local(id))) => { - Some(*self.pat_span_map.get(&id).unwrap()) - } - - // Name matches item from a local name binding - // created by `use` declaration. For example: - // ``` - // pub Foo: &str = ""; - // - // mod submod { - // use super::Foo; - // println!("{}", Foo::Bar); // Name refers to local - // // binding `Foo`. - // } - // ``` - Some(LexicalScopeBinding::Item(name_binding)) => { - Some(name_binding.span) - } - _ => None, - }; - - if let Some(span) = match_span { - Some(( - vec![(span, String::from(""))], + let suggestion = ribs + .and_then(|ribs| { + self.resolve_ident_in_lexical_scope( + ident, + ValueNS, + parent_scope, + None, + path_span, + &ribs[ValueNS], + ) + .ok() + }) + .map(|binding| { + ( + vec![(binding.span, String::from(""))], format!("`{}` is defined here, but is not a type", ident), Applicability::MaybeIncorrect, - )) - } else { - None - } - } else { - None - }; + ) + }); (format!("use of undeclared type `{}`", ident), suggestion) } else { @@ -2589,9 +2514,7 @@ impl<'a> Resolver<'a> { let mut msg = format!("could not find `{}` in {}", ident, parent); if ns == TypeNS || ns == ValueNS { let ns_to_try = if ns == TypeNS { ValueNS } else { TypeNS }; - if let FindBindingResult::Binding(Ok(binding)) = - find_binding_in_ns(self, ns_to_try) - { + if let Ok(binding) = find_binding_in_ns(self, ns_to_try) { let mut found = |what| { msg = format!( "expected {}, found {} `{}` in {}", @@ -2933,11 +2856,6 @@ impl<'a> Resolver<'a> { } } - fn record_pat_span(&mut self, node: NodeId, span: Span) { - debug!("(recording pat) recording {:?} for {:?}", node, span); - self.pat_span_map.insert(node, span); - } - fn is_accessible_from(&self, vis: ty::Visibility, module: Module<'a>) -> bool { vis.is_accessible_from(module.nearest_parent_mod(), self) }