about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbobtwinkles <srkoser+GitHub@gmail.com>2018-04-21 18:20:17 -0400
committerbobtwinkles <srkoser+GitHub@gmail.com>2018-04-23 23:59:59 -0400
commit498dbe44537998bd4bba6c28232a22e9243b9c67 (patch)
treeb9daa240c0fac918c2761e682647d14c5dfa81eb
parent263b36b071ba8b52cd4f79ca36494b05d4762430 (diff)
downloadrust-498dbe44537998bd4bba6c28232a22e9243b9c67.tar.gz
rust-498dbe44537998bd4bba6c28232a22e9243b9c67.zip
Implement a least upper bound for marks.
This is useful when trying to compute when something is lexically before
something else, but they aren't necessarily in the same SyntaxContext
-rw-r--r--src/libsyntax_pos/hygiene.rs27
1 files changed, 27 insertions, 0 deletions
diff --git a/src/libsyntax_pos/hygiene.rs b/src/libsyntax_pos/hygiene.rs
index 6eb662744c3..8e9564d0ac1 100644
--- a/src/libsyntax_pos/hygiene.rs
+++ b/src/libsyntax_pos/hygiene.rs
@@ -21,6 +21,7 @@ use symbol::{Ident, Symbol};
 
 use serialize::{Encodable, Decodable, Encoder, Decoder};
 use std::collections::HashMap;
+use rustc_data_structures::fx::FxHashSet;
 use std::fmt;
 
 /// A SyntaxContext represents a chain of macro expansions (represented by marks).
@@ -117,6 +118,32 @@ impl Mark {
             true
         })
     }
+
+    /// Computes a mark such that both input marks are descendants of (or equal to) the returned
+    /// mark. That is, the following holds:
+    ///
+    /// ```rust
+    /// let lub = lub(a, b);
+    /// assert!(a.is_descendant_of(lub))
+    /// assert!(b.is_descendant_of(lub))
+    /// ```
+    pub fn lub(mut a: Mark, mut b: Mark) -> Mark {
+        HygieneData::with(|data| {
+            // Compute the path from a to the root
+            let mut a_path = FxHashSet::<Mark>();
+            while a != Mark::root() {
+                a_path.insert(a);
+                a = data.marks[a.0 as usize].parent;
+            }
+
+            // While the path from b to the root hasn't intersected, move up the tree
+            while !a_path.contains(&b) {
+                b =  data.marks[b.0 as usize].parent;
+            }
+
+            b
+        })
+    }
 }
 
 pub struct HygieneData {