diff options
| author | bobtwinkles <srkoser+GitHub@gmail.com> | 2018-04-21 18:20:17 -0400 |
|---|---|---|
| committer | bobtwinkles <srkoser+GitHub@gmail.com> | 2018-04-23 23:59:59 -0400 |
| commit | 498dbe44537998bd4bba6c28232a22e9243b9c67 (patch) | |
| tree | b9daa240c0fac918c2761e682647d14c5dfa81eb | |
| parent | 263b36b071ba8b52cd4f79ca36494b05d4762430 (diff) | |
| download | rust-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.rs | 27 |
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 { |
