Skip to content

Commit 190c3ad

Browse files
committed
Improve panic_fmt error messages for invalid format strings too.
1 parent 6b44662 commit 190c3ad

File tree

3 files changed

+66
-16
lines changed

3 files changed

+66
-16
lines changed

compiler/rustc_lint/src/panic_fmt.rs

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use rustc_errors::Applicability;
44
use rustc_hir as hir;
55
use rustc_middle::ty;
66
use rustc_parse_format::{ParseMode, Parser, Piece};
7-
use rustc_span::sym;
7+
use rustc_span::{sym, InnerSpan};
88

99
declare_lint! {
1010
/// The `panic_fmt` lint detects `panic!("..")` with `{` or `}` in the string literal.
@@ -71,7 +71,7 @@ fn check_panic<'tcx>(cx: &LateContext<'tcx>, f: &'tcx hir::Expr<'tcx>, arg: &'tc
7171
};
7272

7373
let mut fmt_parser =
74-
Parser::new(fmt.as_ref(), style, snippet, false, ParseMode::Format);
74+
Parser::new(fmt.as_ref(), style, snippet.clone(), false, ParseMode::Format);
7575
let n_arguments =
7676
(&mut fmt_parser).filter(|a| matches!(a, Piece::NextArgument(_))).count();
7777

@@ -115,8 +115,22 @@ fn check_panic<'tcx>(cx: &LateContext<'tcx>, f: &'tcx hir::Expr<'tcx>, arg: &'tc
115115
l.emit();
116116
});
117117
} else {
118-
cx.struct_span_lint(PANIC_FMT, expn.call_site, |lint| {
119-
let mut l = lint.build("panic message contains a brace");
118+
let brace_spans: Option<Vec<_>> = snippet
119+
.filter(|s| s.starts_with('"') || s.starts_with("r#"))
120+
.map(|s| {
121+
s.char_indices()
122+
.filter(|&(_, c)| c == '{' || c == '}')
123+
.map(|(i, _)| {
124+
fmt_span.from_inner(InnerSpan { start: i, end: i + 1 })
125+
})
126+
.collect()
127+
});
128+
let msg = match &brace_spans {
129+
Some(v) if v.len() == 1 => "panic message contains a brace",
130+
_ => "panic message contains braces",
131+
};
132+
cx.struct_span_lint(PANIC_FMT, brace_spans.unwrap_or(vec![expn.call_site]), |lint| {
133+
let mut l = lint.build(msg);
120134
l.note("this message is not used as a format string, but will be in a future Rust version");
121135
if expn.call_site.contains(arg.span) {
122136
l.span_suggestion(

src/test/ui/panic-brace.rs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,18 @@
11
// build-pass (FIXME(62277): should be check-pass)
22

3+
const C: &str = "abc {}";
4+
static S: &str = "{bla}";
5+
36
#[allow(unreachable_code)]
47
fn main() {
58
panic!("here's a brace: {"); //~ WARN panic message contains a brace
69
std::panic!("another one: }"); //~ WARN panic message contains a brace
710
core::panic!("Hello {}"); //~ WARN panic message contains an unused formatting placeholder
8-
assert!(false, "{:03x} {test} bla"); //~ WARN panic message contains unused formatting placeholders
9-
debug_assert!(false, "{{}} bla"); //~ WARN panic message contains a brace
11+
assert!(false, "{:03x} {test} bla");
12+
//~^ WARN panic message contains unused formatting placeholders
13+
debug_assert!(false, "{{}} bla"); //~ WARN panic message contains braces
14+
panic!(C); // No warning (yet)
15+
panic!(S); // No warning (yet)
16+
panic!(concat!("{", "}")); //~ WARN panic message contains an unused formatting placeholder
17+
panic!(concat!("{", "{")); //~ WARN panic message contains braces
1018
}

src/test/ui/panic-brace.stderr

Lines changed: 38 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
warning: panic message contains a brace
2-
--> $DIR/panic-brace.rs:5:5
2+
--> $DIR/panic-brace.rs:8:29
33
|
44
LL | panic!("here's a brace: {");
5-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
5+
| ^
66
|
77
= note: `#[warn(panic_fmt)]` on by default
88
= note: this message is not used as a format string, but will be in a future Rust version
@@ -12,10 +12,10 @@ LL | panic!("{}", "here's a brace: {");
1212
| ^^^^^
1313

1414
warning: panic message contains a brace
15-
--> $DIR/panic-brace.rs:6:5
15+
--> $DIR/panic-brace.rs:9:31
1616
|
1717
LL | std::panic!("another one: }");
18-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
18+
| ^
1919
|
2020
= note: this message is not used as a format string, but will be in a future Rust version
2121
help: add a "{}" format string to use the message literally
@@ -24,7 +24,7 @@ LL | std::panic!("{}", "another one: }");
2424
| ^^^^^
2525

2626
warning: panic message contains an unused formatting placeholder
27-
--> $DIR/panic-brace.rs:7:25
27+
--> $DIR/panic-brace.rs:10:25
2828
|
2929
LL | core::panic!("Hello {}");
3030
| ^^
@@ -40,7 +40,7 @@ LL | core::panic!("{}", "Hello {}");
4040
| ^^^^^
4141

4242
warning: panic message contains unused formatting placeholders
43-
--> $DIR/panic-brace.rs:8:21
43+
--> $DIR/panic-brace.rs:11:21
4444
|
4545
LL | assert!(false, "{:03x} {test} bla");
4646
| ^^^^^^ ^^^^^^
@@ -55,17 +55,45 @@ help: or add a "{}" format string to use the message literally
5555
LL | assert!(false, "{}", "{:03x} {test} bla");
5656
| ^^^^^
5757

58-
warning: panic message contains a brace
59-
--> $DIR/panic-brace.rs:9:5
58+
warning: panic message contains braces
59+
--> $DIR/panic-brace.rs:13:27
6060
|
6161
LL | debug_assert!(false, "{{}} bla");
62-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
62+
| ^^^^
6363
|
6464
= note: this message is not used as a format string, but will be in a future Rust version
6565
help: add a "{}" format string to use the message literally
6666
|
6767
LL | debug_assert!(false, "{}", "{{}} bla");
6868
| ^^^^^
6969

70-
warning: 5 warnings emitted
70+
warning: panic message contains an unused formatting placeholder
71+
--> $DIR/panic-brace.rs:16:12
72+
|
73+
LL | panic!(concat!("{", "}"));
74+
| ^^^^^^^^^^^^^^^^^
75+
|
76+
= note: this message is not used as a format string when given without arguments, but will be in a future Rust version
77+
help: add the missing argument(s)
78+
|
79+
LL | panic!(concat!("{", "}"), ...);
80+
| ^^^^^
81+
help: or add a "{}" format string to use the message literally
82+
|
83+
LL | panic!("{}", concat!("{", "}"));
84+
| ^^^^^
85+
86+
warning: panic message contains braces
87+
--> $DIR/panic-brace.rs:17:5
88+
|
89+
LL | panic!(concat!("{", "{"));
90+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
91+
|
92+
= note: this message is not used as a format string, but will be in a future Rust version
93+
help: add a "{}" format string to use the message literally
94+
|
95+
LL | panic!("{}", concat!("{", "{"));
96+
| ^^^^^
97+
98+
warning: 7 warnings emitted
7199

0 commit comments

Comments
 (0)