1
Fork 0

Add feature use_extern_macros.

This commit is contained in:
Jeffrey Seyfried 2016-11-10 10:29:36 +00:00
parent b25c063caa
commit 9c88650080
6 changed files with 243 additions and 140 deletions

View file

@ -504,9 +504,11 @@ impl<'b> Resolver<'b> {
}) })
} }
pub fn get_macro(&mut self, def: Def) -> Rc<SyntaxExtension> { pub fn get_macro(&mut self, binding: &'b NameBinding<'b>) -> Rc<SyntaxExtension> {
let def_id = match def { let def_id = match binding.kind {
Def::Macro(def_id) => def_id, NameBindingKind::Def(Def::Macro(def_id)) => def_id,
NameBindingKind::Import { binding, .. } => return self.get_macro(binding),
NameBindingKind::Ambiguity { b1, .. } => return self.get_macro(b1),
_ => panic!("Expected Def::Macro(..)"), _ => panic!("Expected Def::Macro(..)"),
}; };
if let Some(ext) = self.macro_map.get(&def_id) { if let Some(ext) = self.macro_map.get(&def_id) {
@ -579,7 +581,7 @@ impl<'b> Resolver<'b> {
}); });
} else { } else {
for (name, span) in legacy_imports.imports { for (name, span) in legacy_imports.imports {
let result = self.resolve_name_in_module(module, name, MacroNS, false, None); let result = self.resolve_name_in_module(module, name, MacroNS, false, false, None);
if let Success(binding) = result { if let Success(binding) = result {
self.legacy_import_macro(name, binding, span, allow_shadowing); self.legacy_import_macro(name, binding, span, allow_shadowing);
} else { } else {
@ -589,7 +591,7 @@ impl<'b> Resolver<'b> {
} }
for (name, span) in legacy_imports.reexports { for (name, span) in legacy_imports.reexports {
self.used_crates.insert(module.def_id().unwrap().krate); self.used_crates.insert(module.def_id().unwrap().krate);
let result = self.resolve_name_in_module(module, name, MacroNS, false, None); let result = self.resolve_name_in_module(module, name, MacroNS, false, false, None);
if let Success(binding) = result { if let Success(binding) = result {
self.macro_exports.push(Export { name: name, def: binding.def() }); self.macro_exports.push(Export { name: name, def: binding.def() });
} else { } else {

View file

@ -540,6 +540,7 @@ pub enum Namespace {
pub struct PerNS<T> { pub struct PerNS<T> {
value_ns: T, value_ns: T,
type_ns: T, type_ns: T,
macro_ns: Option<T>,
} }
impl<T> ::std::ops::Index<Namespace> for PerNS<T> { impl<T> ::std::ops::Index<Namespace> for PerNS<T> {
@ -548,7 +549,7 @@ impl<T> ::std::ops::Index<Namespace> for PerNS<T> {
match ns { match ns {
ValueNS => &self.value_ns, ValueNS => &self.value_ns,
TypeNS => &self.type_ns, TypeNS => &self.type_ns,
MacroNS => unreachable!(), MacroNS => self.macro_ns.as_ref().unwrap(),
} }
} }
} }
@ -558,7 +559,7 @@ impl<T> ::std::ops::IndexMut<Namespace> for PerNS<T> {
match ns { match ns {
ValueNS => &mut self.value_ns, ValueNS => &mut self.value_ns,
TypeNS => &mut self.type_ns, TypeNS => &mut self.type_ns,
MacroNS => unreachable!(), MacroNS => self.macro_ns.as_mut().unwrap(),
} }
} }
} }
@ -675,7 +676,7 @@ impl<'a> Visitor for Resolver<'a> {
pub type ErrorMessage = Option<(Span, String)>; pub type ErrorMessage = Option<(Span, String)>;
#[derive(Clone, PartialEq, Eq)] #[derive(Clone, PartialEq, Eq, Debug)]
pub enum ResolveResult<T> { pub enum ResolveResult<T> {
Failed(ErrorMessage), // Failed to resolve the name, optional helpful error message. Failed(ErrorMessage), // Failed to resolve the name, optional helpful error message.
Indeterminate, // Couldn't determine due to unresolved globs. Indeterminate, // Couldn't determine due to unresolved globs.
@ -683,14 +684,6 @@ pub enum ResolveResult<T> {
} }
impl<T> ResolveResult<T> { impl<T> ResolveResult<T> {
fn and_then<U, F: FnOnce(T) -> ResolveResult<U>>(self, f: F) -> ResolveResult<U> {
match self {
Failed(msg) => Failed(msg),
Indeterminate => Indeterminate,
Success(t) => f(t),
}
}
fn success(self) -> Option<T> { fn success(self) -> Option<T> {
match self { match self {
Success(t) => Some(t), Success(t) => Some(t),
@ -825,6 +818,7 @@ pub struct ModuleS<'a> {
normal_ancestor_id: Option<NodeId>, normal_ancestor_id: Option<NodeId>,
resolutions: RefCell<FxHashMap<(Name, Namespace), &'a RefCell<NameResolution<'a>>>>, resolutions: RefCell<FxHashMap<(Name, Namespace), &'a RefCell<NameResolution<'a>>>>,
legacy_macro_resolutions: RefCell<Vec<(Mark, Name, Span)>>,
// Macro invocations that can expand into items in this module. // Macro invocations that can expand into items in this module.
unresolved_invocations: RefCell<FxHashSet<Mark>>, unresolved_invocations: RefCell<FxHashSet<Mark>>,
@ -852,6 +846,7 @@ impl<'a> ModuleS<'a> {
kind: kind, kind: kind,
normal_ancestor_id: None, normal_ancestor_id: None,
resolutions: RefCell::new(FxHashMap()), resolutions: RefCell::new(FxHashMap()),
legacy_macro_resolutions: RefCell::new(Vec::new()),
unresolved_invocations: RefCell::new(FxHashSet()), unresolved_invocations: RefCell::new(FxHashSet()),
no_implicit_prelude: false, no_implicit_prelude: false,
glob_importers: RefCell::new(Vec::new()), glob_importers: RefCell::new(Vec::new()),
@ -943,6 +938,7 @@ struct PrivacyError<'a>(Span, Name, &'a NameBinding<'a>);
struct AmbiguityError<'a> { struct AmbiguityError<'a> {
span: Span, span: Span,
name: Name, name: Name,
lexical: bool,
b1: &'a NameBinding<'a>, b1: &'a NameBinding<'a>,
b2: &'a NameBinding<'a>, b2: &'a NameBinding<'a>,
} }
@ -1001,7 +997,7 @@ impl<'a> NameBinding<'a> {
fn is_glob_import(&self) -> bool { fn is_glob_import(&self) -> bool {
match self.kind { match self.kind {
NameBindingKind::Import { directive, .. } => directive.is_glob(), NameBindingKind::Import { directive, .. } => directive.is_glob(),
NameBindingKind::Ambiguity { .. } => true, NameBindingKind::Ambiguity { b1, .. } => b1.is_glob_import(),
_ => false, _ => false,
} }
} }
@ -1136,6 +1132,7 @@ pub struct Resolver<'a> {
arenas: &'a ResolverArenas<'a>, arenas: &'a ResolverArenas<'a>,
dummy_binding: &'a NameBinding<'a>, dummy_binding: &'a NameBinding<'a>,
new_import_semantics: bool, // true if `#![feature(item_like_imports)]` new_import_semantics: bool, // true if `#![feature(item_like_imports)]`
use_extern_macros: bool, // true if `#![feature(use_extern_macros)]`
pub exported_macros: Vec<ast::MacroDef>, pub exported_macros: Vec<ast::MacroDef>,
crate_loader: &'a mut CrateLoader, crate_loader: &'a mut CrateLoader,
@ -1300,6 +1297,7 @@ impl<'a> Resolver<'a> {
ribs: PerNS { ribs: PerNS {
value_ns: vec![Rib::new(ModuleRibKind(graph_root))], value_ns: vec![Rib::new(ModuleRibKind(graph_root))],
type_ns: vec![Rib::new(ModuleRibKind(graph_root))], type_ns: vec![Rib::new(ModuleRibKind(graph_root))],
macro_ns: None,
}, },
label_ribs: Vec::new(), label_ribs: Vec::new(),
@ -1336,6 +1334,7 @@ impl<'a> Resolver<'a> {
vis: ty::Visibility::Public, vis: ty::Visibility::Public,
}), }),
new_import_semantics: session.features.borrow().item_like_imports, new_import_semantics: session.features.borrow().item_like_imports,
use_extern_macros: session.features.borrow().use_extern_macros,
exported_macros: Vec::new(), exported_macros: Vec::new(),
crate_loader: crate_loader, crate_loader: crate_loader,
@ -1365,6 +1364,10 @@ impl<'a> Resolver<'a> {
PerNS { PerNS {
type_ns: f(self, TypeNS), type_ns: f(self, TypeNS),
value_ns: f(self, ValueNS), value_ns: f(self, ValueNS),
macro_ns: match self.use_extern_macros {
true => Some(f(self, MacroNS)),
false => None,
},
} }
} }
@ -1403,8 +1406,9 @@ impl<'a> Resolver<'a> {
} }
NameBindingKind::Import { .. } => false, NameBindingKind::Import { .. } => false,
NameBindingKind::Ambiguity { b1, b2 } => { NameBindingKind::Ambiguity { b1, b2 } => {
let ambiguity_error = AmbiguityError { span: span, name: name, b1: b1, b2: b2 }; self.ambiguity_errors.push(AmbiguityError {
self.ambiguity_errors.push(ambiguity_error); span: span, name: name, lexical: false, b1: b1, b2: b2,
});
true true
} }
_ => false _ => false
@ -1438,7 +1442,7 @@ impl<'a> Resolver<'a> {
-> ResolveResult<Module<'a>> { -> ResolveResult<Module<'a>> {
fn search_parent_externals<'a>(this: &mut Resolver<'a>, needle: Name, module: Module<'a>) fn search_parent_externals<'a>(this: &mut Resolver<'a>, needle: Name, module: Module<'a>)
-> Option<Module<'a>> { -> Option<Module<'a>> {
match this.resolve_name_in_module(module, needle, TypeNS, false, None) { match this.resolve_name_in_module(module, needle, TypeNS, false, false, None) {
Success(binding) if binding.is_extern_crate() => Some(module), Success(binding) if binding.is_extern_crate() => Some(module),
_ => if let (&ModuleKind::Def(..), Some(parent)) = (&module.kind, module.parent) { _ => if let (&ModuleKind::Def(..), Some(parent)) = (&module.kind, module.parent) {
search_parent_externals(this, needle, parent) search_parent_externals(this, needle, parent)
@ -1456,7 +1460,7 @@ impl<'a> Resolver<'a> {
// modules as we go. // modules as we go.
while index < module_path_len { while index < module_path_len {
let name = module_path[index].name; let name = module_path[index].name;
match self.resolve_name_in_module(search_module, name, TypeNS, false, span) { match self.resolve_name_in_module(search_module, name, TypeNS, false, false, span) {
Failed(_) => { Failed(_) => {
let segment_name = name.as_str(); let segment_name = name.as_str();
let module_name = module_to_string(search_module); let module_name = module_to_string(search_module);
@ -1613,7 +1617,7 @@ impl<'a> Resolver<'a> {
if let ModuleRibKind(module) = self.ribs[ns][i].kind { if let ModuleRibKind(module) = self.ribs[ns][i].kind {
let name = ident.name; let name = ident.name;
let item = self.resolve_name_in_module(module, name, ns, true, record_used); let item = self.resolve_name_in_module(module, name, ns, true, false, record_used);
if let Success(binding) = item { if let Success(binding) = item {
// The ident resolves to an item. // The ident resolves to an item.
return Some(LexicalScopeBinding::Item(binding)); return Some(LexicalScopeBinding::Item(binding));
@ -1622,7 +1626,7 @@ impl<'a> Resolver<'a> {
if let ModuleKind::Block(..) = module.kind { // We can see through blocks if let ModuleKind::Block(..) = module.kind { // We can see through blocks
} else if !module.no_implicit_prelude { } else if !module.no_implicit_prelude {
return self.prelude.and_then(|prelude| { return self.prelude.and_then(|prelude| {
self.resolve_name_in_module(prelude, name, ns, false, None).success() self.resolve_name_in_module(prelude, name, ns, false, false, None).success()
}).map(LexicalScopeBinding::Item) }).map(LexicalScopeBinding::Item)
} else { } else {
return None; return None;
@ -1717,6 +1721,7 @@ impl<'a> Resolver<'a> {
self.ribs[ValueNS].push(Rib::new(ModuleRibKind(module))); self.ribs[ValueNS].push(Rib::new(ModuleRibKind(module)));
self.ribs[TypeNS].push(Rib::new(ModuleRibKind(module))); self.ribs[TypeNS].push(Rib::new(ModuleRibKind(module)));
self.finalize_current_module_macro_resolutions();
f(self); f(self);
self.current_module = orig_module; self.current_module = orig_module;
@ -2221,6 +2226,7 @@ impl<'a> Resolver<'a> {
self.ribs[ValueNS].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.ribs[TypeNS].push(Rib::new(ModuleRibKind(anonymous_module)));
self.current_module = anonymous_module; self.current_module = anonymous_module;
self.finalize_current_module_macro_resolutions();
} else { } else {
self.ribs[ValueNS].push(Rib::new(NormalRibKind)); self.ribs[ValueNS].push(Rib::new(NormalRibKind));
} }
@ -2754,8 +2760,7 @@ impl<'a> Resolver<'a> {
let module_path = let module_path =
segments.split_last().unwrap().1.iter().map(|ps| ps.identifier).collect::<Vec<_>>(); segments.split_last().unwrap().1.iter().map(|ps| ps.identifier).collect::<Vec<_>>();
let containing_module; let module = match self.resolve_module_path(&module_path, UseLexicalScope, Some(span)) {
match self.resolve_module_path(&module_path, UseLexicalScope, Some(span)) {
Failed(err) => { Failed(err) => {
if let Some((span, msg)) = err { if let Some((span, msg)) = err {
resolve_error(self, span, ResolutionError::FailedToResolve(&msg)); resolve_error(self, span, ResolutionError::FailedToResolve(&msg));
@ -2763,14 +2768,11 @@ impl<'a> Resolver<'a> {
return Err(true); return Err(true);
} }
Indeterminate => return Err(false), Indeterminate => return Err(false),
Success(resulting_module) => { Success(module) => module,
containing_module = resulting_module; };
}
}
let name = segments.last().unwrap().identifier.name; let name = segments.last().unwrap().identifier.name;
let result = let result = self.resolve_name_in_module(module, name, namespace, false, false, Some(span));
self.resolve_name_in_module(containing_module, name, namespace, false, Some(span));
result.success().ok_or(false) result.success().ok_or(false)
} }
@ -2782,10 +2784,9 @@ impl<'a> Resolver<'a> {
where T: Named, where T: Named,
{ {
let module_path = segments.split_last().unwrap().1.iter().map(T::ident).collect::<Vec<_>>(); let module_path = segments.split_last().unwrap().1.iter().map(T::ident).collect::<Vec<_>>();
let root_module = self.graph_root; let root = self.graph_root;
let containing_module; let module = match self.resolve_module_path_from_root(root, &module_path, 0, Some(span)) {
match self.resolve_module_path_from_root(root_module, &module_path, 0, Some(span)) {
Failed(err) => { Failed(err) => {
if let Some((span, msg)) = err { if let Some((span, msg)) = err {
resolve_error(self, span, ResolutionError::FailedToResolve(&msg)); resolve_error(self, span, ResolutionError::FailedToResolve(&msg));
@ -2795,14 +2796,11 @@ impl<'a> Resolver<'a> {
Indeterminate => return Err(false), Indeterminate => return Err(false),
Success(resulting_module) => { Success(module) => module,
containing_module = resulting_module; };
}
}
let name = segments.last().unwrap().ident().name; let name = segments.last().unwrap().ident().name;
let result = let result = self.resolve_name_in_module(module, name, namespace, false, false, Some(span));
self.resolve_name_in_module(containing_module, name, namespace, false, Some(span));
result.success().ok_or(false) result.success().ok_or(false)
} }
@ -3383,14 +3381,18 @@ impl<'a> Resolver<'a> {
self.report_shadowing_errors(); self.report_shadowing_errors();
let mut reported_spans = FxHashSet(); let mut reported_spans = FxHashSet();
for &AmbiguityError { span, name, b1, b2 } in &self.ambiguity_errors { for &AmbiguityError { span, name, b1, b2, lexical } in &self.ambiguity_errors {
if !reported_spans.insert(span) { continue } if !reported_spans.insert(span) { continue }
let msg1 = format!("`{}` could resolve to the name imported here", name); let msg1 = format!("`{}` could resolve to the name imported here", name);
let msg2 = format!("`{}` could also resolve to the name imported here", name); let msg2 = format!("`{}` could also resolve to the name imported here", name);
self.session.struct_span_err(span, &format!("`{}` is ambiguous", name)) self.session.struct_span_err(span, &format!("`{}` is ambiguous", name))
.span_note(b1.span, &msg1) .span_note(b1.span, &msg1)
.span_note(b2.span, &msg2) .span_note(b2.span, &msg2)
.note(&format!("Consider adding an explicit import of `{}` to disambiguate", name)) .note(&if lexical || !b1.is_glob_import() {
"macro-expanded macro imports do not shadow".to_owned()
} else {
format!("consider adding an explicit import of `{}` to disambiguate", name)
})
.emit(); .emit();
} }
@ -3413,12 +3415,12 @@ impl<'a> Resolver<'a> {
fn report_shadowing_errors(&mut self) { fn report_shadowing_errors(&mut self) {
for (name, scope) in replace(&mut self.lexical_macro_resolutions, Vec::new()) { for (name, scope) in replace(&mut self.lexical_macro_resolutions, Vec::new()) {
self.resolve_macro_name(scope, name); self.resolve_legacy_scope(scope, name, true);
} }
let mut reported_errors = FxHashSet(); let mut reported_errors = FxHashSet();
for binding in replace(&mut self.disallowed_shadowing, Vec::new()) { for binding in replace(&mut self.disallowed_shadowing, Vec::new()) {
if self.resolve_macro_name(binding.parent, binding.name).is_some() && if self.resolve_legacy_scope(binding.parent, binding.name, false).is_some() &&
reported_errors.insert((binding.name, binding.span)) { reported_errors.insert((binding.name, binding.span)) {
let msg = format!("`{}` is already in scope", binding.name); let msg = format!("`{}` is already in scope", binding.name);
self.session.struct_span_err(binding.span, &msg) self.session.struct_span_err(binding.span, &msg)

View file

@ -8,7 +8,9 @@
// option. This file may not be copied, modified, or distributed // option. This file may not be copied, modified, or distributed
// except according to those terms. // except according to those terms.
use {Module, ModuleKind, NameBinding, NameBindingKind, Resolver}; use {Module, ModuleKind, NameBinding, NameBindingKind, Resolver, AmbiguityError};
use Namespace::{self, MacroNS};
use ResolveResult::{Success, Indeterminate, Failed};
use build_reduced_graph::BuildReducedGraphVisitor; use build_reduced_graph::BuildReducedGraphVisitor;
use resolve_imports::ImportResolver; use resolve_imports::ImportResolver;
use rustc::hir::def_id::{DefId, BUILTIN_MACROS_CRATE, CRATE_DEF_INDEX, DefIndex}; use rustc::hir::def_id::{DefId, BUILTIN_MACROS_CRATE, CRATE_DEF_INDEX, DefIndex};
@ -17,7 +19,7 @@ use rustc::hir::map::{self, DefCollector};
use rustc::ty; use rustc::ty;
use std::cell::Cell; use std::cell::Cell;
use std::rc::Rc; use std::rc::Rc;
use syntax::ast; use syntax::ast::{self, Name};
use syntax::errors::DiagnosticBuilder; use syntax::errors::DiagnosticBuilder;
use syntax::ext::base::{self, Determinacy, MultiModifier, MultiDecorator}; use syntax::ext::base::{self, Determinacy, MultiModifier, MultiDecorator};
use syntax::ext::base::{NormalTT, SyntaxExtension}; use syntax::ext::base::{NormalTT, SyntaxExtension};
@ -85,6 +87,11 @@ pub struct LegacyBinding<'a> {
pub span: Span, pub span: Span,
} }
pub enum MacroBinding<'a> {
Legacy(&'a LegacyBinding<'a>),
Modern(&'a NameBinding<'a>),
}
impl<'a> base::Resolver for Resolver<'a> { impl<'a> base::Resolver for Resolver<'a> {
fn next_node_id(&mut self) -> ast::NodeId { fn next_node_id(&mut self) -> ast::NodeId {
self.session.next_node_id() self.session.next_node_id()
@ -140,6 +147,7 @@ impl<'a> base::Resolver for Resolver<'a> {
expansion: mark, expansion: mark,
}; };
expansion.visit_with(&mut visitor); expansion.visit_with(&mut visitor);
self.current_module.unresolved_invocations.borrow_mut().remove(&mark);
invocation.expansion.set(visitor.legacy_scope); invocation.expansion.set(visitor.legacy_scope);
} }
@ -201,7 +209,7 @@ impl<'a> base::Resolver for Resolver<'a> {
for i in 0..attrs.len() { for i in 0..attrs.len() {
let name = intern(&attrs[i].name()); let name = intern(&attrs[i].name());
match self.builtin_macros.get(&name).cloned() { match self.builtin_macros.get(&name).cloned() {
Some(binding) => match *self.get_macro(binding.def()) { Some(binding) => match *self.get_macro(binding) {
MultiModifier(..) | MultiDecorator(..) | SyntaxExtension::AttrProcMacro(..) => { MultiModifier(..) | MultiDecorator(..) | SyntaxExtension::AttrProcMacro(..) => {
return Some(attrs.remove(i)) return Some(attrs.remove(i))
} }
@ -225,25 +233,77 @@ impl<'a> base::Resolver for Resolver<'a> {
if let LegacyScope::Expansion(parent) = invocation.legacy_scope.get() { if let LegacyScope::Expansion(parent) = invocation.legacy_scope.get() {
invocation.legacy_scope.set(LegacyScope::simplify_expansion(parent)); invocation.legacy_scope.set(LegacyScope::simplify_expansion(parent));
} }
self.resolve_macro_name(invocation.legacy_scope.get(), name).ok_or_else(|| {
if force { self.current_module = invocation.module.get();
let msg = format!("macro undefined: '{}!'", name); let result = match self.resolve_legacy_scope(invocation.legacy_scope.get(), name, false) {
let mut err = self.session.struct_span_err(path.span, &msg); Some(MacroBinding::Legacy(binding)) => Ok(binding.ext.clone()),
self.suggest_macro_name(&name.as_str(), &mut err); Some(MacroBinding::Modern(binding)) => Ok(self.get_macro(binding)),
err.emit(); None => match self.resolve_in_item_lexical_scope(name, MacroNS, None) {
Determinacy::Determined Some(binding) => Ok(self.get_macro(binding)),
} else { None => return Err(if force {
Determinacy::Undetermined let msg = format!("macro undefined: '{}!'", name);
} let mut err = self.session.struct_span_err(path.span, &msg);
}) self.suggest_macro_name(&name.as_str(), &mut err);
err.emit();
Determinacy::Determined
} else {
Determinacy::Undetermined
}),
},
};
if self.use_extern_macros {
self.current_module.legacy_macro_resolutions.borrow_mut()
.push((scope, name, path.span));
}
result
} }
} }
impl<'a> Resolver<'a> { impl<'a> Resolver<'a> {
pub fn resolve_macro_name(&mut self, mut scope: LegacyScope<'a>, name: ast::Name) // Resolve the name in the module's lexical scope, excluding non-items.
-> Option<Rc<SyntaxExtension>> { fn resolve_in_item_lexical_scope(
&mut self, name: Name, ns: Namespace, record_used: Option<Span>,
) -> Option<&'a NameBinding<'a>> {
let mut module = self.current_module;
let mut potential_expanded_shadower = None;
loop {
// Since expanded macros may not shadow the lexical scope (enforced below),
// we can ignore unresolved invocations (indicated by the penultimate argument).
match self.resolve_name_in_module(module, name, ns, true, true, record_used) {
Success(binding) => {
let span = match record_used {
Some(span) => span,
None => return Some(binding),
};
if let Some(shadower) = potential_expanded_shadower {
self.ambiguity_errors.push(AmbiguityError {
span: span, name: name, b1: shadower, b2: binding, lexical: true,
});
return Some(shadower);
} else if binding.expansion == Mark::root() {
return Some(binding);
} else {
potential_expanded_shadower = Some(binding);
}
},
Indeterminate => return None,
Failed(..) => {}
}
match module.kind {
ModuleKind::Block(..) => module = module.parent.unwrap(),
ModuleKind::Def(..) => return potential_expanded_shadower,
}
}
}
pub fn resolve_legacy_scope(
&mut self, mut scope: LegacyScope<'a>, name: ast::Name, record_used: bool,
) -> Option<MacroBinding<'a>> {
let mut possible_time_travel = None; let mut possible_time_travel = None;
let mut relative_depth: u32 = 0; let mut relative_depth: u32 = 0;
let mut binding = None;
loop { loop {
scope = match scope { scope = match scope {
LegacyScope::Empty => break, LegacyScope::Empty => break,
@ -262,25 +322,59 @@ impl<'a> Resolver<'a> {
relative_depth = relative_depth.saturating_sub(1); relative_depth = relative_depth.saturating_sub(1);
invocation.legacy_scope.get() invocation.legacy_scope.get()
} }
LegacyScope::Binding(binding) => { LegacyScope::Binding(potential_binding) => {
if binding.name == name { if potential_binding.name == name {
if let Some(scope) = possible_time_travel { if (!self.use_extern_macros || record_used) && relative_depth > 0 {
// Check for disallowed shadowing later self.disallowed_shadowing.push(potential_binding);
self.lexical_macro_resolutions.push((name, scope));
} else if relative_depth > 0 {
self.disallowed_shadowing.push(binding);
} }
return Some(binding.ext.clone()); binding = Some(potential_binding);
break
} }
binding.parent potential_binding.parent
} }
}; };
} }
if let Some(scope) = possible_time_travel { let binding = match binding {
self.lexical_macro_resolutions.push((name, scope)); Some(binding) => MacroBinding::Legacy(binding),
None => match self.builtin_macros.get(&name).cloned() {
Some(binding) => MacroBinding::Modern(binding),
None => return None,
},
};
if !self.use_extern_macros {
if let Some(scope) = possible_time_travel {
// Check for disallowed shadowing later
self.lexical_macro_resolutions.push((name, scope));
}
}
Some(binding)
}
pub fn finalize_current_module_macro_resolutions(&mut self) {
let module = self.current_module;
for &(mark, name, span) in module.legacy_macro_resolutions.borrow().iter() {
let legacy_scope = self.invocations[&mark].legacy_scope.get();
let legacy_resolution = self.resolve_legacy_scope(legacy_scope, name, true);
let resolution = self.resolve_in_item_lexical_scope(name, MacroNS, Some(span));
let (legacy_resolution, resolution) = match (legacy_resolution, resolution) {
(Some(legacy_resolution), Some(resolution)) => (legacy_resolution, resolution),
_ => continue,
};
let (legacy_span, participle) = match legacy_resolution {
MacroBinding::Modern(binding) if binding.def() == resolution.def() => continue,
MacroBinding::Modern(binding) => (binding.span, "imported"),
MacroBinding::Legacy(binding) => (binding.span, "defined"),
};
let msg1 = format!("`{}` could resolve to the macro {} here", name, participle);
let msg2 = format!("`{}` could also resolve to the macro imported here", name);
self.session.struct_span_err(span, &format!("`{}` is ambiguous", name))
.span_note(legacy_span, &msg1)
.span_note(resolution.span, &msg2)
.emit();
} }
self.builtin_macros.get(&name).cloned().map(|binding| self.get_macro(binding.def()))
} }
fn suggest_macro_name(&mut self, name: &str, err: &mut DiagnosticBuilder<'a>) { fn suggest_macro_name(&mut self, name: &str, err: &mut DiagnosticBuilder<'a>) {

View file

@ -11,7 +11,7 @@
use self::ImportDirectiveSubclass::*; use self::ImportDirectiveSubclass::*;
use {Module, PerNS}; use {Module, PerNS};
use Namespace::{self, TypeNS}; use Namespace::{self, TypeNS, MacroNS};
use {NameBinding, NameBindingKind, PrivacyError, ToNameBinding}; use {NameBinding, NameBindingKind, PrivacyError, ToNameBinding};
use ResolveResult; use ResolveResult;
use ResolveResult::*; use ResolveResult::*;
@ -142,6 +142,7 @@ impl<'a> Resolver<'a> {
name: Name, name: Name,
ns: Namespace, ns: Namespace,
allow_private_imports: bool, allow_private_imports: bool,
ignore_unresolved_invocations: bool,
record_used: Option<Span>) record_used: Option<Span>)
-> ResolveResult<&'a NameBinding<'a>> { -> ResolveResult<&'a NameBinding<'a>> {
self.populate_module_if_necessary(module); self.populate_module_if_necessary(module);
@ -175,23 +176,55 @@ impl<'a> Resolver<'a> {
return resolution.binding.map(Success).unwrap_or(Failed(None)); return resolution.binding.map(Success).unwrap_or(Failed(None));
} }
// If the resolution doesn't depend on glob definability, check privacy and return. let check_usable = |this: &mut Self, binding: &'a NameBinding<'a>| {
if let Some(result) = self.try_result(&resolution, module, ns) { let usable =
return result.and_then(|binding| { this.is_accessible(binding.vis) && !is_disallowed_private_import(binding) ||
if self.is_accessible(binding.vis) && !is_disallowed_private_import(binding) || binding.is_extern_crate(); // c.f. issue #37020
binding.is_extern_crate() { // c.f. issue #37020 if usable { Success(binding) } else { Failed(None) }
Success(binding) };
} else {
Failed(None) // Items and single imports are not shadowable.
if let Some(binding) = resolution.binding {
if !binding.is_glob_import() {
return check_usable(self, binding);
}
}
// Check if a single import can still define the name.
match resolution.single_imports {
SingleImports::AtLeastOne => return Indeterminate,
SingleImports::MaybeOne(directive) if self.is_accessible(directive.vis.get()) => {
let module = match directive.imported_module.get() {
Some(module) => module,
None => return Indeterminate,
};
let name = match directive.subclass {
SingleImport { source, .. } => source,
_ => unreachable!(),
};
match self.resolve_name_in_module(module, name, ns, true, false, None) {
Failed(_) => {}
_ => return Indeterminate,
} }
}); }
SingleImports::MaybeOne(_) | SingleImports::None => {},
}
let no_unresolved_invocations =
ignore_unresolved_invocations || module.unresolved_invocations.borrow().is_empty();
match resolution.binding {
// In `MacroNS`, expanded bindings do not shadow (enforced in `try_define`).
Some(binding) if no_unresolved_invocations || ns == MacroNS =>
return check_usable(self, binding),
None if no_unresolved_invocations => {}
_ => return Indeterminate,
} }
// Check if the globs are determined // Check if the globs are determined
for directive in module.globs.borrow().iter() { for directive in module.globs.borrow().iter() {
if self.is_accessible(directive.vis.get()) { if self.is_accessible(directive.vis.get()) {
if let Some(module) = directive.imported_module.get() { if let Some(module) = directive.imported_module.get() {
let result = self.resolve_name_in_module(module, name, ns, true, None); let result = self.resolve_name_in_module(module, name, ns, true, false, None);
if let Indeterminate = result { if let Indeterminate = result {
return Indeterminate; return Indeterminate;
} }
@ -204,43 +237,6 @@ impl<'a> Resolver<'a> {
Failed(None) Failed(None)
} }
// Returns Some(the resolution of the name), or None if the resolution depends
// on whether more globs can define the name.
fn try_result(&mut self, resolution: &NameResolution<'a>, module: Module<'a>, ns: Namespace)
-> Option<ResolveResult<&'a NameBinding<'a>>> {
match resolution.binding {
Some(binding) if !binding.is_glob_import() =>
return Some(Success(binding)), // Items and single imports are not shadowable.
_ => {}
};
// Check if a single import can still define the name.
match resolution.single_imports {
SingleImports::AtLeastOne => return Some(Indeterminate),
SingleImports::MaybeOne(directive) if self.is_accessible(directive.vis.get()) => {
let module = match directive.imported_module.get() {
Some(module) => module,
None => return Some(Indeterminate),
};
let name = match directive.subclass {
SingleImport { source, .. } => source,
_ => unreachable!(),
};
match self.resolve_name_in_module(module, name, ns, true, None) {
Failed(_) => {}
_ => return Some(Indeterminate),
}
}
SingleImports::MaybeOne(_) | SingleImports::None => {},
}
if !module.unresolved_invocations.borrow().is_empty() {
return Some(Indeterminate);
}
resolution.binding.map(Success)
}
// Add an import directive to the current module. // Add an import directive to the current module.
pub fn add_import_directive(&mut self, pub fn add_import_directive(&mut self,
module_path: Vec<Ident>, module_path: Vec<Ident>,
@ -315,29 +311,26 @@ impl<'a> Resolver<'a> {
self.update_resolution(module, name, ns, |this, resolution| { self.update_resolution(module, name, ns, |this, resolution| {
if let Some(old_binding) = resolution.binding { if let Some(old_binding) = resolution.binding {
if binding.is_glob_import() { if binding.is_glob_import() {
if !this.new_import_semantics || !old_binding.is_glob_import() { if !this.new_import_semantics {
resolution.duplicate_globs.push(binding); resolution.duplicate_globs.push(binding);
} else if !old_binding.is_glob_import() &&
!(ns == MacroNS && old_binding.expansion != Mark::root()) {
} else if binding.def() != old_binding.def() { } else if binding.def() != old_binding.def() {
resolution.binding = Some(this.arenas.alloc_name_binding(NameBinding { resolution.binding = Some(this.ambiguity(old_binding, binding));
kind: NameBindingKind::Ambiguity {
b1: old_binding,
b2: binding,
},
vis: if old_binding.vis.is_at_least(binding.vis, this) {
old_binding.vis
} else {
binding.vis
},
span: old_binding.span,
expansion: Mark::root(),
}));
} else if !old_binding.vis.is_at_least(binding.vis, this) { } else if !old_binding.vis.is_at_least(binding.vis, this) {
// We are glob-importing the same item but with greater visibility. // We are glob-importing the same item but with greater visibility.
resolution.binding = Some(binding); resolution.binding = Some(binding);
} }
} else if old_binding.is_glob_import() { } else if old_binding.is_glob_import() {
resolution.duplicate_globs.push(old_binding); if !this.new_import_semantics {
resolution.binding = Some(binding); resolution.duplicate_globs.push(old_binding);
resolution.binding = Some(binding);
} else if ns == MacroNS && binding.expansion != Mark::root() &&
binding.def() != old_binding.def() {
resolution.binding = Some(this.ambiguity(binding, old_binding));
} else {
resolution.binding = Some(binding);
}
} else { } else {
return Err(old_binding); return Err(old_binding);
} }
@ -349,6 +342,16 @@ impl<'a> Resolver<'a> {
}) })
} }
pub fn ambiguity(&mut self, b1: &'a NameBinding<'a>, b2: &'a NameBinding<'a>)
-> &'a NameBinding<'a> {
self.arenas.alloc_name_binding(NameBinding {
kind: NameBindingKind::Ambiguity { b1: b1, b2: b2 },
vis: if b1.vis.is_at_least(b2.vis, self) { b1.vis } else { b2.vis },
span: b1.span,
expansion: Mark::root(),
})
}
// Use `f` to mutate the resolution of the name in the module. // Use `f` to mutate the resolution of the name in the module.
// If the resolution becomes a success, define it in the module's glob importers. // If the resolution becomes a success, define it in the module's glob importers.
fn update_resolution<T, F>(&mut self, module: Module<'a>, name: Name, ns: Namespace, f: F) -> T fn update_resolution<T, F>(&mut self, module: Module<'a>, name: Name, ns: Namespace, f: F) -> T
@ -525,7 +528,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
self.per_ns(|this, ns| { self.per_ns(|this, ns| {
if let Err(Undetermined) = result[ns].get() { if let Err(Undetermined) = result[ns].get() {
result[ns].set({ result[ns].set({
match this.resolve_name_in_module(module, source, ns, false, None) { match this.resolve_name_in_module(module, source, ns, false, false, None) {
Success(binding) => Ok(binding), Success(binding) => Ok(binding),
Indeterminate => Err(Undetermined), Indeterminate => Err(Undetermined),
Failed(_) => Err(Determined), Failed(_) => Err(Determined),
@ -621,7 +624,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
if all_ns_err { if all_ns_err {
let mut all_ns_failed = true; let mut all_ns_failed = true;
self.per_ns(|this, ns| { self.per_ns(|this, ns| {
match this.resolve_name_in_module(module, name, ns, false, Some(span)) { match this.resolve_name_in_module(module, name, ns, false, false, Some(span)) {
Success(_) => all_ns_failed = false, Success(_) => all_ns_failed = false,
_ => {} _ => {}
} }

View file

@ -314,6 +314,8 @@ declare_features! (
// Allows #[link(..., cfg(..))] // Allows #[link(..., cfg(..))]
(active, link_cfg, "1.14.0", Some(37406)), (active, link_cfg, "1.14.0", Some(37406)),
(active, use_extern_macros, "1.15.0", Some(35896)),
); );
declare_features! ( declare_features! (

View file

@ -46,9 +46,9 @@ mod g {
fn main() { fn main() {
e::foo(); e::foo();
f::foo(); //~ ERROR `foo` is ambiguous f::foo(); //~ ERROR `foo` is ambiguous
//~| NOTE Consider adding an explicit import of `foo` to disambiguate //~| NOTE consider adding an explicit import of `foo` to disambiguate
g::foo(); //~ ERROR `foo` is ambiguous g::foo(); //~ ERROR `foo` is ambiguous
//~| NOTE Consider adding an explicit import of `foo` to disambiguate //~| NOTE consider adding an explicit import of `foo` to disambiguate
} }
mod ambiguous_module_errors { mod ambiguous_module_errors {