Feature gate macro arguments
Uses the same approach as https://github.com/rust-lang/rust/pull/17286 (and subsequent changes making it more correct), where the visitor will skip any pieces of the AST that are from "foreign code", where the spans don't line up, indicating that that piece of code is due to a macro expansion. If this breaks your code, read the error message to determine which feature gate you should add to your crate, and bask in the knowledge that your code won't mysteriously break should you try to use the 1.0 release. Closes #18102 [breaking-change]
This commit is contained in:
@@ -563,6 +563,38 @@ impl CodeMap {
|
||||
ExpnId(i) => f(Some(&(*self.expansions.borrow())[i as uint]))
|
||||
}
|
||||
}
|
||||
|
||||
/// Check if a span is "internal" to a macro. This means that it is entirely generated by a
|
||||
/// macro expansion and contains no code that was passed in as an argument.
|
||||
pub fn span_is_internal(&self, span: Span) -> bool {
|
||||
// first, check if the given expression was generated by a macro or not
|
||||
// we need to go back the expn_info tree to check only the arguments
|
||||
// of the initial macro call, not the nested ones.
|
||||
let mut is_internal = false;
|
||||
let mut expnid = span.expn_id;
|
||||
while self.with_expn_info(expnid, |expninfo| {
|
||||
match expninfo {
|
||||
Some(ref info) => {
|
||||
// save the parent expn_id for next loop iteration
|
||||
expnid = info.call_site.expn_id;
|
||||
if info.callee.span.is_none() {
|
||||
// it's a compiler built-in, we *really* don't want to mess with it
|
||||
// so we skip it, unless it was called by a regular macro, in which case
|
||||
// we will handle the caller macro next turn
|
||||
is_internal = true;
|
||||
true // continue looping
|
||||
} else {
|
||||
// was this expression from the current macro arguments ?
|
||||
is_internal = !( span.lo > info.call_site.lo &&
|
||||
span.hi < info.call_site.hi );
|
||||
true // continue looping
|
||||
}
|
||||
},
|
||||
_ => false // stop looping
|
||||
}
|
||||
}) { /* empty while loop body */ }
|
||||
return is_internal;
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
Reference in New Issue
Block a user