about summary refs log tree commit diff
path: root/src/libsyntax_pos
diff options
context:
space:
mode:
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 {