From b25c063caa5e4ab8202527e3cfcfe04196e0836f Mon Sep 17 00:00:00 2001 From: Jeffrey Seyfried Date: Thu, 10 Nov 2016 06:19:54 +0000 Subject: [PATCH] Refactor out `PerNS`. --- src/librustc_resolve/build_reduced_graph.rs | 15 +- src/librustc_resolve/check_unused.rs | 6 +- src/librustc_resolve/lib.rs | 144 +++++++------ src/librustc_resolve/resolve_imports.rs | 195 ++++++++---------- .../blind-item-block-item-shadow.rs | 2 +- src/test/compile-fail/double-type-import.rs | 2 +- 6 files changed, 186 insertions(+), 178 deletions(-) diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index bfbc5b3163a..5917a1a0d17 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -15,7 +15,7 @@ use macros::{InvocationData, LegacyScope}; use resolve_imports::ImportDirective; -use resolve_imports::ImportDirectiveSubclass::{self, GlobImport}; +use resolve_imports::ImportDirectiveSubclass::{self, GlobImport, SingleImport}; use {Resolver, Module, ModuleS, ModuleKind, NameBinding, NameBindingKind, ToNameBinding}; use Namespace::{self, TypeNS, ValueNS, MacroNS}; use ResolveResult::Success; @@ -37,6 +37,7 @@ use syntax::ast::{Mutability, StmtKind, TraitItem, TraitItemKind}; use syntax::ast::{Variant, ViewPathGlob, ViewPathList, ViewPathSimple}; use syntax::ext::base::SyntaxExtension; +use syntax::ext::base::Determinacy::Undetermined; use syntax::ext::expand::mark_tts; use syntax::ext::hygiene::Mark; use syntax::ext::tt::macro_rules; @@ -157,7 +158,11 @@ fn build_reduced_graph_for_item(&mut self, item: &Item, expansion: Mark) { .emit(); } - let subclass = ImportDirectiveSubclass::single(binding.name, source.name); + let subclass = SingleImport { + target: binding.name, + source: source.name, + result: self.per_ns(|_, _| Cell::new(Err(Undetermined))), + }; self.add_import_directive( module_path, subclass, view_path.span, item.id, vis, expansion, ); @@ -206,7 +211,11 @@ fn build_reduced_graph_for_item(&mut self, item: &Item, expansion: Mark) { (module_path.to_vec(), name, rename) } }; - let subclass = ImportDirectiveSubclass::single(rename, name); + let subclass = SingleImport { + target: rename, + source: name, + result: self.per_ns(|_, _| Cell::new(Err(Undetermined))), + }; let id = source_item.node.id; self.add_import_directive( module_path, subclass, source_item.span, id, vis, expansion, diff --git a/src/librustc_resolve/check_unused.rs b/src/librustc_resolve/check_unused.rs index 36e05a43341..492c5e695bb 100644 --- a/src/librustc_resolve/check_unused.rs +++ b/src/librustc_resolve/check_unused.rs @@ -22,7 +22,6 @@ use std::ops::{Deref, DerefMut}; use Resolver; -use Namespace::{TypeNS, ValueNS}; use rustc::lint; use rustc::util::nodemap::NodeMap; @@ -56,8 +55,9 @@ impl<'a, 'b> UnusedImportCheckVisitor<'a, 'b> { // We have information about whether `use` (import) directives are actually // used now. If an import is not used at all, we signal a lint error. fn check_import(&mut self, item_id: ast::NodeId, id: ast::NodeId, span: Span) { - if !self.used_imports.contains(&(id, TypeNS)) && - !self.used_imports.contains(&(id, ValueNS)) { + let mut used = false; + self.per_ns(|this, ns| used |= this.used_imports.contains(&(id, ns))); + if !used { if self.maybe_unused_trait_imports.contains(&id) { // Check later. return; diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 4164f3a897d..af729770242 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -536,6 +536,33 @@ pub enum Namespace { MacroNS, } +#[derive(Clone, Default, Debug)] +pub struct PerNS { + value_ns: T, + type_ns: T, +} + +impl ::std::ops::Index for PerNS { + type Output = T; + fn index(&self, ns: Namespace) -> &T { + match ns { + ValueNS => &self.value_ns, + TypeNS => &self.type_ns, + MacroNS => unreachable!(), + } + } +} + +impl ::std::ops::IndexMut for PerNS { + fn index_mut(&mut self, ns: Namespace) -> &mut T { + match ns { + ValueNS => &mut self.value_ns, + TypeNS => &mut self.type_ns, + MacroNS => unreachable!(), + } + } +} + impl<'a> Visitor for Resolver<'a> { fn visit_item(&mut self, item: &Item) { self.resolve_item(item); @@ -612,7 +639,7 @@ fn visit_fn(&mut self, }; // Create a value rib for the function. - self.value_ribs.push(Rib::new(rib_kind)); + self.ribs[ValueNS].push(Rib::new(rib_kind)); // Create a label rib for the function. self.label_ribs.push(Rib::new(rib_kind)); @@ -642,7 +669,7 @@ fn visit_fn(&mut self, debug!("(resolving function) leaving function"); self.label_ribs.pop(); - self.value_ribs.pop(); + self.ribs[ValueNS].pop(); } } @@ -1049,12 +1076,9 @@ pub struct Resolver<'a> { // The module that represents the current item scope. current_module: Module<'a>, - // The current set of local scopes, for values. + // The current set of local scopes for types and values. // FIXME #4948: Reuse ribs to avoid allocation. - value_ribs: Vec>, - - // The current set of local scopes, for types. - type_ribs: Vec>, + ribs: PerNS>>, // The current set of local scopes, for labels. label_ribs: Vec>, @@ -1273,8 +1297,10 @@ pub fn new(session: &'a Session, indeterminate_imports: Vec::new(), current_module: graph_root, - value_ribs: vec![Rib::new(ModuleRibKind(graph_root))], - type_ribs: vec![Rib::new(ModuleRibKind(graph_root))], + ribs: PerNS { + value_ns: vec![Rib::new(ModuleRibKind(graph_root))], + type_ns: vec![Rib::new(ModuleRibKind(graph_root))], + }, label_ribs: Vec::new(), current_trait_ref: None, @@ -1335,6 +1361,13 @@ pub fn arenas() -> ResolverArenas<'a> { } } + fn per_ns T>(&mut self, mut f: F) -> PerNS { + PerNS { + type_ns: f(self, TypeNS), + value_ns: f(self, ValueNS), + } + } + /// Entry point to crate resolution. pub fn resolve_crate(&mut self, krate: &Crate) { ImportResolver { resolver: self }.finalize_imports(); @@ -1354,14 +1387,6 @@ fn new_module(&self, parent: Module<'a>, kind: ModuleKind, local: bool) -> Modul }) } - fn get_ribs<'b>(&'b mut self, ns: Namespace) -> &'b mut Vec> { - match ns { - ValueNS => &mut self.value_ribs, - TypeNS => &mut self.type_ribs, - MacroNS => panic!("The macro namespace has no ribs"), - } - } - fn record_use(&mut self, name: Name, ns: Namespace, binding: &'a NameBinding<'a>, span: Span) -> bool /* true if an error was reported */ { // track extern crates for unused_extern_crate lint @@ -1577,8 +1602,8 @@ fn resolve_ident_in_lexical_scope(&mut self, } // Walk backwards up the ribs in scope. - for i in (0 .. self.get_ribs(ns).len()).rev() { - if let Some(def) = self.get_ribs(ns)[i].bindings.get(&ident).cloned() { + for i in (0 .. self.ribs[ns].len()).rev() { + if let Some(def) = self.ribs[ns][i].bindings.get(&ident).cloned() { // The ident resolves to a type parameter or local variable. return Some(LexicalScopeBinding::LocalDef(LocalDef { ribs: Some((ns, i)), @@ -1586,7 +1611,7 @@ fn resolve_ident_in_lexical_scope(&mut self, })); } - if let ModuleRibKind(module) = self.get_ribs(ns)[i].kind { + if let ModuleRibKind(module) = self.ribs[ns][i].kind { let name = ident.name; let item = self.resolve_name_in_module(module, name, ns, true, record_used); if let Success(binding) = item { @@ -1604,7 +1629,7 @@ fn resolve_ident_in_lexical_scope(&mut self, } } - if let MacroDefinition(mac) = self.get_ribs(ns)[i].kind { + if let MacroDefinition(mac) = self.ribs[ns][i].kind { // If an invocation of this macro created `ident`, give up on `ident` // and switch to `ident`'s source from the macro definition. let (source_ctxt, source_macro) = ident.ctxt.source(); @@ -1689,14 +1714,14 @@ fn with_scope(&mut self, id: NodeId, f: F) if let Some(module) = module { // Move down in the graph. let orig_module = replace(&mut self.current_module, module); - self.value_ribs.push(Rib::new(ModuleRibKind(module))); - self.type_ribs.push(Rib::new(ModuleRibKind(module))); + self.ribs[ValueNS].push(Rib::new(ModuleRibKind(module))); + self.ribs[TypeNS].push(Rib::new(ModuleRibKind(module))); f(self); self.current_module = orig_module; - self.value_ribs.pop(); - self.type_ribs.pop(); + self.ribs[ValueNS].pop(); + self.ribs[TypeNS].pop(); } else { f(self); } @@ -1871,7 +1896,7 @@ fn with_type_parameter_rib<'b, F>(&'b mut self, type_parameters: TypeParameters< function_type_rib.bindings.insert(Ident::with_empty_ctxt(name), def); self.record_def(type_parameter.id, PathResolution::new(def)); } - self.type_ribs.push(function_type_rib); + self.ribs[TypeNS].push(function_type_rib); } NoTypeParameters => { @@ -1882,7 +1907,7 @@ fn with_type_parameter_rib<'b, F>(&'b mut self, type_parameters: TypeParameters< f(self); if let HasTypeParameters(..) = type_parameters { - self.type_ribs.pop(); + self.ribs[TypeNS].pop(); } } @@ -1897,11 +1922,11 @@ fn with_label_rib(&mut self, f: F) fn with_constant_rib(&mut self, f: F) where F: FnOnce(&mut Resolver) { - self.value_ribs.push(Rib::new(ConstantItemRibKind)); - self.type_ribs.push(Rib::new(ConstantItemRibKind)); + self.ribs[ValueNS].push(Rib::new(ConstantItemRibKind)); + self.ribs[TypeNS].push(Rib::new(ConstantItemRibKind)); f(self); - self.type_ribs.pop(); - self.value_ribs.pop(); + self.ribs[TypeNS].pop(); + self.ribs[ValueNS].pop(); } fn resolve_trait_reference(&mut self, @@ -2011,9 +2036,9 @@ fn with_self_rib(&mut self, self_def: Def, f: F) // plain insert (no renaming, types are not currently hygienic....) self_type_rib.bindings.insert(keywords::SelfType.ident(), self_def); - self.type_ribs.push(self_type_rib); + self.ribs[TypeNS].push(self_type_rib); f(self); - self.type_ribs.pop(); + self.ribs[TypeNS].pop(); } fn resolve_implementation(&mut self, @@ -2167,7 +2192,7 @@ fn check_consistent_bindings(&mut self, arm: &Arm) { } fn resolve_arm(&mut self, arm: &Arm) { - self.value_ribs.push(Rib::new(NormalRibKind)); + self.ribs[ValueNS].push(Rib::new(NormalRibKind)); let mut bindings_list = FxHashMap(); for pattern in &arm.pats { @@ -2181,7 +2206,7 @@ fn resolve_arm(&mut self, arm: &Arm) { walk_list!(self, visit_expr, &arm.guard); self.visit_expr(&arm.body); - self.value_ribs.pop(); + self.ribs[ValueNS].pop(); } fn resolve_block(&mut self, block: &Block) { @@ -2193,11 +2218,11 @@ fn resolve_block(&mut self, block: &Block) { let mut num_macro_definition_ribs = 0; if let Some(anonymous_module) = anonymous_module { debug!("(resolving block) found anonymous module, moving down"); - self.value_ribs.push(Rib::new(ModuleRibKind(anonymous_module))); - self.type_ribs.push(Rib::new(ModuleRibKind(anonymous_module))); + self.ribs[ValueNS].push(Rib::new(ModuleRibKind(anonymous_module))); + self.ribs[TypeNS].push(Rib::new(ModuleRibKind(anonymous_module))); self.current_module = anonymous_module; } else { - self.value_ribs.push(Rib::new(NormalRibKind)); + self.ribs[ValueNS].push(Rib::new(NormalRibKind)); } // Descend into the block. @@ -2205,7 +2230,7 @@ fn resolve_block(&mut self, block: &Block) { if let Some(marks) = self.macros_at_scope.remove(&stmt.id) { num_macro_definition_ribs += marks.len() as u32; for mark in marks { - self.value_ribs.push(Rib::new(MacroDefinition(mark))); + self.ribs[ValueNS].push(Rib::new(MacroDefinition(mark))); self.label_ribs.push(Rib::new(MacroDefinition(mark))); } } @@ -2216,12 +2241,12 @@ fn resolve_block(&mut self, block: &Block) { // Move back up. self.current_module = orig_module; for _ in 0 .. num_macro_definition_ribs { - self.value_ribs.pop(); + self.ribs[ValueNS].pop(); self.label_ribs.pop(); } - self.value_ribs.pop(); + self.ribs[ValueNS].pop(); if let Some(_) = anonymous_module { - self.type_ribs.pop(); + self.ribs[TypeNS].pop(); } debug!("(resolving block) leaving block"); } @@ -2340,7 +2365,7 @@ fn fresh_binding(&mut self, Some(..) if pat_src == PatternSource::Match => { // `Variant1(a) | Variant2(a)`, ok // Reuse definition from the first `a`. - def = self.value_ribs.last_mut().unwrap().bindings[&ident.node]; + def = self.ribs[ValueNS].last_mut().unwrap().bindings[&ident.node]; } Some(..) => { span_bug!(ident.span, "two bindings with the same name from \ @@ -2350,7 +2375,7 @@ fn fresh_binding(&mut self, // A completely fresh binding, add to the lists if it's valid. if ident.node.name != keywords::Invalid.name() { bindings.insert(ident.node, outer_pat_id); - self.value_ribs.last_mut().unwrap().bindings.insert(ident.node, def); + self.ribs[ValueNS].last_mut().unwrap().bindings.insert(ident.node, def); } } } @@ -2634,9 +2659,8 @@ fn resolve_identifier(&mut self, // Resolve a local definition, potentially adjusting for closures. fn adjust_local_def(&mut self, local_def: LocalDef, span: Span) -> Option { let ribs = match local_def.ribs { - Some((TypeNS, i)) => &self.type_ribs[i + 1..], - Some((ValueNS, i)) => &self.value_ribs[i + 1..], - _ => &[] as &[_], + Some((ns, i)) => &self.ribs[ns][i + 1..], + None => &[] as &[_], }; let mut def = local_def.def; match def { @@ -2798,8 +2822,8 @@ pub fn with_module_lexical_scope(&mut self, module: Module<'a>, f: F) -> T where F: FnOnce(&mut Resolver<'a>) -> T, { self.with_empty_ribs(|this| { - this.value_ribs.push(Rib::new(ModuleRibKind(module))); - this.type_ribs.push(Rib::new(ModuleRibKind(module))); + this.ribs[ValueNS].push(Rib::new(ModuleRibKind(module))); + this.ribs[TypeNS].push(Rib::new(ModuleRibKind(module))); f(this) }) } @@ -2807,13 +2831,11 @@ pub fn with_module_lexical_scope(&mut self, module: Module<'a>, f: F) -> T fn with_empty_ribs(&mut self, f: F) -> T where F: FnOnce(&mut Resolver<'a>) -> T, { - let value_ribs = replace(&mut self.value_ribs, Vec::new()); - let type_ribs = replace(&mut self.type_ribs, Vec::new()); + let ribs = replace(&mut self.ribs, PerNS::>::default()); let label_ribs = replace(&mut self.label_ribs, Vec::new()); let result = f(self); - self.value_ribs = value_ribs; - self.type_ribs = type_ribs; + self.ribs = ribs; self.label_ribs = label_ribs; result } @@ -2865,7 +2887,7 @@ fn find_best_match(&mut self, name: &str) -> SuggestionType { return SuggestionType::Macro(format!("{}!", macro_name)); } - let names = self.value_ribs + let names = self.ribs[ValueNS] .iter() .rev() .flat_map(|rib| rib.bindings.keys().map(|ident| &ident.name)); @@ -2968,7 +2990,7 @@ fn resolve_expr(&mut self, expr: &Expr, parent: Option<&Expr>) { } else { let mut method_scope = false; let mut is_static = false; - self.value_ribs.iter().rev().all(|rib| { + self.ribs[ValueNS].iter().rev().all(|rib| { method_scope = match rib.kind { MethodRibKind(is_static_) => { is_static = is_static_; @@ -3079,10 +3101,10 @@ fn resolve_expr(&mut self, expr: &Expr, parent: Option<&Expr>) { ExprKind::IfLet(ref pattern, ref subexpression, ref if_block, ref optional_else) => { self.visit_expr(subexpression); - self.value_ribs.push(Rib::new(NormalRibKind)); + self.ribs[ValueNS].push(Rib::new(NormalRibKind)); self.resolve_pattern(pattern, PatternSource::IfLet, &mut FxHashMap()); self.visit_block(if_block); - self.value_ribs.pop(); + self.ribs[ValueNS].pop(); optional_else.as_ref().map(|expr| self.visit_expr(expr)); } @@ -3096,22 +3118,22 @@ fn resolve_expr(&mut self, expr: &Expr, parent: Option<&Expr>) { ExprKind::WhileLet(ref pattern, ref subexpression, ref block, label) => { self.visit_expr(subexpression); - self.value_ribs.push(Rib::new(NormalRibKind)); + self.ribs[ValueNS].push(Rib::new(NormalRibKind)); self.resolve_pattern(pattern, PatternSource::WhileLet, &mut FxHashMap()); self.resolve_labeled_block(label, expr.id, block); - self.value_ribs.pop(); + self.ribs[ValueNS].pop(); } ExprKind::ForLoop(ref pattern, ref subexpression, ref block, label) => { self.visit_expr(subexpression); - self.value_ribs.push(Rib::new(NormalRibKind)); + self.ribs[ValueNS].push(Rib::new(NormalRibKind)); self.resolve_pattern(pattern, PatternSource::For, &mut FxHashMap()); self.resolve_labeled_block(label, expr.id, block); - self.value_ribs.pop(); + self.ribs[ValueNS].pop(); } ExprKind::Field(ref subexpression, _) => { diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index 01d09a3b7c4..f04f3bf45ee 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -10,8 +10,8 @@ use self::ImportDirectiveSubclass::*; -use Module; -use Namespace::{self, TypeNS, ValueNS}; +use {Module, PerNS}; +use Namespace::{self, TypeNS}; use {NameBinding, NameBindingKind, PrivacyError, ToNameBinding}; use ResolveResult; use ResolveResult::*; @@ -39,8 +39,7 @@ pub enum ImportDirectiveSubclass<'a> { SingleImport { target: Name, source: Name, - value_result: Cell, Determinacy>>, - type_result: Cell, Determinacy>>, + result: PerNS, Determinacy>>>, }, GlobImport { is_prelude: bool, @@ -50,17 +49,6 @@ pub enum ImportDirectiveSubclass<'a> { ExternCrate, } -impl<'a> ImportDirectiveSubclass<'a> { - pub fn single(target: Name, source: Name) -> Self { - SingleImport { - target: target, - source: source, - type_result: Cell::new(Err(Undetermined)), - value_result: Cell::new(Err(Undetermined)), - } - } -} - /// One import directive. #[derive(Debug,Clone)] pub struct ImportDirective<'a> { @@ -276,10 +264,10 @@ pub fn add_import_directive(&mut self, self.indeterminate_imports.push(directive); match directive.subclass { SingleImport { target, .. } => { - for &ns in &[ValueNS, TypeNS] { - let mut resolution = self.resolution(current_module, target, ns).borrow_mut(); + self.per_ns(|this, ns| { + let mut resolution = this.resolution(current_module, target, ns).borrow_mut(); resolution.single_imports.add_directive(directive); - } + }); } // We don't add prelude imports to the globs since they only affect lexical scopes, // which are not relevant to import resolution. @@ -397,6 +385,18 @@ fn update_resolution(&mut self, module: Module<'a>, name: Name, ns: Namesp t } + + // Define a "dummy" resolution containing a Def::Err as a placeholder for a + // failed resolution + fn import_dummy_binding(&mut self, directive: &'a ImportDirective<'a>) { + if let SingleImport { target, .. } = directive.subclass { + let dummy_binding = self.dummy_binding; + let dummy_binding = self.import(dummy_binding, directive); + self.per_ns(|this, ns| { + let _ = this.try_define(directive.parent, target, ns, dummy_binding.clone()); + }); + } + } } pub struct ImportResolver<'a, 'b: 'a> { @@ -481,17 +481,6 @@ pub fn finalize_imports(&mut self) { } } - // Define a "dummy" resolution containing a Def::Err as a placeholder for a - // failed resolution - fn import_dummy_binding(&mut self, directive: &'b ImportDirective<'b>) { - if let SingleImport { target, .. } = directive.subclass { - let dummy_binding = self.dummy_binding; - let dummy_binding = self.import(dummy_binding, directive); - let _ = self.try_define(directive.parent, target, ValueNS, dummy_binding.clone()); - let _ = self.try_define(directive.parent, target, TypeNS, dummy_binding); - } - } - /// Attempts to resolve the given import. The return value indicates /// failure if we're certain the name does not exist, indeterminate if we /// don't know whether the name exists at the moment due to other @@ -523,9 +512,8 @@ fn resolve_import(&mut self, directive: &'b ImportDirective<'b>) -> ResolveResul }; directive.imported_module.set(Some(module)); - let (source, target, value_result, type_result) = match directive.subclass { - SingleImport { source, target, ref value_result, ref type_result } => - (source, target, value_result, type_result), + let (source, target, result) = match directive.subclass { + SingleImport { source, target, ref result } => (source, target, result), GlobImport { .. } => { self.resolve_glob_import(directive); return Success(()); @@ -534,46 +522,45 @@ fn resolve_import(&mut self, directive: &'b ImportDirective<'b>) -> ResolveResul }; let mut indeterminate = false; - for &(ns, result) in &[(ValueNS, value_result), (TypeNS, type_result)] { - if let Err(Undetermined) = result.get() { - result.set({ - match self.resolve_name_in_module(module, source, ns, false, None) { + self.per_ns(|this, ns| { + if let Err(Undetermined) = result[ns].get() { + result[ns].set({ + match this.resolve_name_in_module(module, source, ns, false, None) { Success(binding) => Ok(binding), Indeterminate => Err(Undetermined), Failed(_) => Err(Determined), } }); } else { - continue + return }; - match result.get() { + match result[ns].get() { Err(Undetermined) => indeterminate = true, Err(Determined) => { - self.update_resolution(directive.parent, target, ns, |_, resolution| { + this.update_resolution(directive.parent, target, ns, |_, resolution| { resolution.single_imports.directive_failed() }); } Ok(binding) if !binding.is_importable() => { let msg = format!("`{}` is not directly importable", target); - struct_span_err!(self.session, directive.span, E0253, "{}", &msg) + struct_span_err!(this.session, directive.span, E0253, "{}", &msg) .span_label(directive.span, &format!("cannot be imported directly")) .emit(); // Do not import this illegal binding. Import a dummy binding and pretend // everything is fine - self.import_dummy_binding(directive); - return Success(()); + this.import_dummy_binding(directive); } Ok(binding) => { - let imported_binding = self.import(binding, directive); - let conflict = self.try_define(directive.parent, target, ns, imported_binding); + let imported_binding = this.import(binding, directive); + let conflict = this.try_define(directive.parent, target, ns, imported_binding); if let Err(old_binding) = conflict { - let binding = &self.import(binding, directive); - self.report_conflict(directive.parent, target, ns, binding, old_binding); + let binding = &this.import(binding, directive); + this.report_conflict(directive.parent, target, ns, binding, old_binding); } } } - } + }); if indeterminate { Indeterminate } else { Success(()) } } @@ -601,9 +588,8 @@ fn finalize_import(&mut self, directive: &'b ImportDirective<'b>) -> ResolveResu }, }; - let (name, value_result, type_result) = match directive.subclass { - SingleImport { source, ref value_result, ref type_result, .. } => - (source, value_result.get(), type_result.get()), + let (name, result) = match directive.subclass { + SingleImport { source, ref result, .. } => (source, result), GlobImport { .. } if module.def_id() == directive.parent.def_id() => { // Importing a module into itself is not allowed. let msg = "Cannot glob-import a module into itself.".into(); @@ -621,21 +607,27 @@ fn finalize_import(&mut self, directive: &'b ImportDirective<'b>) -> ResolveResu _ => unreachable!(), }; - for &(ns, result) in &[(ValueNS, value_result), (TypeNS, type_result)] { - if let Ok(binding) = result { - if self.record_use(name, ns, binding, directive.span) { - self.resolution(module, name, ns).borrow_mut().binding = - Some(self.dummy_binding); + let mut all_ns_err = true; + self.per_ns(|this, ns| { + if let Ok(binding) = result[ns].get() { + all_ns_err = false; + if this.record_use(name, ns, binding, directive.span) { + this.resolution(module, name, ns).borrow_mut().binding = + Some(this.dummy_binding); } } - } + }); - if value_result.is_err() && type_result.is_err() { - let (value_result, type_result); - value_result = self.resolve_name_in_module(module, name, ValueNS, false, Some(span)); - type_result = self.resolve_name_in_module(module, name, TypeNS, false, Some(span)); + if all_ns_err { + let mut all_ns_failed = true; + self.per_ns(|this, ns| { + match this.resolve_name_in_module(module, name, ns, false, Some(span)) { + Success(_) => all_ns_failed = false, + _ => {} + } + }); - return if let (Failed(_), Failed(_)) = (value_result, type_result) { + return if all_ns_failed { let resolutions = module.resolutions.borrow(); let names = resolutions.iter().filter_map(|(&(ref n, _), resolution)| { if *n == name { return None; } // Never suggest the same name @@ -663,64 +655,49 @@ fn finalize_import(&mut self, directive: &'b ImportDirective<'b>) -> ResolveResu } } - let session = self.session; - let reexport_error = || { - let msg = format!("`{}` is private, and cannot be reexported", name); - let note_msg = - format!("consider marking `{}` as `pub` in the imported module", name); - struct_span_err!(session, directive.span, E0364, "{}", &msg) - .span_note(directive.span, ¬e_msg) - .emit(); - }; - - let extern_crate_lint = || { - let msg = format!("extern crate `{}` is private, and cannot be reexported \ - (error E0364), consider declaring with `pub`", - name); - session.add_lint(PRIVATE_IN_PUBLIC, directive.id, directive.span, msg); - }; - - match (value_result, type_result) { - // All namespaces must be re-exported with extra visibility for an error to occur. - (Ok(value_binding), Ok(type_binding)) => { + let mut reexport_error = None; + let mut any_successful_reexport = false; + self.per_ns(|this, ns| { + if let Ok(binding) = result[ns].get() { let vis = directive.vis.get(); - if !value_binding.pseudo_vis().is_at_least(vis, self) && - !type_binding.pseudo_vis().is_at_least(vis, self) { - reexport_error(); - } else if type_binding.is_extern_crate() && - !type_binding.vis.is_at_least(vis, self) { - extern_crate_lint(); - } - } - - (Ok(binding), _) if !binding.pseudo_vis().is_at_least(directive.vis.get(), self) => { - reexport_error(); - } - - (_, Ok(binding)) if !binding.pseudo_vis().is_at_least(directive.vis.get(), self) => { - if binding.is_extern_crate() { - extern_crate_lint(); + if !binding.pseudo_vis().is_at_least(vis, this) { + reexport_error = Some((ns, binding)); } else { - struct_span_err!(self.session, directive.span, E0365, - "`{}` is private, and cannot be reexported", name) - .span_label(directive.span, &format!("reexport of private `{}`", name)) - .note(&format!("consider declaring type or module `{}` with `pub`", name)) - .emit(); + any_successful_reexport = true; } } + }); - _ => {} + // All namespaces must be re-exported with extra visibility for an error to occur. + if !any_successful_reexport { + let (ns, binding) = reexport_error.unwrap(); + if ns == TypeNS && binding.is_extern_crate() { + let msg = format!("extern crate `{}` is private, and cannot be reexported \ + (error E0364), consider declaring with `pub`", + name); + self.session.add_lint(PRIVATE_IN_PUBLIC, directive.id, directive.span, msg); + } else if ns == TypeNS { + struct_span_err!(self.session, directive.span, E0365, + "`{}` is private, and cannot be reexported", name) + .span_label(directive.span, &format!("reexport of private `{}`", name)) + .note(&format!("consider declaring type or module `{}` with `pub`", name)) + .emit(); + } else { + let msg = format!("`{}` is private, and cannot be reexported", name); + let note_msg = + format!("consider marking `{}` as `pub` in the imported module", name); + struct_span_err!(self.session, directive.span, E0364, "{}", &msg) + .span_note(directive.span, ¬e_msg) + .emit(); + } } // Record what this import resolves to for later uses in documentation, // this may resolve to either a value or a type, but for documentation // purposes it's good enough to just favor one over the other. - let def = match type_result.ok().map(NameBinding::def) { - Some(def) => def, - None => value_result.ok().map(NameBinding::def).unwrap(), - }; - let path_resolution = PathResolution::new(def); - self.def_map.insert(directive.id, path_resolution); + self.per_ns(|this, ns| if let Some(binding) = result[ns].get().ok() { + this.def_map.entry(directive.id).or_insert(PathResolution::new(binding.def())); + }); debug!("(resolving single import) successfully resolved import"); return Success(()); diff --git a/src/test/compile-fail/blind-item-block-item-shadow.rs b/src/test/compile-fail/blind-item-block-item-shadow.rs index a26b9e3c7aa..2d53aee39e9 100644 --- a/src/test/compile-fail/blind-item-block-item-shadow.rs +++ b/src/test/compile-fail/blind-item-block-item-shadow.rs @@ -14,6 +14,6 @@ fn main() { { struct Bar; use foo::Bar; - //~^ ERROR a value named `Bar` has already been defined in this block + //~^ ERROR a type named `Bar` has already been defined in this block } } diff --git a/src/test/compile-fail/double-type-import.rs b/src/test/compile-fail/double-type-import.rs index e51ef5e32e8..760612c05ce 100644 --- a/src/test/compile-fail/double-type-import.rs +++ b/src/test/compile-fail/double-type-import.rs @@ -11,7 +11,7 @@ mod foo { pub use self::bar::X; use self::bar::X; - //~^ ERROR a value named `X` has already been imported in this module + //~^ ERROR a type named `X` has already been imported in this module mod bar { pub struct X; -- GitLab