Refactor out PerNS
.
This commit is contained in:
parent
1bbf7a43d3
commit
b25c063caa
@ -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::{self, Block, ForeignItem, ForeignItemKind, Item, ItemKind};
|
||||
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 @@ impl<'b> Resolver<'b> {
|
||||
.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 @@ impl<'b> Resolver<'b> {
|
||||
(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 @@ impl<'a> Visitor for Resolver<'a> {
|
||||
};
|
||||
|
||||
// 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 @@ impl<'a> Visitor for Resolver<'a> {
|
||||
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 @@ impl<'a> Resolver<'a> {
|
||||
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 @@ impl<'a> Resolver<'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 @@ impl<'a> Resolver<'a> {
|
||||
})
|
||||
}
|
||||
|
||||
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 @@ impl<'a> Resolver<'a> {
|
||||
}
|
||||
|
||||
// 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 @@ impl<'a> Resolver<'a> {
|
||||
}));
|
||||
}
|
||||
|
||||
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 @@ impl<'a> Resolver<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
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 @@ impl<'a> Resolver<'a> {
|
||||
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 @@ impl<'a> Resolver<'a> {
|
||||
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 @@ impl<'a> Resolver<'a> {
|
||||
f(self);
|
||||
|
||||
if let HasTypeParameters(..) = type_parameters {
|
||||
self.type_ribs.pop();
|
||||
self.ribs[TypeNS].pop();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1897,11 +1922,11 @@ impl<'a> Resolver<'a> {
|
||||
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 @@ impl<'a> Resolver<'a> {
|
||||
|
||||
// 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 @@ impl<'a> Resolver<'a> {
|
||||
}
|
||||
|
||||
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 @@ impl<'a> Resolver<'a> {
|
||||
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 @@ impl<'a> Resolver<'a> {
|
||||
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 @@ impl<'a> Resolver<'a> {
|
||||
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 @@ impl<'a> Resolver<'a> {
|
||||
// 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 @@ impl<'a> Resolver<'a> {
|
||||
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 @@ impl<'a> Resolver<'a> {
|
||||
// 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 @@ impl<'a> Resolver<'a> {
|
||||
// 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 @@ impl<'a> Resolver<'a> {
|
||||
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 @@ impl<'a> Resolver<'a> {
|
||||
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 @@ impl<'a> Resolver<'a> {
|
||||
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 @@ impl<'a> Resolver<'a> {
|
||||
} 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 @@ impl<'a> Resolver<'a> {
|
||||
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 @@ impl<'a> Resolver<'a> {
|
||||
|
||||
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 @@ impl<'a> Resolver<'a> {
|
||||
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 @@ impl<'a> Resolver<'a> {
|
||||
|
||||
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 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
|
||||
}
|
||||
}
|
||||
|
||||
// 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 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
|
||||
};
|
||||
|
||||
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 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
|
||||
};
|
||||
|
||||
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 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
|
||||
},
|
||||
};
|
||||
|
||||
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 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
|
||||
_ => 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 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
|
||||
}
|
||||
}
|
||||
|
||||
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(());
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user