about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMara Bos <m-ou.se@m-ou.se>2021-02-14 19:43:07 +0100
committerMara Bos <m-ou.se@m-ou.se>2021-02-14 19:44:48 +0100
commit37c532c010cddb8f9283fb50318d8c3816646063 (patch)
treeae0f393a007f4a9046d7cd71132f26f9cdc0ce0b
parent9f97a0b364bcbb261f05d6ac62436b6802bfa80b (diff)
downloadrust-37c532c010cddb8f9283fb50318d8c3816646063.tar.gz
rust-37c532c010cddb8f9283fb50318d8c3816646063.zip
Suggest correct replacement for panic![123].
Before this change, the suggestion was `std::panic::panic_any(123]`,
changing the opening brace but not the closing one.
-rw-r--r--compiler/rustc_lint/src/non_fmt_panic.rs48
-rw-r--r--src/test/ui/non-fmt-panic.stderr8
2 files changed, 37 insertions, 19 deletions
diff --git a/compiler/rustc_lint/src/non_fmt_panic.rs b/compiler/rustc_lint/src/non_fmt_panic.rs
index 7432f476d7c..c4627745648 100644
--- a/compiler/rustc_lint/src/non_fmt_panic.rs
+++ b/compiler/rustc_lint/src/non_fmt_panic.rs
@@ -93,12 +93,12 @@ fn check_panic<'tcx>(cx: &LateContext<'tcx>, f: &'tcx hir::Expr<'tcx>, arg: &'tc
         if arg_macro.map_or(false, |id| cx.tcx.is_diagnostic_item(sym::format_macro, id)) {
             // A case of `panic!(format!(..))`.
             l.note("the panic!() macro supports formatting, so there's no need for the format!() macro here");
-            if let Some(inner) = find_inner_span(cx, arg_span) {
+            if let Some((open, close, _)) = find_delimiters(cx, arg_span) {
                 l.multipart_suggestion(
                     "remove the `format!(..)` macro call",
                     vec![
-                        (arg_span.until(inner), "".into()),
-                        (inner.between(arg_span.shrink_to_hi()), "".into()),
+                        (arg_span.until(open.shrink_to_hi()), "".into()),
+                        (close.until(arg_span.shrink_to_hi()), "".into()),
                     ],
                     Applicability::MachineApplicable,
                 );
@@ -111,12 +111,20 @@ fn check_panic<'tcx>(cx: &LateContext<'tcx>, f: &'tcx hir::Expr<'tcx>, arg: &'tc
                 Applicability::MaybeIncorrect,
             );
             if panic == sym::std_panic_macro {
-                l.span_suggestion_verbose(
-                    span.until(arg_span),
-                    "or use std::panic::panic_any instead",
-                    "std::panic::panic_any(".into(),
-                    Applicability::MachineApplicable,
-                );
+                if let Some((open, close, del)) = find_delimiters(cx, span) {
+                    l.multipart_suggestion(
+                        "or use std::panic::panic_any instead",
+                        if del == '(' {
+                            vec![(span.until(open), "std::panic::panic_any".into())]
+                        } else {
+                            vec![
+                                (span.until(open.shrink_to_hi()), "std::panic::panic_any(".into()),
+                                (close, ")".into()),
+                            ]
+                        },
+                        Applicability::MachineApplicable,
+                    );
+                }
             }
         }
         l.emit();
@@ -206,13 +214,23 @@ fn check_panic_str<'tcx>(
     }
 }
 
-/// Given the span of `some_macro!(args)`, gives the span of `args`.
-fn find_inner_span<'tcx>(cx: &LateContext<'tcx>, span: Span) -> Option<Span> {
+/// Given the span of `some_macro!(args);`, gives the span of `(` and `)`,
+/// and the type of (opening) delimiter used.
+fn find_delimiters<'tcx>(cx: &LateContext<'tcx>, span: Span) -> Option<(Span, Span, char)> {
     let snippet = cx.sess().parse_sess.source_map().span_to_snippet(span).ok()?;
-    Some(span.from_inner(InnerSpan {
-        start: snippet.find(&['(', '{', '['][..])? + 1,
-        end: snippet.rfind(&[')', '}', ']'][..])?,
-    }))
+    let (open, open_ch) = snippet.char_indices().find(|&(_, c)| "([{".contains(c))?;
+    let close = snippet.rfind(|c| ")]}".contains(c))?;
+    Some((
+        span.from_inner(InnerSpan {
+            start: open,
+            end: open + 1,
+        }),
+        span.from_inner(InnerSpan {
+            start: close,
+            end: close + 1,
+        }),
+        open_ch,
+    ))
 }
 
 fn panic_call<'tcx>(cx: &LateContext<'tcx>, f: &'tcx hir::Expr<'tcx>) -> (Span, Symbol) {
diff --git a/src/test/ui/non-fmt-panic.stderr b/src/test/ui/non-fmt-panic.stderr
index 043c4b0f750..001f066ad21 100644
--- a/src/test/ui/non-fmt-panic.stderr
+++ b/src/test/ui/non-fmt-panic.stderr
@@ -93,7 +93,7 @@ LL |     panic!("{}", C);
 help: or use std::panic::panic_any instead
    |
 LL |     std::panic::panic_any(C);
-   |     ^^^^^^^^^^^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^^^^^^^^^^
 
 warning: panic message is not a string literal
   --> $DIR/non-fmt-panic.rs:20:12
@@ -109,7 +109,7 @@ LL |     panic!("{}", S);
 help: or use std::panic::panic_any instead
    |
 LL |     std::panic::panic_any(S);
-   |     ^^^^^^^^^^^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^^^^^^^^^^
 
 warning: panic message is not a string literal
   --> $DIR/non-fmt-panic.rs:21:17
@@ -125,7 +125,7 @@ LL |     std::panic!("{}", 123);
 help: or use std::panic::panic_any instead
    |
 LL |     std::panic::panic_any(123);
-   |     ^^^^^^^^^^^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^^^^^^^^^^
 
 warning: panic message is not a string literal
   --> $DIR/non-fmt-panic.rs:22:18
@@ -197,7 +197,7 @@ LL |     panic!("{}", a!());
 help: or use std::panic::panic_any instead
    |
 LL |     std::panic::panic_any(a!());
-   |     ^^^^^^^^^^^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^^^^^^^^^^
 
 warning: panic message is not a string literal
   --> $DIR/non-fmt-panic.rs:38:12