about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_lint/src/panic_fmt.rs22
-rw-r--r--src/test/ui/panic-brace.rs12
-rw-r--r--src/test/ui/panic-brace.stderr48
3 files changed, 66 insertions, 16 deletions
diff --git a/compiler/rustc_lint/src/panic_fmt.rs b/compiler/rustc_lint/src/panic_fmt.rs
index cff50ff9912..7428a9d13ff 100644
--- a/compiler/rustc_lint/src/panic_fmt.rs
+++ b/compiler/rustc_lint/src/panic_fmt.rs
@@ -4,7 +4,7 @@ use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_middle::ty;
 use rustc_parse_format::{ParseMode, Parser, Piece};
-use rustc_span::sym;
+use rustc_span::{sym, InnerSpan};
 
 declare_lint! {
     /// 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
                         };
 
                     let mut fmt_parser =
-                        Parser::new(fmt.as_ref(), style, snippet, false, ParseMode::Format);
+                        Parser::new(fmt.as_ref(), style, snippet.clone(), false, ParseMode::Format);
                     let n_arguments =
                         (&mut fmt_parser).filter(|a| matches!(a, Piece::NextArgument(_))).count();
 
@@ -115,8 +115,22 @@ fn check_panic<'tcx>(cx: &LateContext<'tcx>, f: &'tcx hir::Expr<'tcx>, arg: &'tc
                             l.emit();
                         });
                     } else {
-                        cx.struct_span_lint(PANIC_FMT, expn.call_site, |lint| {
-                            let mut l = lint.build("panic message contains a brace");
+                        let brace_spans: Option<Vec<_>> = snippet
+                            .filter(|s| s.starts_with('"') || s.starts_with("r#"))
+                            .map(|s| {
+                                s.char_indices()
+                                    .filter(|&(_, c)| c == '{' || c == '}')
+                                    .map(|(i, _)| {
+                                        fmt_span.from_inner(InnerSpan { start: i, end: i + 1 })
+                                    })
+                                    .collect()
+                            });
+                        let msg = match &brace_spans {
+                            Some(v) if v.len() == 1 => "panic message contains a brace",
+                            _ => "panic message contains braces",
+                        };
+                        cx.struct_span_lint(PANIC_FMT, brace_spans.unwrap_or(vec![expn.call_site]), |lint| {
+                            let mut l = lint.build(msg);
                             l.note("this message is not used as a format string, but will be in a future Rust version");
                             if expn.call_site.contains(arg.span) {
                                 l.span_suggestion(
diff --git a/src/test/ui/panic-brace.rs b/src/test/ui/panic-brace.rs
index e74b6ad96c2..d38d8ac4deb 100644
--- a/src/test/ui/panic-brace.rs
+++ b/src/test/ui/panic-brace.rs
@@ -1,10 +1,18 @@
 // build-pass (FIXME(62277): should be check-pass)
 
+const C: &str = "abc {}";
+static S: &str = "{bla}";
+
 #[allow(unreachable_code)]
 fn main() {
     panic!("here's a brace: {"); //~ WARN panic message contains a brace
     std::panic!("another one: }"); //~ WARN panic message contains a brace
     core::panic!("Hello {}"); //~ WARN panic message contains an unused formatting placeholder
-    assert!(false, "{:03x} {test} bla"); //~ WARN panic message contains unused formatting placeholders
-    debug_assert!(false, "{{}} bla"); //~ WARN panic message contains a brace
+    assert!(false, "{:03x} {test} bla");
+    //~^ WARN panic message contains unused formatting placeholders
+    debug_assert!(false, "{{}} bla"); //~ WARN panic message contains braces
+    panic!(C); // No warning (yet)
+    panic!(S); // No warning (yet)
+    panic!(concat!("{", "}")); //~ WARN panic message contains an unused formatting placeholder
+    panic!(concat!("{", "{")); //~ WARN panic message contains braces
 }
diff --git a/src/test/ui/panic-brace.stderr b/src/test/ui/panic-brace.stderr
index 23ae31d00eb..16795ed3d36 100644
--- a/src/test/ui/panic-brace.stderr
+++ b/src/test/ui/panic-brace.stderr
@@ -1,8 +1,8 @@
 warning: panic message contains a brace
-  --> $DIR/panic-brace.rs:5:5
+  --> $DIR/panic-brace.rs:8:29
    |
 LL |     panic!("here's a brace: {");
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                             ^
    |
    = note: `#[warn(panic_fmt)]` on by default
    = 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: {");
    |            ^^^^^
 
 warning: panic message contains a brace
-  --> $DIR/panic-brace.rs:6:5
+  --> $DIR/panic-brace.rs:9:31
    |
 LL |     std::panic!("another one: }");
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                               ^
    |
    = note: this message is not used as a format string, but will be in a future Rust version
 help: add a "{}" format string to use the message literally
@@ -24,7 +24,7 @@ LL |     std::panic!("{}", "another one: }");
    |                 ^^^^^
 
 warning: panic message contains an unused formatting placeholder
-  --> $DIR/panic-brace.rs:7:25
+  --> $DIR/panic-brace.rs:10:25
    |
 LL |     core::panic!("Hello {}");
    |                         ^^
@@ -40,7 +40,7 @@ LL |     core::panic!("{}", "Hello {}");
    |                  ^^^^^
 
 warning: panic message contains unused formatting placeholders
-  --> $DIR/panic-brace.rs:8:21
+  --> $DIR/panic-brace.rs:11:21
    |
 LL |     assert!(false, "{:03x} {test} bla");
    |                     ^^^^^^ ^^^^^^
@@ -55,11 +55,11 @@ help: or add a "{}" format string to use the message literally
 LL |     assert!(false, "{}", "{:03x} {test} bla");
    |                    ^^^^^
 
-warning: panic message contains a brace
-  --> $DIR/panic-brace.rs:9:5
+warning: panic message contains braces
+  --> $DIR/panic-brace.rs:13:27
    |
 LL |     debug_assert!(false, "{{}} bla");
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                           ^^^^
    |
    = note: this message is not used as a format string, but will be in a future Rust version
 help: add a "{}" format string to use the message literally
@@ -67,5 +67,33 @@ help: add a "{}" format string to use the message literally
 LL |     debug_assert!(false, "{}", "{{}} bla");
    |                          ^^^^^
 
-warning: 5 warnings emitted
+warning: panic message contains an unused formatting placeholder
+  --> $DIR/panic-brace.rs:16:12
+   |
+LL |     panic!(concat!("{", "}"));
+   |            ^^^^^^^^^^^^^^^^^
+   |
+   = note: this message is not used as a format string when given without arguments, but will be in a future Rust version
+help: add the missing argument(s)
+   |
+LL |     panic!(concat!("{", "}"), ...);
+   |                             ^^^^^
+help: or add a "{}" format string to use the message literally
+   |
+LL |     panic!("{}", concat!("{", "}"));
+   |            ^^^^^
+
+warning: panic message contains braces
+  --> $DIR/panic-brace.rs:17:5
+   |
+LL |     panic!(concat!("{", "{"));
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this message is not used as a format string, but will be in a future Rust version
+help: add a "{}" format string to use the message literally
+   |
+LL |     panic!("{}", concat!("{", "{"));
+   |            ^^^^^
+
+warning: 7 warnings emitted