about summary refs log tree commit diff
diff options
context:
space:
mode:
authorJeffrey Seyfried <jeffrey.seyfried@gmail.com>2016-10-31 22:17:15 +0000
committerJeffrey Seyfried <jeffrey.seyfried@gmail.com>2016-11-02 07:42:37 +0000
commit076c5d445b7611995a8d7e26e94c327a79eb20e2 (patch)
tree9b414cc6ee85ef62c7b2c7dd33109ecdc6cd78ad
parent6c4b551403624b064c4a5836dfa59971a215cf4a (diff)
downloadrust-076c5d445b7611995a8d7e26e94c327a79eb20e2.tar.gz
rust-076c5d445b7611995a8d7e26e94c327a79eb20e2.zip
Fix shadowing checking.
-rw-r--r--src/librustc_resolve/lib.rs10
-rw-r--r--src/librustc_resolve/macros.rs19
2 files changed, 21 insertions, 8 deletions
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<Name>,
     builtin_macros: FnvHashMap<Name, Rc<SyntaxExtension>>,
+    lexical_macro_resolutions: Vec<(Name, LegacyScope<'a>)>,
 
     // Maps the `Mark` of an expansion to its containing module or block.
     invocations: FnvHashMap<Mark, &'a InvocationData<'a>>,
@@ -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<Rc<SyntaxExtension>> {
+        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()
     }