提交 b25c063c 编写于 作者: J Jeffrey Seyfried

Refactor out `PerNS`.

上级 1bbf7a43
......@@ -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,
......
......@@ -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;
......
......@@ -536,6 +536,33 @@ pub enum Namespace {
MacroNS,
}
#[derive(Clone, Default, Debug)]
pub struct PerNS<T> {
value_ns: T,
type_ns: T,
}
impl<T> ::std::ops::Index<Namespace> for PerNS<T> {
type Output = T;
fn index(&self, ns: Namespace) -> &T {
match ns {
ValueNS => &self.value_ns,
TypeNS => &self.type_ns,
MacroNS => unreachable!(),
}
}
}
impl<T> ::std::ops::IndexMut<Namespace> for PerNS<T> {
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<Rib<'a>>,
// The current set of local scopes, for types.
type_ribs: Vec<Rib<'a>>,
ribs: PerNS<Vec<Rib<'a>>>,
// The current set of local scopes, for labels.
label_ribs: Vec<Rib<'a>>,
......@@ -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, F: FnMut(&mut Self, Namespace) -> T>(&mut self, mut f: F) -> PerNS<T> {
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<Rib<'a>> {
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<F>(&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<F>(&mut self, f: F)
fn with_constant_rib<F>(&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<F>(&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<Def> {
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<T, F>(&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<T, F>(&mut self, module: Module<'a>, f: F) -> T
fn with_empty_ribs<T, F>(&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::<Vec<Rib>>::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, _) => {
......
......@@ -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<Result<&'a NameBinding<'a>, Determinacy>>,
type_result: Cell<Result<&'a NameBinding<'a>, Determinacy>>,
result: PerNS<Cell<Result<&'a NameBinding<'a>, 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<T, F>(&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, &note_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, &note_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(());
......
......@@ -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
}
}
......@@ -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;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册