Skip to content

Commit 35f6499

Browse files
committed
Auto merge of #43352 - estebank:macro-span-replacement, r=petrochenkov
Use the macro structure spans instead of the invocation Fix #42104, CC #2887.
2 parents e49a948 + 6772661 commit 35f6499

File tree

9 files changed

+97
-13
lines changed

9 files changed

+97
-13
lines changed

Diff for: src/libsyntax/ext/expand.rs

+1
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 {

Diff for: src/libsyntax/ext/tt/macro_rules.rs

+15-1
Original file line numberDiff line numberDiff line change
@@ -119,8 +119,22 @@ 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+
123+
let rhs_spans = rhs.iter().map(|t| t.span()).collect::<Vec<_>>();
122124
// rhs has holes ( `$id` and `$(...)` that need filled)
123-
let tts = transcribe(cx, Some(named_matches), rhs);
125+
let mut tts = transcribe(cx, Some(named_matches), rhs);
126+
127+
// Replace all the tokens for the corresponding positions in the macro, to maintain
128+
// proper positions in error reporting, while maintaining the macro_backtrace.
129+
if rhs_spans.len() == tts.len() {
130+
tts = tts.map_enumerated(|i, tt| {
131+
let mut tt = tt.clone();
132+
let mut sp = rhs_spans[i];
133+
sp.ctxt = tt.span().ctxt;
134+
tt.set_span(sp);
135+
tt
136+
});
137+
}
124138

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

Diff for: src/libsyntax/ext/tt/quoted.rs

+1-1
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, _) |

Diff for: src/libsyntax/parse/parser.rs

+3-5
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

Diff for: src/libsyntax/tokenstream.rs

+32
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_enumerated<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();

Diff for: src/libsyntax_pos/lib.rs

+14-5
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,21 @@ impl Span {
184185
result
185186
}
186187

188+
/// Return a `Span` that would enclose both `self` and `end`.
187189
pub fn to(self, end: Span) -> Span {
188-
// 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 }
191-
} else {
192-
Span { hi: end.hi, ..self }
190+
Span {
191+
lo: cmp::min(self.lo, end.lo),
192+
hi: cmp::max(self.hi, end.hi),
193+
// FIXME(jseyfried): self.ctxt should always equal end.ctxt here (c.f. issue #23480)
194+
ctxt: if self.ctxt == SyntaxContext::empty() {
195+
end.ctxt
196+
} else {
197+
self.ctxt
198+
},
193199
}
194200
}
195201

202+
/// Return a `Span` between the end of `self` to the beginning of `end`.
196203
pub fn between(self, end: Span) -> Span {
197204
Span {
198205
lo: self.hi,
@@ -205,6 +212,7 @@ impl Span {
205212
}
206213
}
207214

215+
/// Return a `Span` between the beginning of `self` to the beginning of `end`.
208216
pub fn until(self, end: Span) -> Span {
209217
Span {
210218
lo: self.lo,
@@ -852,6 +860,7 @@ pub struct FileLines {
852860
thread_local!(pub static SPAN_DEBUG: Cell<fn(Span, &mut fmt::Formatter) -> fmt::Result> =
853861
Cell::new(default_span_debug));
854862

863+
#[derive(Debug)]
855864
pub struct MacroBacktrace {
856865
/// span where macro was applied to generate this code
857866
pub call_site: Span,

Diff for: src/test/ui/did_you_mean/issue-31424.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ error[E0596]: cannot borrow immutable argument `self` as mutable
1111
--> $DIR/issue-31424.rs:23:15
1212
|
1313
22 | fn bar(self: &mut Self) {
14-
| ---- consider changing this to `mut self`
14+
| --------------- consider changing this to `mut self: &mut Self`
1515
23 | (&mut self).bar();
1616
| ^^^^ cannot borrow mutably
1717

Diff for: src/test/ui/span/macro-span-replacement.rs

+19
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+
}

Diff for: src/test/ui/span/macro-span-replacement.stderr

+11
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)