about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc_resolve/lib.rs4
-rw-r--r--src/libsyntax_pos/hygiene.rs21
2 files changed, 20 insertions, 5 deletions
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index c05b69ab44f..f9cf95a873f 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -2308,7 +2308,7 @@ impl<'a> Resolver<'a> {
 
     fn hygienic_lexical_parent(&mut self, module: Module<'a>, span: &mut Span)
                                -> Option<Module<'a>> {
-        if !module.expansion.is_descendant_of(span.ctxt().outer()) {
+        if !module.expansion.outer_is_descendant_of(span.ctxt()) {
             return Some(self.macro_def_scope(span.remove_mark()));
         }
 
@@ -2344,7 +2344,7 @@ impl<'a> Resolver<'a> {
             module.expansion.is_descendant_of(parent.expansion) {
                 // The macro is a proc macro derive
                 if module.expansion.looks_like_proc_macro_derive() {
-                    if parent.expansion.is_descendant_of(span.ctxt().outer()) {
+                    if parent.expansion.outer_is_descendant_of(span.ctxt()) {
                         *poisoned = Some(node_id);
                         return module.parent;
                     }
diff --git a/src/libsyntax_pos/hygiene.rs b/src/libsyntax_pos/hygiene.rs
index e8dcd8171c9..3ffeaf43b85 100644
--- a/src/libsyntax_pos/hygiene.rs
+++ b/src/libsyntax_pos/hygiene.rs
@@ -124,6 +124,21 @@ impl Mark {
         })
     }
 
+    /// `mark.outer_is_descendant_of(ctxt)` is equivalent to but faster than
+    /// `mark.is_descendant_of(ctxt.outer())`.
+    pub fn outer_is_descendant_of(mut self, ctxt: SyntaxContext) -> bool {
+        HygieneData::with(|data| {
+            let outer = data.syntax_contexts[ctxt.0 as usize].outer_mark;
+            while self != outer {
+                if self == Mark::root() {
+                    return false;
+                }
+                self = data.marks[self.0 as usize].parent;
+            }
+            true
+        })
+    }
+
     /// Computes a mark such that both input marks are descendants of (or equal to) the returned
     /// mark. That is, the following holds:
     ///
@@ -416,7 +431,7 @@ impl SyntaxContext {
     /// or `None` if we privacy check as usual (i.e., not w.r.t. a macro definition scope).
     pub fn adjust(&mut self, expansion: Mark) -> Option<Mark> {
         let mut scope = None;
-        while !expansion.is_descendant_of(self.outer()) {
+        while !expansion.outer_is_descendant_of(*self) {
             scope = Some(self.remove_mark());
         }
         scope
@@ -450,7 +465,7 @@ impl SyntaxContext {
     pub fn glob_adjust(&mut self, expansion: Mark, mut glob_ctxt: SyntaxContext)
                        -> Option<Option<Mark>> {
         let mut scope = None;
-        while !expansion.is_descendant_of(glob_ctxt.outer()) {
+        while !expansion.outer_is_descendant_of(glob_ctxt) {
             scope = Some(glob_ctxt.remove_mark());
             if self.remove_mark() != scope.unwrap() {
                 return None;
@@ -476,7 +491,7 @@ impl SyntaxContext {
         }
 
         let mut marks = Vec::new();
-        while !expansion.is_descendant_of(glob_ctxt.outer()) {
+        while !expansion.outer_is_descendant_of(glob_ctxt) {
             marks.push(glob_ctxt.remove_mark());
         }