Skip to content

Commit e99d309

Browse files
committed
Use the macro structure spans instead of the invocation
1 parent cc80053 commit e99d309

File tree

8 files changed

+105
-11
lines changed

8 files changed

+105
-11
lines changed

src/libsyntax/ext/expand.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1046,6 +1046,7 @@ impl<'feat> ExpansionConfig<'feat> {
10461046
}
10471047

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

10511052
impl Folder for Marker {

src/libsyntax/ext/tt/macro_rules.rs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,8 +119,21 @@ fn generic_extension<'cx>(cx: &'cx mut ExtCtxt,
119119
quoted::TokenTree::Delimited(_, ref delimed) => delimed.tts.clone(),
120120
_ => cx.span_bug(sp, "malformed macro rhs"),
121121
};
122+
122123
// rhs has holes ( `$id` and `$(...)` that need filled)
123-
let tts = transcribe(cx, Some(named_matches), rhs);
124+
let mut tts = transcribe(cx, Some(named_matches), rhs.clone());
125+
126+
// Replace all the tokens for the corresponding positions in the macro, to maintain
127+
// proper positions in error reporting, while maintaining the macro_backtrace.
128+
if rhs.len() == tts.len() {
129+
tts = tts.map_pos(|i, tt| {
130+
let mut tt = tt.clone();
131+
let mut sp = rhs[i].span();
132+
sp.ctxt = tt.span().ctxt;
133+
tt.set_span(sp);
134+
tt
135+
});
136+
}
124137

125138
if cx.trace_macros() {
126139
trace_macros_note(cx, sp, format!("to `{}`", tts));

src/libsyntax/ext/tt/quoted.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ impl TokenTree {
128128
}
129129
}
130130

131-
/// Retrieve the TokenTree's span.
131+
/// Retrieve the `TokenTree`'s span.
132132
pub fn span(&self) -> Span {
133133
match *self {
134134
TokenTree::Token(sp, _) |

src/libsyntax/parse/parser.rs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ fn maybe_append(mut lhs: Vec<Attribute>, rhs: Option<Vec<Attribute>>)
150150
lhs
151151
}
152152

153-
#[derive(Clone, Copy, PartialEq)]
153+
#[derive(Debug, Clone, Copy, PartialEq)]
154154
enum PrevTokenKind {
155155
DocComment,
156156
Comma,
@@ -6090,8 +6090,7 @@ impl<'a> Parser<'a> {
60906090
let (delim, tts) = self.expect_delimited_token_tree()?;
60916091
if delim != token::Brace {
60926092
if !self.eat(&token::Semi) {
6093-
let prev_span = self.prev_span;
6094-
self.span_err(prev_span,
6093+
self.span_err(self.prev_span,
60956094
"macros that expand to items must either \
60966095
be surrounded with braces or followed by \
60976096
a semicolon");
@@ -6108,8 +6107,7 @@ impl<'a> Parser<'a> {
61086107
match visibility {
61096108
Visibility::Inherited => {}
61106109
_ => {
6111-
let prev_span = self.prev_span;
6112-
return Err(self.span_fatal(prev_span, "unmatched visibility `pub`"));
6110+
return Err(self.span_fatal(self.prev_span, "unmatched visibility `pub`"));
61136111
}
61146112
}
61156113

src/libsyntax/tokenstream.rs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,15 @@ impl TokenTree {
131131
}
132132
}
133133

134+
/// Modify the `TokenTree`'s span inplace.
135+
pub fn set_span(&mut self, span: Span) {
136+
match *self {
137+
TokenTree::Token(ref mut sp, _) | TokenTree::Delimited(ref mut sp, _) => {
138+
*sp = span;
139+
}
140+
}
141+
}
142+
134143
/// Indicates if the stream is a token that is equal to the provided token.
135144
pub fn eq_token(&self, t: Token) -> bool {
136145
match *self {
@@ -190,6 +199,14 @@ impl PartialEq<TokenStream> for TokenStream {
190199
}
191200

192201
impl TokenStream {
202+
pub fn len(&self) -> usize {
203+
if let TokenStreamKind::Stream(ref slice) = self.kind {
204+
slice.len()
205+
} else {
206+
0
207+
}
208+
}
209+
193210
pub fn empty() -> TokenStream {
194211
TokenStream { kind: TokenStreamKind::Empty }
195212
}
@@ -241,6 +258,21 @@ impl TokenStream {
241258
}
242259
}
243260

261+
pub fn map_pos<F: FnMut(usize, TokenTree) -> TokenTree>(self, mut f: F) -> TokenStream {
262+
let mut trees = self.into_trees();
263+
let mut result = Vec::new();
264+
let mut i = 0;
265+
while let Some(stream) = trees.next_as_stream() {
266+
result.push(match stream.kind {
267+
TokenStreamKind::Tree(tree) => f(i, tree).into(),
268+
TokenStreamKind::JointTree(tree) => f(i, tree).joint(),
269+
_ => unreachable!()
270+
});
271+
i += 1;
272+
}
273+
TokenStream::concat(result)
274+
}
275+
244276
pub fn map<F: FnMut(TokenTree) -> TokenTree>(self, mut f: F) -> TokenStream {
245277
let mut trees = self.into_trees();
246278
let mut result = Vec::new();

src/libsyntax_pos/lib.rs

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ impl Span {
100100
if self.source_equal(&DUMMY_SP) { other } else { self }
101101
}
102102

103+
/// Return true if `self` fully encloses `other`.
103104
pub fn contains(self, other: Span) -> bool {
104105
self.lo <= other.lo && other.hi <= self.hi
105106
}
@@ -184,15 +185,32 @@ impl Span {
184185
result
185186
}
186187

188+
pub fn empty_ctxt(&self) -> bool {
189+
self.ctxt == SyntaxContext::empty()
190+
}
191+
192+
/// Return a `Span` that would enclose both `self` and `end`.
187193
pub fn to(self, end: Span) -> Span {
194+
let lo = if self.lo < end.lo {
195+
self.lo
196+
} else {
197+
end.lo
198+
};
199+
let hi = if self.hi > end.hi {
200+
self.hi
201+
} else {
202+
end.hi
203+
};
188204
// FIXME(jseyfried): self.ctxt should always equal end.ctxt here (c.f. issue #23480)
189-
if self.ctxt == SyntaxContext::empty() {
190-
Span { lo: self.lo, ..end }
205+
let ctxt = if self.ctxt == SyntaxContext::empty() {
206+
end.ctxt
191207
} else {
192-
Span { hi: end.hi, ..self }
193-
}
208+
self.ctxt
209+
};
210+
Span {lo, hi, ctxt}
194211
}
195212

213+
/// Return a `Span` between the end of `self` to the beginning of `end`.
196214
pub fn between(self, end: Span) -> Span {
197215
Span {
198216
lo: self.hi,
@@ -205,6 +223,7 @@ impl Span {
205223
}
206224
}
207225

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

874+
#[derive(Debug)]
855875
pub struct MacroBacktrace {
856876
/// span where macro was applied to generate this code
857877
pub call_site: Span,
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
macro_rules! m {
12+
($a:tt $b:tt) => {
13+
$b $a;
14+
}
15+
}
16+
17+
fn main() {
18+
m!(S struct);
19+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
warning: struct is never used: `S`
2+
--> $DIR/macro-span-replacement.rs:13:9
3+
|
4+
13 | $b $a;
5+
| ^^^^^^
6+
...
7+
18 | m!(S struct);
8+
| ------------- in this macro invocation
9+
|
10+
= note: #[warn(dead_code)] on by default
11+

0 commit comments

Comments
 (0)