Skip to content

Commit 498dbe4

Browse files
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
1 parent 263b36b commit 498dbe4

File tree

1 file changed

+27
-0
lines changed

1 file changed

+27
-0
lines changed

src/libsyntax_pos/hygiene.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ use symbol::{Ident, Symbol};
2121

2222
use serialize::{Encodable, Decodable, Encoder, Decoder};
2323
use std::collections::HashMap;
24+
use rustc_data_structures::fx::FxHashSet;
2425
use std::fmt;
2526

2627
/// A SyntaxContext represents a chain of macro expansions (represented by marks).
@@ -117,6 +118,32 @@ impl Mark {
117118
true
118119
})
119120
}
121+
122+
/// Computes a mark such that both input marks are descendants of (or equal to) the returned
123+
/// mark. That is, the following holds:
124+
///
125+
/// ```rust
126+
/// let lub = lub(a, b);
127+
/// assert!(a.is_descendant_of(lub))
128+
/// assert!(b.is_descendant_of(lub))
129+
/// ```
130+
pub fn lub(mut a: Mark, mut b: Mark) -> Mark {
131+
HygieneData::with(|data| {
132+
// Compute the path from a to the root
133+
let mut a_path = FxHashSet::<Mark>();
134+
while a != Mark::root() {
135+
a_path.insert(a);
136+
a = data.marks[a.0 as usize].parent;
137+
}
138+
139+
// While the path from b to the root hasn't intersected, move up the tree
140+
while !a_path.contains(&b) {
141+
b = data.marks[b.0 as usize].parent;
142+
}
143+
144+
b
145+
})
146+
}
120147
}
121148

122149
pub struct HygieneData {

0 commit comments

Comments
 (0)