Skip to content

Commit a4660df

Browse files
committed
Point at unused arguments for format string
Avoid overlapping spans by only pointing at the arguments that are not being used in the argument string. Enable libsyntax to have diagnostics with multiple primary spans by accepting `Into<MultiSpan>` instead of `Span`.
1 parent bb345a0 commit a4660df

File tree

7 files changed

+62
-84
lines changed

7 files changed

+62
-84
lines changed

src/libsyntax/ext/base.rs

+19-19
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ pub use self::SyntaxExtension::*;
1313
use ast::{self, Attribute, Name, PatKind, MetaItem};
1414
use attr::HasAttrs;
1515
use codemap::{self, CodeMap, Spanned, respan};
16-
use syntax_pos::{Span, DUMMY_SP};
16+
use syntax_pos::{Span, MultiSpan, DUMMY_SP};
1717
use errors::DiagnosticBuilder;
1818
use ext::expand::{self, Expansion, Invocation};
1919
use ext::hygiene::{Mark, SyntaxContext};
@@ -754,22 +754,22 @@ impl<'a> ExtCtxt<'a> {
754754
last_macro
755755
}
756756

757-
pub fn struct_span_warn(&self,
758-
sp: Span,
759-
msg: &str)
760-
-> DiagnosticBuilder<'a> {
757+
pub fn struct_span_warn<S: Into<MultiSpan>>(&self,
758+
sp: S,
759+
msg: &str)
760+
-> DiagnosticBuilder<'a> {
761761
self.parse_sess.span_diagnostic.struct_span_warn(sp, msg)
762762
}
763-
pub fn struct_span_err(&self,
764-
sp: Span,
765-
msg: &str)
766-
-> DiagnosticBuilder<'a> {
763+
pub fn struct_span_err<S: Into<MultiSpan>>(&self,
764+
sp: S,
765+
msg: &str)
766+
-> DiagnosticBuilder<'a> {
767767
self.parse_sess.span_diagnostic.struct_span_err(sp, msg)
768768
}
769-
pub fn struct_span_fatal(&self,
770-
sp: Span,
771-
msg: &str)
772-
-> DiagnosticBuilder<'a> {
769+
pub fn struct_span_fatal<S: Into<MultiSpan>>(&self,
770+
sp: S,
771+
msg: &str)
772+
-> DiagnosticBuilder<'a> {
773773
self.parse_sess.span_diagnostic.struct_span_fatal(sp, msg)
774774
}
775775

@@ -785,7 +785,7 @@ impl<'a> ExtCtxt<'a> {
785785
/// in most cases one can construct a dummy expression/item to
786786
/// substitute; we never hit resolve/type-checking so the dummy
787787
/// value doesn't have to match anything)
788-
pub fn span_fatal(&self, sp: Span, msg: &str) -> ! {
788+
pub fn span_fatal<S: Into<MultiSpan>>(&self, sp: S, msg: &str) -> ! {
789789
panic!(self.parse_sess.span_diagnostic.span_fatal(sp, msg));
790790
}
791791

@@ -794,20 +794,20 @@ impl<'a> ExtCtxt<'a> {
794794
///
795795
/// Compilation will be stopped in the near future (at the end of
796796
/// the macro expansion phase).
797-
pub fn span_err(&self, sp: Span, msg: &str) {
797+
pub fn span_err<S: Into<MultiSpan>>(&self, sp: S, msg: &str) {
798798
self.parse_sess.span_diagnostic.span_err(sp, msg);
799799
}
800-
pub fn mut_span_err(&self, sp: Span, msg: &str)
800+
pub fn mut_span_err<S: Into<MultiSpan>>(&self, sp: S, msg: &str)
801801
-> DiagnosticBuilder<'a> {
802802
self.parse_sess.span_diagnostic.mut_span_err(sp, msg)
803803
}
804-
pub fn span_warn(&self, sp: Span, msg: &str) {
804+
pub fn span_warn<S: Into<MultiSpan>>(&self, sp: S, msg: &str) {
805805
self.parse_sess.span_diagnostic.span_warn(sp, msg);
806806
}
807-
pub fn span_unimpl(&self, sp: Span, msg: &str) -> ! {
807+
pub fn span_unimpl<S: Into<MultiSpan>>(&self, sp: S, msg: &str) -> ! {
808808
self.parse_sess.span_diagnostic.span_unimpl(sp, msg);
809809
}
810-
pub fn span_bug(&self, sp: Span, msg: &str) -> ! {
810+
pub fn span_bug<S: Into<MultiSpan>>(&self, sp: S, msg: &str) -> ! {
811811
self.parse_sess.span_diagnostic.span_bug(sp, msg);
812812
}
813813
pub fn trace_macros_diag(&mut self) {

src/libsyntax/parse/parser.rs

+15-10
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ use ast::{BinOpKind, UnOp};
4242
use ast::{RangeEnd, RangeSyntax};
4343
use {ast, attr};
4444
use codemap::{self, CodeMap, Spanned, respan};
45-
use syntax_pos::{self, Span, BytePos, FileName, DUMMY_SP};
45+
use syntax_pos::{self, Span, MultiSpan, BytePos, FileName, DUMMY_SP};
4646
use errors::{self, DiagnosticBuilder};
4747
use parse::{self, classify, token};
4848
use parse::common::SeqSep;
@@ -447,7 +447,9 @@ pub enum Error {
447447
}
448448

449449
impl Error {
450-
pub fn span_err(self, sp: Span, handler: &errors::Handler) -> DiagnosticBuilder {
450+
pub fn span_err<S: Into<MultiSpan>>(self,
451+
sp: S,
452+
handler: &errors::Handler) -> DiagnosticBuilder {
451453
match self {
452454
Error::FileNotFoundForModule { ref mod_name,
453455
ref default_path,
@@ -1266,13 +1268,16 @@ impl<'a> Parser<'a> {
12661268
pub fn fatal(&self, m: &str) -> DiagnosticBuilder<'a> {
12671269
self.sess.span_diagnostic.struct_span_fatal(self.span, m)
12681270
}
1269-
pub fn span_fatal(&self, sp: Span, m: &str) -> DiagnosticBuilder<'a> {
1271+
pub fn span_fatal<S: Into<MultiSpan>>(&self, sp: S, m: &str) -> DiagnosticBuilder<'a> {
12701272
self.sess.span_diagnostic.struct_span_fatal(sp, m)
12711273
}
1272-
pub fn span_fatal_err(&self, sp: Span, err: Error) -> DiagnosticBuilder<'a> {
1274+
pub fn span_fatal_err<S: Into<MultiSpan>>(&self, sp: S, err: Error) -> DiagnosticBuilder<'a> {
12731275
err.span_err(sp, self.diagnostic())
12741276
}
1275-
pub fn span_fatal_help(&self, sp: Span, m: &str, help: &str) -> DiagnosticBuilder<'a> {
1277+
pub fn span_fatal_help<S: Into<MultiSpan>>(&self,
1278+
sp: S,
1279+
m: &str,
1280+
help: &str) -> DiagnosticBuilder<'a> {
12761281
let mut err = self.sess.span_diagnostic.struct_span_fatal(sp, m);
12771282
err.help(help);
12781283
err
@@ -1283,21 +1288,21 @@ impl<'a> Parser<'a> {
12831288
pub fn warn(&self, m: &str) {
12841289
self.sess.span_diagnostic.span_warn(self.span, m)
12851290
}
1286-
pub fn span_warn(&self, sp: Span, m: &str) {
1291+
pub fn span_warn<S: Into<MultiSpan>>(&self, sp: S, m: &str) {
12871292
self.sess.span_diagnostic.span_warn(sp, m)
12881293
}
1289-
pub fn span_err(&self, sp: Span, m: &str) {
1294+
pub fn span_err<S: Into<MultiSpan>>(&self, sp: S, m: &str) {
12901295
self.sess.span_diagnostic.span_err(sp, m)
12911296
}
1292-
pub fn struct_span_err(&self, sp: Span, m: &str) -> DiagnosticBuilder<'a> {
1297+
pub fn struct_span_err<S: Into<MultiSpan>>(&self, sp: S, m: &str) -> DiagnosticBuilder<'a> {
12931298
self.sess.span_diagnostic.struct_span_err(sp, m)
12941299
}
1295-
pub fn span_err_help(&self, sp: Span, m: &str, h: &str) {
1300+
pub fn span_err_help<S: Into<MultiSpan>>(&self, sp: S, m: &str, h: &str) {
12961301
let mut err = self.sess.span_diagnostic.mut_span_err(sp, m);
12971302
err.help(h);
12981303
err.emit();
12991304
}
1300-
pub fn span_bug(&self, sp: Span, m: &str) -> ! {
1305+
pub fn span_bug<S: Into<MultiSpan>>(&self, sp: S, m: &str) -> ! {
13011306
self.sess.span_diagnostic.span_bug(sp, m)
13021307
}
13031308
pub fn abort_if_errors(&self) {

src/libsyntax_ext/format.rs

+2-10
Original file line numberDiff line numberDiff line change
@@ -814,16 +814,8 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt,
814814
let (sp, msg) = errs.into_iter().next().unwrap();
815815
cx.ecx.struct_span_err(sp, msg)
816816
} else {
817-
let mut diag = cx.ecx.struct_span_err(cx.fmtsp,
818-
"multiple unused formatting arguments");
819-
820-
// Ignoring message, as it gets repetitive
821-
// Then use MultiSpan to not clutter up errors
822-
for (sp, _) in errs {
823-
diag.span_label(sp, "unused");
824-
}
825-
826-
diag
817+
cx.ecx.struct_span_err(errs.iter().map(|&(sp, _)| sp).collect::<Vec<Span>>(),
818+
"multiple unused formatting arguments")
827819
}
828820
};
829821

src/test/ui/macros/format-foreign.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
// except according to those terms.
1010

1111
fn main() {
12-
println!("%.*3$s %s!\n", "Hello,", "World", 4);
12+
println!("%.*3$s %s!\n", "Hello,", "World", 4); //~ ERROR multiple unused formatting arguments
1313
println!("%1$*2$.*3$f", 123.456); //~ ERROR never used
1414

1515
// This should *not* produce hints, on the basis that there's equally as

src/test/ui/macros/format-foreign.stderr

+3-8
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,12 @@
11
error: multiple unused formatting arguments
2-
--> $DIR/format-foreign.rs:12:5
2+
--> $DIR/format-foreign.rs:12:30
33
|
4-
12 | println!("%.*3$s %s!/n", "Hello,", "World", 4);
5-
| ^^^^^^^^^^^^^^^^^^^^^^^^^--------^^-------^^-^^
6-
| | | |
7-
| | | unused
8-
| | unused
9-
| unused
4+
12 | println!("%.*3$s %s!/n", "Hello,", "World", 4); //~ ERROR multiple unused formatting arguments
5+
| ^^^^^^^^ ^^^^^^^ ^
106
|
117
= help: `%.*3$s` should be written as `{:.2$}`
128
= help: `%s` should be written as `{}`
139
= note: printf formatting not supported; see the documentation for `std::fmt`
14-
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
1510

1611
error: argument never used
1712
--> $DIR/format-foreign.rs:13:29

src/test/ui/macros/format-unused-lables.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -10,17 +10,18 @@
1010

1111
fn main() {
1212
println!("Test", 123, 456, 789);
13+
//~^ ERROR multiple unused formatting arguments
1314

1415
println!("Test2",
15-
123,
16+
123, //~ ERROR multiple unused formatting arguments
1617
456,
1718
789
1819
);
1920

2021
println!("Some stuff", UNUSED="args"); //~ ERROR named argument never used
2122

2223
println!("Some more $STUFF",
23-
"woo!",
24+
"woo!", //~ ERROR multiple unused formatting arguments
2425
STUFF=
2526
"things"
2627
, UNUSED="args");
+19-34
Original file line numberDiff line numberDiff line change
@@ -1,53 +1,38 @@
11
error: multiple unused formatting arguments
2-
--> $DIR/format-unused-lables.rs:12:5
2+
--> $DIR/format-unused-lables.rs:12:22
33
|
44
12 | println!("Test", 123, 456, 789);
5-
| ^^^^^^^^^^^^^^^^^---^^---^^---^^
6-
| | | |
7-
| | | unused
8-
| | unused
9-
| unused
10-
|
11-
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
5+
| ^^^ ^^^ ^^^
126

137
error: multiple unused formatting arguments
14-
--> $DIR/format-unused-lables.rs:14:5
15-
|
16-
14 | / println!("Test2",
17-
15 | | 123,
18-
| | --- unused
19-
16 | | 456,
20-
| | --- unused
21-
17 | | 789
22-
| | --- unused
23-
18 | | );
24-
| |______^
8+
--> $DIR/format-unused-lables.rs:16:9
259
|
26-
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
10+
16 | 123, //~ ERROR multiple unused formatting arguments
11+
| ^^^
12+
17 | 456,
13+
| ^^^
14+
18 | 789
15+
| ^^^
2716

2817
error: named argument never used
29-
--> $DIR/format-unused-lables.rs:20:35
18+
--> $DIR/format-unused-lables.rs:21:35
3019
|
31-
20 | println!("Some stuff", UNUSED="args"); //~ ERROR named argument never used
20+
21 | println!("Some stuff", UNUSED="args"); //~ ERROR named argument never used
3221
| ^^^^^^
3322

3423
error: multiple unused formatting arguments
35-
--> $DIR/format-unused-lables.rs:22:5
24+
--> $DIR/format-unused-lables.rs:24:9
3625
|
37-
22 | / println!("Some more $STUFF",
38-
23 | | "woo!",
39-
| | ------ unused
40-
24 | | STUFF=
41-
25 | | "things"
42-
| | -------- unused
43-
26 | | , UNUSED="args");
44-
| |_______________________------_^
45-
| |
46-
| unused
26+
24 | "woo!", //~ ERROR multiple unused formatting arguments
27+
| ^^^^^^
28+
25 | STUFF=
29+
26 | "things"
30+
| ^^^^^^^^
31+
27 | , UNUSED="args");
32+
| ^^^^^^
4733
|
4834
= help: `$STUFF` should be written as `{STUFF}`
4935
= note: shell formatting not supported; see the documentation for `std::fmt`
50-
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
5136

5237
error: aborting due to 4 previous errors
5338

0 commit comments

Comments
 (0)