about summary refs log tree commit diff
path: root/src/libsyntax_pos
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 /src/libsyntax_pos
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
Diffstat (limited to 'src/libsyntax_pos')
-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 {