about summary refs log tree commit diff
diff options
context:
space:
mode:
authorJeffrey Seyfried <jeffrey.seyfried@gmail.com>2016-10-08 00:30:24 +0000
committerJeffrey Seyfried <jeffrey.seyfried@gmail.com>2016-10-10 09:35:25 +0000
commit53fd3b0acc42c8c038382bcbc5e4ba7869178228 (patch)
treef4c5b90d6f01f8ae1a0372aa4e4769cb79ff15aa
parentfbc96e18ad0c2a3f5be7e4ef003c720146b0a52d (diff)
downloadrust-53fd3b0acc42c8c038382bcbc5e4ba7869178228.tar.gz
rust-53fd3b0acc42c8c038382bcbc5e4ba7869178228.zip
Avoid quadratic complexity.
-rw-r--r--src/librustc_resolve/macros.rs20
1 files changed, 18 insertions, 2 deletions
diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs
index 31b0180f6f1..4ee07036edb 100644
--- a/src/librustc_resolve/macros.rs
+++ b/src/librustc_resolve/macros.rs
@@ -60,6 +60,19 @@ pub enum LegacyScope<'a> {
     Binding(&'a LegacyBinding<'a>),
 }
 
+impl<'a> LegacyScope<'a> {
+    fn simplify_expansion(mut invoc: &'a InvocationData<'a>) -> Self {
+        while let LegacyScope::Invocation(_) = invoc.expansion.get() {
+            match invoc.legacy_scope.get() {
+                LegacyScope::Expansion(new_invoc) => invoc = new_invoc,
+                LegacyScope::Binding(_) => break,
+                scope @ _ => return scope,
+            }
+        }
+        LegacyScope::Expansion(invoc)
+    }
+}
+
 pub struct LegacyBinding<'a> {
     parent: LegacyScope<'a>,
     kind: LegacyBindingKind,
@@ -175,8 +188,11 @@ impl<'a> base::Resolver for Resolver<'a> {
             InvocationKind::Attr { ref attr, .. } => (intern(&*attr.name()), attr.span),
         };
 
-        let scope = self.invocations[&scope].legacy_scope.get();
-        self.resolve_macro_name(scope, name, true).or_else(|| {
+        let invocation = self.invocations[&scope];
+        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).or_else(|| {
             let mut err =
                 self.session.struct_span_err(span, &format!("macro undefined: '{}!'", name));
             self.suggest_macro_name(&name.as_str(), &mut err);