Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use the macro structure spans instead of the invocation #43352

Merged
merged 3 commits into from
Jul 22, 2017
Merged
Show file tree
Hide file tree
Changes from 2 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
1 change: 1 addition & 0 deletions src/libsyntax/ext/expand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1046,6 +1046,7 @@ impl<'feat> ExpansionConfig<'feat> {
}

// A Marker adds the given mark to the syntax context.
#[derive(Debug)]
pub struct Marker(pub Mark);

impl Folder for Marker {
Expand Down
15 changes: 14 additions & 1 deletion src/libsyntax/ext/tt/macro_rules.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,8 +119,21 @@ fn generic_extension<'cx>(cx: &'cx mut ExtCtxt,
quoted::TokenTree::Delimited(_, ref delimed) => delimed.tts.clone(),
_ => cx.span_bug(sp, "malformed macro rhs"),
};

// rhs has holes ( `$id` and `$(...)` that need filled)
let tts = transcribe(cx, Some(named_matches), rhs);
let mut tts = transcribe(cx, Some(named_matches), rhs.clone());
Copy link
Contributor

Choose a reason for hiding this comment

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

Just to be sure, everything is under Rc and cloning/mapping is cheap, right?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

All I need is the spans after this, so I'm cloning the spans first into their own Vec.


// Replace all the tokens for the corresponding positions in the macro, to maintain
// proper positions in error reporting, while maintaining the macro_backtrace.
if rhs.len() == tts.len() {
tts = tts.map_pos(|i, tt| {
let mut tt = tt.clone();
let mut sp = rhs[i].span();
sp.ctxt = tt.span().ctxt;
tt.set_span(sp);
tt
});
}

if cx.trace_macros() {
trace_macros_note(cx, sp, format!("to `{}`", tts));
Expand Down
2 changes: 1 addition & 1 deletion src/libsyntax/ext/tt/quoted.rs
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ impl TokenTree {
}
}

/// Retrieve the TokenTree's span.
/// Retrieve the `TokenTree`'s span.
pub fn span(&self) -> Span {
match *self {
TokenTree::Token(sp, _) |
Expand Down
8 changes: 3 additions & 5 deletions src/libsyntax/parse/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ fn maybe_append(mut lhs: Vec<Attribute>, rhs: Option<Vec<Attribute>>)
lhs
}

#[derive(Clone, Copy, PartialEq)]
#[derive(Debug, Clone, Copy, PartialEq)]
enum PrevTokenKind {
DocComment,
Comma,
Expand Down Expand Up @@ -6090,8 +6090,7 @@ impl<'a> Parser<'a> {
let (delim, tts) = self.expect_delimited_token_tree()?;
if delim != token::Brace {
if !self.eat(&token::Semi) {
let prev_span = self.prev_span;
self.span_err(prev_span,
self.span_err(self.prev_span,
"macros that expand to items must either \
be surrounded with braces or followed by \
a semicolon");
Expand All @@ -6108,8 +6107,7 @@ impl<'a> Parser<'a> {
match visibility {
Visibility::Inherited => {}
_ => {
let prev_span = self.prev_span;
return Err(self.span_fatal(prev_span, "unmatched visibility `pub`"));
return Err(self.span_fatal(self.prev_span, "unmatched visibility `pub`"));
}
}

Expand Down
32 changes: 32 additions & 0 deletions src/libsyntax/tokenstream.rs
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,15 @@ impl TokenTree {
}
}

/// Modify the `TokenTree`'s span inplace.
pub fn set_span(&mut self, span: Span) {
match *self {
TokenTree::Token(ref mut sp, _) | TokenTree::Delimited(ref mut sp, _) => {
*sp = span;
}
}
}

/// Indicates if the stream is a token that is equal to the provided token.
pub fn eq_token(&self, t: Token) -> bool {
match *self {
Expand Down Expand Up @@ -190,6 +199,14 @@ impl PartialEq<TokenStream> for TokenStream {
}

impl TokenStream {
pub fn len(&self) -> usize {
if let TokenStreamKind::Stream(ref slice) = self.kind {
slice.len()
} else {
0
}
}

pub fn empty() -> TokenStream {
TokenStream { kind: TokenStreamKind::Empty }
}
Expand Down Expand Up @@ -241,6 +258,21 @@ impl TokenStream {
}
}

pub fn map_pos<F: FnMut(usize, TokenTree) -> TokenTree>(self, mut f: F) -> TokenStream {
Copy link
Contributor

Choose a reason for hiding this comment

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

I'd rename this into enumerate_map (or map_enumerated), to use the same naming conventions as Iterator.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.

let mut trees = self.into_trees();
let mut result = Vec::new();
let mut i = 0;
while let Some(stream) = trees.next_as_stream() {
result.push(match stream.kind {
TokenStreamKind::Tree(tree) => f(i, tree).into(),
TokenStreamKind::JointTree(tree) => f(i, tree).joint(),
_ => unreachable!()
});
i += 1;
}
TokenStream::concat(result)
}

pub fn map<F: FnMut(TokenTree) -> TokenTree>(self, mut f: F) -> TokenStream {
let mut trees = self.into_trees();
let mut result = Vec::new();
Expand Down
28 changes: 24 additions & 4 deletions src/libsyntax_pos/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ impl Span {
if self.source_equal(&DUMMY_SP) { other } else { self }
}

/// Return true if `self` fully encloses `other`.
pub fn contains(self, other: Span) -> bool {
self.lo <= other.lo && other.hi <= self.hi
}
Expand Down Expand Up @@ -184,15 +185,32 @@ impl Span {
result
}

pub fn empty_ctxt(&self) -> bool {
Copy link
Contributor

Choose a reason for hiding this comment

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

This new function is unused.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Removed.

self.ctxt == SyntaxContext::empty()
}

/// Return a `Span` that would enclose both `self` and `end`.
pub fn to(self, end: Span) -> Span {
let lo = if self.lo < end.lo {
self.lo
} else {
end.lo
};
let hi = if self.hi > end.hi {
self.hi
} else {
end.hi
};
Copy link
Contributor

Choose a reason for hiding this comment

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

Probably better to use standard min and max for clarity.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.

// FIXME(jseyfried): self.ctxt should always equal end.ctxt here (c.f. issue #23480)
if self.ctxt == SyntaxContext::empty() {
Span { lo: self.lo, ..end }
let ctxt = if self.ctxt == SyntaxContext::empty() {
end.ctxt
} else {
Span { hi: end.hi, ..self }
}
self.ctxt
};
Span {lo, hi, ctxt}
}

/// Return a `Span` between the end of `self` to the beginning of `end`.
pub fn between(self, end: Span) -> Span {
Span {
lo: self.hi,
Expand All @@ -205,6 +223,7 @@ impl Span {
}
}

/// Return a `Span` between the beginning of `self` to the beginning of `end`.
pub fn until(self, end: Span) -> Span {
Span {
lo: self.lo,
Expand Down Expand Up @@ -852,6 +871,7 @@ pub struct FileLines {
thread_local!(pub static SPAN_DEBUG: Cell<fn(Span, &mut fmt::Formatter) -> fmt::Result> =
Cell::new(default_span_debug));

#[derive(Debug)]
pub struct MacroBacktrace {
/// span where macro was applied to generate this code
pub call_site: Span,
Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/did_you_mean/issue-31424.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ error[E0596]: cannot borrow immutable argument `self` as mutable
--> $DIR/issue-31424.rs:23:15
|
22 | fn bar(self: &mut Self) {
| ---- consider changing this to `mut self`
| --------------- consider changing this to `mut self: &mut Self`
23 | (&mut self).bar();
| ^^^^ cannot borrow mutably

Expand Down
19 changes: 19 additions & 0 deletions src/test/ui/span/macro-span-replacement.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

macro_rules! m {
($a:tt $b:tt) => {
$b $a;
}
}

fn main() {
m!(S struct);
}
11 changes: 11 additions & 0 deletions src/test/ui/span/macro-span-replacement.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
warning: struct is never used: `S`
--> $DIR/macro-span-replacement.rs:13:9
|
13 | $b $a;
| ^^^^^^
...
18 | m!(S struct);
| ------------- in this macro invocation
|
= note: #[warn(dead_code)] on by default