Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/libproc_macro/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,7 @@ impl Span {
/// `self` was generated from, if any.
#[unstable(feature = "proc_macro", issue = "38356")]
pub fn parent(&self) -> Option<Span> {
self.0.ctxt().outer().expn_info().map(|i| Span(i.call_site))
self.0.parent().map(|x| { Span(x) })
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: .map(Span)

}

/// The span for the origin source code that `self` was generated from. If
Expand Down
43 changes: 43 additions & 0 deletions src/libsyntax_pos/hygiene.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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).
Expand Down Expand Up @@ -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 {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe least_ancestor for clarity and symmetry with the is_descendant_of? (I'd probably call this join if it were math)

HygieneData::with(|data| {
// Compute the path from a to the root
let mut a_path = FxHashSet::<Mark>();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice, O(n) :)

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;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: two spaces after =

}

b
})
}
}

pub struct HygieneData {
Expand Down Expand Up @@ -238,6 +265,22 @@ impl SyntaxContext {
})
}

/// Pulls a single mark off of the syntax context. This effectively moves the
/// context up one macro definition level. That is, if we have a nested macro
/// definition as follows:
///
/// ```rust
/// macro_rules! f {
/// macro_rules! g {
/// ...
/// }
/// }
/// ```
///
/// and we have a SyntaxContext that is referring to something declared by an invocation
/// of g (call it g1), calling remove_mark will result in the SyntaxContext for the
/// invocation of f that created g1.
/// Returns the mark that was removed.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

pub fn remove_mark(&mut self) -> Mark {
HygieneData::with(|data| {
let outer_mark = data.syntax_contexts[self.0 as usize].outer_mark;
Expand Down
6 changes: 6 additions & 0 deletions src/libsyntax_pos/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,12 @@ impl Span {
self.ctxt().outer().expn_info().map(|info| info.call_site.source_callsite()).unwrap_or(self)
}

/// The `Span for the tokens in the previous macro expansion from which `self` was generated,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: `Span

/// if any
pub fn parent(self) -> Option<Span> {
self.ctxt().outer().expn_info().map(|i| i.call_site)
}

/// Return the source callee.
///
/// Returns None if the supplied span has no expansion trace,
Expand Down