diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index fcd299b56b0..e7d83a64e03 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -77,7 +77,7 @@ use std::mem::replace; use std::rc::Rc; use resolve_imports::{ImportDirective, NameResolution}; -use macros::{InvocationData, LegacyBinding}; +use macros::{InvocationData, LegacyBinding, LegacyScope}; // NB: This module needs to be declared first so diagnostics are // registered before they are used. @@ -1077,6 +1077,7 @@ pub struct Resolver<'a> { crate_loader: &'a mut CrateLoader, macro_names: FnvHashSet, builtin_macros: FnvHashMap>, + lexical_macro_resolutions: Vec<(Name, LegacyScope<'a>)>, // Maps the `Mark` of an expansion to its containing module or block. invocations: FnvHashMap>, @@ -1267,6 +1268,7 @@ impl<'a> Resolver<'a> { crate_loader: crate_loader, macro_names: FnvHashSet(), builtin_macros: FnvHashMap(), + lexical_macro_resolutions: Vec::new(), invocations: invocations, } } @@ -3363,9 +3365,13 @@ impl<'a> Resolver<'a> { } fn report_shadowing_errors(&mut self) { + for (name, scope) in replace(&mut self.lexical_macro_resolutions, Vec::new()) { + self.resolve_macro_name(scope, name); + } + let mut reported_errors = FnvHashSet(); for binding in replace(&mut self.disallowed_shadowing, Vec::new()) { - if self.resolve_macro_name(binding.parent, binding.name, false).is_some() && + if self.resolve_macro_name(binding.parent, binding.name).is_some() && reported_errors.insert((binding.name, binding.span)) { let msg = format!("`{}` is already in scope", binding.name); self.session.struct_span_err(binding.span, &msg) diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index eb72145b774..356158e58da 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -174,7 +174,7 @@ impl<'a> base::Resolver for Resolver<'a> { if let LegacyScope::Expansion(parent) = invocation.legacy_scope.get() { invocation.legacy_scope.set(LegacyScope::simplify_expansion(parent)); } - self.resolve_macro_name(invocation.legacy_scope.get(), name, true).ok_or_else(|| { + self.resolve_macro_name(invocation.legacy_scope.get(), name).ok_or_else(|| { if force { let msg = format!("macro undefined: '{}!'", name); let mut err = self.session.struct_span_err(path.span, &msg); @@ -189,17 +189,18 @@ impl<'a> base::Resolver for Resolver<'a> { } impl<'a> Resolver<'a> { - pub fn resolve_macro_name(&mut self, - mut scope: LegacyScope<'a>, - name: ast::Name, - record_used: bool) + pub fn resolve_macro_name(&mut self, mut scope: LegacyScope<'a>, name: ast::Name) -> Option> { + let mut possible_time_travel = None; let mut relative_depth: u32 = 0; loop { scope = match scope { LegacyScope::Empty => break, LegacyScope::Expansion(invocation) => { if let LegacyScope::Empty = invocation.expansion.get() { + if possible_time_travel.is_none() { + possible_time_travel = Some(scope); + } invocation.legacy_scope.get() } else { relative_depth += 1; @@ -212,7 +213,10 @@ impl<'a> Resolver<'a> { } LegacyScope::Binding(binding) => { if binding.name == name { - if record_used && relative_depth > 0 { + if let Some(scope) = possible_time_travel { + // Check for disallowed shadowing later + self.lexical_macro_resolutions.push((name, scope)); + } else if relative_depth > 0 { self.disallowed_shadowing.push(binding); } return Some(binding.ext.clone()); @@ -222,6 +226,9 @@ impl<'a> Resolver<'a> { }; } + if let Some(scope) = possible_time_travel { + self.lexical_macro_resolutions.push((name, scope)); + } self.builtin_macros.get(&name).cloned() }