fn descr(&self) -> &'static str {
if self.is_extern_crate() { "extern crate" } else { self.def().kind_name() }
}
+
+ // Suppose that we resolved macro invocation with `invoc_id` to binding `binding` at some
+ // expansion round `max(invoc_id, binding)` when they both emerged from macros.
+ // Then this function returns `true` if `self` may emerge from a macro *after* that
+ // in some later round and screw up our previously found resolution.
+ fn may_appear_after(&self, _invoc_id: Mark, _binding: &NameBinding) -> bool {
+ // FIXME: This is a very conservative estimation.
+ self.expansion != Mark::root()
+ }
}
/// Interns the names of the primitive types.
record_used: bool,
path_span: Span,
crate_lint: CrateLint,
+ ) -> PathResult<'a> {
+ self.resolve_path_with_invoc_id(base_module, path, opt_ns, Mark::root(),
+ record_used, path_span, crate_lint)
+ }
+
+ fn resolve_path_with_invoc_id(
+ &mut self,
+ base_module: Option<ModuleOrUniformRoot<'a>>,
+ path: &[Ident],
+ opt_ns: Option<Namespace>, // `None` indicates a module path
+ invoc_id: Mark,
+ record_used: bool,
+ path_span: Span,
+ crate_lint: CrateLint,
) -> PathResult<'a> {
let mut module = base_module;
let mut allow_super = true;
self.resolve_ident_in_module(module, ident, ns, record_used, path_span)
} else if opt_ns == Some(MacroNS) {
assert!(ns == TypeNS);
- self.resolve_lexical_macro_path_segment(ident, ns, record_used, record_used,
- false, path_span).map(|(b, _)| b)
+ self.resolve_lexical_macro_path_segment(ident, ns, invoc_id, record_used,
+ record_used, false, path_span)
+ .map(|(binding, _)| binding)
} else {
let record_used_id =
if record_used { crate_lint.node_id().or(Some(CRATE_NODE_ID)) } else { None };
Ok((def, self.get_macro(def)))
}
- pub fn resolve_macro_to_def_inner(&mut self, path: &ast::Path, kind: MacroKind, scope: Mark,
+ pub fn resolve_macro_to_def_inner(&mut self, path: &ast::Path, kind: MacroKind, invoc_id: Mark,
derives_in_scope: &[ast::Path], force: bool)
-> Result<Def, Determinacy> {
let ast::Path { ref segments, span } = *path;
let mut path: Vec<_> = segments.iter().map(|seg| seg.ident).collect();
- let invocation = self.invocations[&scope];
+ let invocation = self.invocations[&invoc_id];
let module = invocation.module.get();
self.current_module = if module.is_trait() { module.parent.unwrap() } else { module };
}
if path.len() > 1 {
- let res = self.resolve_path(None, &path, Some(MacroNS), false, span, CrateLint::No);
- let def = match res {
+ let def = match self.resolve_path_with_invoc_id(None, &path, Some(MacroNS), invoc_id,
+ false, span, CrateLint::No) {
PathResult::NonModule(path_res) => match path_res.base_def() {
Def::Err => Err(Determinacy::Determined),
def @ _ => {
}
}
- let legacy_resolution = self.resolve_legacy_scope(&invocation.legacy_scope, path[0], false);
+ let legacy_resolution =
+ self.resolve_legacy_scope(path[0], invoc_id, &invocation.legacy_scope, false);
let result = if let Some(legacy_binding) = legacy_resolution {
Ok(legacy_binding.def())
} else {
- match self.resolve_lexical_macro_path_segment(path[0], MacroNS, false, force,
+ match self.resolve_lexical_macro_path_segment(path[0], MacroNS, invoc_id, false, force,
kind == MacroKind::Attr, span) {
Ok((binding, _)) => Ok(binding.def_ignoring_ambiguity()),
Err(Determinacy::Undetermined) => return Err(Determinacy::Undetermined),
};
self.current_module.nearest_item_scope().legacy_macro_resolutions.borrow_mut()
- .push((scope, path[0], kind, result.ok()));
+ .push((invoc_id, path[0], kind, result.ok()));
if let Ok(Def::NonMacroAttr(NonMacroAttrKind::Custom)) = result {} else {
return result;
enum ConvertToDeriveHelper { Yes, No, DontKnow }
let mut convert_to_derive_helper = ConvertToDeriveHelper::No;
for derive in derives_in_scope {
- match self.resolve_macro_path(derive, MacroKind::Derive, scope, &[], force) {
+ match self.resolve_macro_path(derive, MacroKind::Derive, invoc_id, &[], force) {
Ok(ext) => if let SyntaxExtension::ProcMacroDerive(_, ref inert_attrs, _) = *ext {
if inert_attrs.contains(&path[0].name) {
convert_to_derive_helper = ConvertToDeriveHelper::Yes;
&mut self,
mut ident: Ident,
ns: Namespace,
+ invoc_id: Mark,
record_used: bool,
force: bool,
is_attr: bool,
- path_span: Span
+ path_span: Span,
) -> Result<(&'a NameBinding<'a>, FromPrelude), Determinacy> {
// General principles:
// 1. Not controlled (user-defined) names should have higher priority than controlled names
// Found another solution, if the first one was "weak", report an error.
if result.0.def() != innermost_result.0.def() &&
(innermost_result.0.is_glob_import() ||
- innermost_result.0.expansion != Mark::root()) {
+ innermost_result.0.may_appear_after(invoc_id, result.0)) {
self.ambiguity_errors.push(AmbiguityError {
span: path_span,
name: ident.name,
}
fn resolve_legacy_scope(&mut self,
- invocation_legacy_scope: &'a Cell<LegacyScope<'a>>,
ident: Ident,
+ invoc_id: Mark,
+ invoc_parent_legacy_scope: &'a Cell<LegacyScope<'a>>,
record_used: bool)
-> Option<&'a NameBinding<'a>> {
let ident = ident.modern();
let mut innermost_result: Option<&NameBinding> = None;
// Go through all the scopes and try to resolve the name.
- let mut where_to_resolve = invocation_legacy_scope;
+ let mut where_to_resolve = invoc_parent_legacy_scope;
loop {
let result = match where_to_resolve.get() {
LegacyScope::Binding(legacy_binding) if ident == legacy_binding.ident =>
if let Some(innermost_result) = innermost_result {
// Found another solution, if the first one was "weak", report an error.
if result.def() != innermost_result.def() &&
- innermost_result.expansion != Mark::root() {
+ innermost_result.may_appear_after(invoc_id, result) {
self.ambiguity_errors.push(AmbiguityError {
span: ident.span,
name: ident.name,
}
}
- for &(mark, ident, kind, def) in module.legacy_macro_resolutions.borrow().iter() {
+ for &(invoc_id, ident, kind, def) in module.legacy_macro_resolutions.borrow().iter() {
let span = ident.span;
- let legacy_scope = &self.invocations[&mark].legacy_scope;
- let legacy_resolution = self.resolve_legacy_scope(legacy_scope, ident, true);
- let resolution = self.resolve_lexical_macro_path_segment(ident, MacroNS, true, true,
- kind == MacroKind::Attr, span);
+ let legacy_scope = &self.invocations[&invoc_id].legacy_scope;
+ let legacy_resolution = self.resolve_legacy_scope(ident, invoc_id, legacy_scope, true);
+ let resolution = self.resolve_lexical_macro_path_segment(
+ ident, MacroNS, invoc_id, true, true, kind == MacroKind::Attr, span
+ );
let check_consistency = |this: &Self, new_def: Def| {
if let Some(def) = def {
err.emit();
},
(Some(legacy_binding), Ok((binding, FromPrelude(from_prelude))))
- if !from_prelude || legacy_binding.expansion != Mark::root() => {
+ if !from_prelude || legacy_binding.may_appear_after(invoc_id, binding) => {
if legacy_binding.def_ignoring_ambiguity() != binding.def_ignoring_ambiguity() {
self.report_ambiguity_error(ident.name, span, legacy_binding, binding);
}