Skip to content

Commit

Permalink
Minimize weird spans involving macro context
Browse files Browse the repository at this point in the history
Sometimes the parser attempts to synthesize spans from within a macro
context with the span for the captured argument, leading to non-sensical
spans with very bad output. Given that an incorrect span is worse than
a partially incomplete span, when detecting this situation return only
one of the spans without mergin them.
  • Loading branch information
estebank committed Feb 1, 2018
1 parent bacb5c5 commit aaec608
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 8 deletions.
23 changes: 17 additions & 6 deletions src/libsyntax_pos/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -361,13 +361,24 @@ impl Span {

/// Return a `Span` that would enclose both `self` and `end`.
pub fn to(self, end: Span) -> Span {
let span = self.data();
let end = end.data();
let span_data = self.data();
let end_data = end.data();
// FIXME(jseyfried): self.ctxt should always equal end.ctxt here (c.f. issue #23480)
// Return the macro span on its own to avoid weird diagnostic output. It is preferable to
// have an incomplete span than a completely nonsensical one.
if span_data.ctxt != end_data.ctxt {
if span_data.ctxt == SyntaxContext::empty() {
return end;
} else if end_data.ctxt == SyntaxContext::empty() {
return self;
}
// both span fall within a macro
// FIXME(estebank) check if it is the *same* macro
}
Span::new(
cmp::min(span.lo, end.lo),
cmp::max(span.hi, end.hi),
// FIXME(jseyfried): self.ctxt should always equal end.ctxt here (c.f. issue #23480)
if span.ctxt == SyntaxContext::empty() { end.ctxt } else { span.ctxt },
cmp::min(span_data.lo, end_data.lo),
cmp::max(span_data.hi, end_data.hi),
if span_data.ctxt == SyntaxContext::empty() { end_data.ctxt } else { span_data.ctxt },
)
}

Expand Down
23 changes: 23 additions & 0 deletions src/test/ui/macros/span-covering-argument-1.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// Copyright 2018 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! bad {
($s:ident whatever) => {
{
let $s = 0;
*&mut $s = 0;
//~^ ERROR cannot borrow immutable local variable `foo` as mutable [E0596]
}
}
}

fn main() {
bad!(foo whatever);
}
13 changes: 13 additions & 0 deletions src/test/ui/macros/span-covering-argument-1.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
error[E0596]: cannot borrow immutable local variable `foo` as mutable
--> $DIR/span-covering-argument-1.rs:15:19
|
14 | let $s = 0;
| -- consider changing this to `mut $s`
15 | *&mut $s = 0;
| ^^ cannot borrow mutably
...
22 | bad!(foo whatever);
| ------------------- in this macro invocation

error: aborting due to previous error

4 changes: 2 additions & 2 deletions src/test/ui/span/macro-span-replacement.stderr
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
warning: struct is never used: `S`
--> $DIR/macro-span-replacement.rs:17:9
--> $DIR/macro-span-replacement.rs:17:14
|
17 | $b $a; //~ WARN struct is never used
| ^^^^^^
| ^
...
22 | m!(S struct);
| ------------- in this macro invocation
Expand Down

0 comments on commit aaec608

Please sign in to comment.