Skip to content

Commit cc5be28

Browse files
committed
Use more precise span when reporting semicolon hint
When reporting "consider removing this semicolon" hint message, the offending semicolon may come from macro call site instead of macro itself. Using the more appropriate span makes the hint more helpful. Closes rust-lang#13428.
1 parent ce2bab6 commit cc5be28

File tree

5 files changed

+54
-18
lines changed

5 files changed

+54
-18
lines changed

src/librustc/middle/liveness.rs

+5-4
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ use std::rc::Rc;
117117
use std::str;
118118
use std::uint;
119119
use syntax::ast::*;
120-
use syntax::codemap::Span;
120+
use syntax::codemap::{BytePos, original_sp, Span};
121121
use syntax::parse::token::special_idents;
122122
use syntax::parse::token;
123123
use syntax::print::pprust::{expr_to_str, block_to_str};
@@ -1473,10 +1473,11 @@ impl<'a> Liveness<'a> {
14731473
};
14741474
if ends_with_stmt {
14751475
let last_stmt = body.stmts.last().unwrap();
1476+
let original_span = original_sp(last_stmt.span, sp);
14761477
let span_semicolon = Span {
1477-
lo: last_stmt.span.hi,
1478-
hi: last_stmt.span.hi,
1479-
expn_info: last_stmt.span.expn_info
1478+
lo: original_span.hi - BytePos(1),
1479+
hi: original_span.hi,
1480+
expn_info: original_span.expn_info
14801481
};
14811482
self.ir.tcx.sess.span_note(
14821483
span_semicolon, "consider removing this semicolon:");

src/libsyntax/codemap.rs

+11
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,17 @@ pub fn mk_sp(lo: BytePos, hi: BytePos) -> Span {
141141
Span {lo: lo, hi: hi, expn_info: None}
142142
}
143143

144+
/// Return the span itself if it doesn't come from a macro expansion,
145+
/// otherwise return the call site span up to the `enclosing_sp` by
146+
/// following the `expn_info` chain.
147+
pub fn original_sp(sp: Span, enclosing_sp: Span) -> Span {
148+
match (sp.expn_info, enclosing_sp.expn_info) {
149+
(None, _) => sp,
150+
(Some(expn1), Some(expn2)) if expn1.call_site == expn2.call_site => sp,
151+
(Some(expn1), _) => original_sp(expn1.call_site, enclosing_sp),
152+
}
153+
}
154+
144155
/// A source code location used for error reporting
145156
pub struct Loc {
146157
/// Information about the original source

src/libsyntax/parse/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -686,7 +686,7 @@ mod test {
686686
}),
687687
span: sp(17,18)},
688688
ast::DUMMY_NODE_ID),
689-
span: sp(17,18)}),
689+
span: sp(17,19)}),
690690
expr: None,
691691
id: ast::DUMMY_NODE_ID,
692692
rules: ast::DefaultBlock, // no idea

src/libsyntax/parse/parser.rs

+11-13
Original file line numberDiff line numberDiff line change
@@ -3260,9 +3260,14 @@ impl<'a> Parser<'a> {
32603260
match self.token {
32613261
token::SEMI => {
32623262
self.bump();
3263+
let span_with_semi = Span {
3264+
lo: stmt.span.lo,
3265+
hi: self.last_span.hi,
3266+
expn_info: stmt.span.expn_info,
3267+
};
32633268
stmts.push(@codemap::Spanned {
32643269
node: StmtSemi(e, stmt_id),
3265-
span: stmt.span,
3270+
span: span_with_semi,
32663271
});
32673272
}
32683273
token::RBRACE => {
@@ -3275,33 +3280,26 @@ impl<'a> Parser<'a> {
32753280
}
32763281
StmtMac(ref m, _) => {
32773282
// statement macro; might be an expr
3278-
let has_semi;
32793283
match self.token {
32803284
token::SEMI => {
3281-
has_semi = true;
3285+
self.bump();
3286+
stmts.push(@codemap::Spanned {
3287+
node: StmtMac((*m).clone(), true),
3288+
span: stmt.span,
3289+
});
32823290
}
32833291
token::RBRACE => {
32843292
// if a block ends in `m!(arg)` without
32853293
// a `;`, it must be an expr
3286-
has_semi = false;
32873294
expr = Some(
32883295
self.mk_mac_expr(stmt.span.lo,
32893296
stmt.span.hi,
32903297
m.node.clone()));
32913298
}
32923299
_ => {
3293-
has_semi = false;
32943300
stmts.push(stmt);
32953301
}
32963302
}
3297-
3298-
if has_semi {
3299-
self.bump();
3300-
stmts.push(@codemap::Spanned {
3301-
node: StmtMac((*m).clone(), true),
3302-
span: stmt.span,
3303-
});
3304-
}
33053303
}
33063304
_ => { // all other kinds of statements:
33073305
stmts.push(stmt);

src/test/compile-fail/issue-13428.rs

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// Copyright 2014 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+
// Regression test for #13428
12+
13+
fn foo() -> ~str { //~ ERROR not all control paths return a value
14+
format!("Hello {}",
15+
"world")
16+
// Put the trailing semicolon on its own line to test that the
17+
// note message gets the offending semicolon exactly
18+
; //~ NOTE consider removing this semicolon
19+
}
20+
21+
fn bar() -> ~str { //~ ERROR not all control paths return a value
22+
"foobar".to_owned()
23+
; //~ NOTE consider removing this semicolon
24+
}
25+
26+
pub fn main() {}

0 commit comments

Comments
 (0)