about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2022-02-05 17:44:37 +0000
committerbors <bors@rust-lang.org>2022-02-05 17:44:37 +0000
commit68b44986de6a8c9e844afa55693a24f0d4a0978e (patch)
treefa2e21087e2a10dfada3a1879a5132ed789cf5be
parent29cc0d8e595f93cd0bd8341dd034c847f3a7746f (diff)
parent144b4a59c7a3d18a0dd2c4316061672d00516ea3 (diff)
downloadrust-68b44986de6a8c9e844afa55693a24f0d4a0978e.tar.gz
rust-68b44986de6a8c9e844afa55693a24f0d4a0978e.zip
Auto merge of #8365 - Alexendoo:explicit-write-suggestion, r=camsteffen
Add `explicit_write` suggestions for `write!`s with format args

changelog: Add [`explicit_write`] suggestions for `write!`s with format args

Fixes #4542

```rust
writeln!(std::io::stderr(), "macro arg {}", one!()).unwrap();
```

Now suggests:

```
error: use of `writeln!(stderr(), ...).unwrap()`
  --> $DIR/explicit_write.rs:36:9
   |
LL |         writeln!(std::io::stderr(), "macro arg {}", one!()).unwrap();
   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `eprintln!("macro arg {}", one!())`
```

---------

r? `@camsteffen` (again, sorry 😛) for the `FormatArgsExpn` change

Before this change `inputs_span` returned a span pointing to just `1` in

```rust
macro_rules! one {
    () => { 1 };
}

`writeln!(std::io::stderr(), "macro arg {}", one!()).unwrap();`
```

And the `source_callsite` of that span didn't include the format string, it was just `one!()`
-rw-r--r--clippy_lints/src/explicit_write.rs41
-rw-r--r--clippy_utils/src/macros.rs9
-rw-r--r--tests/ui/expect_fun_call.fixed9
-rw-r--r--tests/ui/expect_fun_call.rs9
-rw-r--r--tests/ui/expect_fun_call.stderr32
-rw-r--r--tests/ui/explicit_write.fixed12
-rw-r--r--tests/ui/explicit_write.rs12
-rw-r--r--tests/ui/explicit_write.stderr42
-rw-r--r--tests/ui/explicit_write_non_rustfix.rs8
-rw-r--r--tests/ui/explicit_write_non_rustfix.stderr11
-rw-r--r--tests/ui/manual_assert.edition2018.fixed7
-rw-r--r--tests/ui/manual_assert.edition2018.stderr24
-rw-r--r--tests/ui/manual_assert.edition2021.fixed7
-rw-r--r--tests/ui/manual_assert.edition2021.stderr24
-rw-r--r--tests/ui/manual_assert.rs9
15 files changed, 173 insertions, 83 deletions
diff --git a/clippy_lints/src/explicit_write.rs b/clippy_lints/src/explicit_write.rs
index f326fd83d18..3e2217c28da 100644
--- a/clippy_lints/src/explicit_write.rs
+++ b/clippy_lints/src/explicit_write.rs
@@ -1,5 +1,6 @@
-use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_sugg};
+use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::macros::FormatArgsExpn;
+use clippy_utils::source::snippet_with_applicability;
 use clippy_utils::{is_expn_of, match_function_call, paths};
 use if_chain::if_chain;
 use rustc_errors::Applicability;
@@ -79,28 +80,22 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitWrite {
                         "print".into(),
                     )
                 };
-                let msg = format!("use of `{}.unwrap()`", used);
-                if let [write_output] = *format_args.format_string_parts {
-                    let mut write_output = write_output.to_string();
-                    if write_output.ends_with('\n') {
-                        write_output.pop();
-                    }
-
-                    let sugg = format!("{}{}!(\"{}\")", prefix, sugg_mac, write_output.escape_default());
-                    span_lint_and_sugg(
-                        cx,
-                        EXPLICIT_WRITE,
-                        expr.span,
-                        &msg,
-                        "try this",
-                        sugg,
-                        Applicability::MachineApplicable
-                    );
-                } else {
-                    // We don't have a proper suggestion
-                    let help = format!("consider using `{}{}!` instead", prefix, sugg_mac);
-                    span_lint_and_help(cx, EXPLICIT_WRITE, expr.span, &msg, None, &help);
-                }
+                let mut applicability = Applicability::MachineApplicable;
+                let inputs_snippet = snippet_with_applicability(
+                    cx,
+                    format_args.inputs_span(),
+                    "..",
+                    &mut applicability,
+                );
+                span_lint_and_sugg(
+                    cx,
+                    EXPLICIT_WRITE,
+                    expr.span,
+                    &format!("use of `{}.unwrap()`", used),
+                    "try this",
+                    format!("{}{}!({})", prefix, sugg_mac, inputs_snippet),
+                    applicability,
+                )
             }
         }
     }
diff --git a/clippy_utils/src/macros.rs b/clippy_utils/src/macros.rs
index 5bc353bdd89..76478c74e21 100644
--- a/clippy_utils/src/macros.rs
+++ b/clippy_utils/src/macros.rs
@@ -9,7 +9,7 @@ use rustc_hir::intravisit::Visitor;
 use rustc_hir::{self as hir, Expr, ExprKind, HirId, Node, QPath};
 use rustc_lint::LateContext;
 use rustc_span::def_id::DefId;
-use rustc_span::hygiene::{MacroKind, SyntaxContext};
+use rustc_span::hygiene::{self, MacroKind, SyntaxContext};
 use rustc_span::{sym, ExpnData, ExpnId, ExpnKind, Span, Symbol};
 use std::ops::ControlFlow;
 
@@ -306,6 +306,7 @@ fn is_assert_arg(cx: &LateContext<'_>, expr: &Expr<'_>, assert_expn: ExpnId) ->
 }
 
 /// A parsed `format_args!` expansion
+#[derive(Debug)]
 pub struct FormatArgsExpn<'tcx> {
     /// Span of the first argument, the format string
     pub format_string_span: Span,
@@ -465,11 +466,13 @@ impl<'tcx> FormatArgsExpn<'tcx> {
             .collect()
     }
 
-    /// Span of all inputs
+    /// Source callsite span of all inputs
     pub fn inputs_span(&self) -> Span {
         match *self.value_args {
             [] => self.format_string_span,
-            [.., last] => self.format_string_span.to(last.span),
+            [.., last] => self
+                .format_string_span
+                .to(hygiene::walk_chain(last.span, self.format_string_span.ctxt())),
         }
     }
 }
diff --git a/tests/ui/expect_fun_call.fixed b/tests/ui/expect_fun_call.fixed
index cf923a6a594..53e45d28bde 100644
--- a/tests/ui/expect_fun_call.fixed
+++ b/tests/ui/expect_fun_call.fixed
@@ -5,6 +5,12 @@
 
 /// Checks implementation of the `EXPECT_FUN_CALL` lint
 
+macro_rules! one {
+    () => {
+        1
+    };
+}
+
 fn main() {
     struct Foo;
 
@@ -31,6 +37,9 @@ fn main() {
     let with_none_and_as_str: Option<i32> = None;
     with_none_and_as_str.unwrap_or_else(|| panic!("Error {}: fake error", error_code));
 
+    let with_none_and_format_with_macro: Option<i32> = None;
+    with_none_and_format_with_macro.unwrap_or_else(|| panic!("Error {}: fake error", one!()));
+
     let with_ok: Result<(), ()> = Ok(());
     with_ok.expect("error");
 
diff --git a/tests/ui/expect_fun_call.rs b/tests/ui/expect_fun_call.rs
index e6f252259df..22e530b8034 100644
--- a/tests/ui/expect_fun_call.rs
+++ b/tests/ui/expect_fun_call.rs
@@ -5,6 +5,12 @@
 
 /// Checks implementation of the `EXPECT_FUN_CALL` lint
 
+macro_rules! one {
+    () => {
+        1
+    };
+}
+
 fn main() {
     struct Foo;
 
@@ -31,6 +37,9 @@ fn main() {
     let with_none_and_as_str: Option<i32> = None;
     with_none_and_as_str.expect(format!("Error {}: fake error", error_code).as_str());
 
+    let with_none_and_format_with_macro: Option<i32> = None;
+    with_none_and_format_with_macro.expect(format!("Error {}: fake error", one!()).as_str());
+
     let with_ok: Result<(), ()> = Ok(());
     with_ok.expect("error");
 
diff --git a/tests/ui/expect_fun_call.stderr b/tests/ui/expect_fun_call.stderr
index ac48a06671c..aca15935fca 100644
--- a/tests/ui/expect_fun_call.stderr
+++ b/tests/ui/expect_fun_call.stderr
@@ -1,5 +1,5 @@
 error: use of `expect` followed by a function call
-  --> $DIR/expect_fun_call.rs:29:26
+  --> $DIR/expect_fun_call.rs:35:26
    |
 LL |     with_none_and_format.expect(&format!("Error {}: fake error", error_code));
    |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| panic!("Error {}: fake error", error_code))`
@@ -7,70 +7,76 @@ LL |     with_none_and_format.expect(&format!("Error {}: fake error", error_code
    = note: `-D clippy::expect-fun-call` implied by `-D warnings`
 
 error: use of `expect` followed by a function call
-  --> $DIR/expect_fun_call.rs:32:26
+  --> $DIR/expect_fun_call.rs:38:26
    |
 LL |     with_none_and_as_str.expect(format!("Error {}: fake error", error_code).as_str());
    |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| panic!("Error {}: fake error", error_code))`
 
 error: use of `expect` followed by a function call
-  --> $DIR/expect_fun_call.rs:42:25
+  --> $DIR/expect_fun_call.rs:41:37
+   |
+LL |     with_none_and_format_with_macro.expect(format!("Error {}: fake error", one!()).as_str());
+   |                                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| panic!("Error {}: fake error", one!()))`
+
+error: use of `expect` followed by a function call
+  --> $DIR/expect_fun_call.rs:51:25
    |
 LL |     with_err_and_format.expect(&format!("Error {}: fake error", error_code));
    |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|_| panic!("Error {}: fake error", error_code))`
 
 error: use of `expect` followed by a function call
-  --> $DIR/expect_fun_call.rs:45:25
+  --> $DIR/expect_fun_call.rs:54:25
    |
 LL |     with_err_and_as_str.expect(format!("Error {}: fake error", error_code).as_str());
    |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|_| panic!("Error {}: fake error", error_code))`
 
 error: use of `expect` followed by a function call
-  --> $DIR/expect_fun_call.rs:57:17
+  --> $DIR/expect_fun_call.rs:66:17
    |
 LL |     Some("foo").expect(format!("{} {}", 1, 2).as_ref());
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| panic!("{} {}", 1, 2))`
 
 error: use of `expect` followed by a function call
-  --> $DIR/expect_fun_call.rs:78:21
+  --> $DIR/expect_fun_call.rs:87:21
    |
 LL |         Some("foo").expect(&get_string());
    |                     ^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| { panic!("{}", get_string()) })`
 
 error: use of `expect` followed by a function call
-  --> $DIR/expect_fun_call.rs:79:21
+  --> $DIR/expect_fun_call.rs:88:21
    |
 LL |         Some("foo").expect(get_string().as_ref());
    |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| { panic!("{}", get_string()) })`
 
 error: use of `expect` followed by a function call
-  --> $DIR/expect_fun_call.rs:80:21
+  --> $DIR/expect_fun_call.rs:89:21
    |
 LL |         Some("foo").expect(get_string().as_str());
    |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| { panic!("{}", get_string()) })`
 
 error: use of `expect` followed by a function call
-  --> $DIR/expect_fun_call.rs:82:21
+  --> $DIR/expect_fun_call.rs:91:21
    |
 LL |         Some("foo").expect(get_static_str());
    |                     ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| { panic!("{}", get_static_str()) })`
 
 error: use of `expect` followed by a function call
-  --> $DIR/expect_fun_call.rs:83:21
+  --> $DIR/expect_fun_call.rs:92:21
    |
 LL |         Some("foo").expect(get_non_static_str(&0));
    |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| { panic!("{}", get_non_static_str(&0).to_string()) })`
 
 error: use of `expect` followed by a function call
-  --> $DIR/expect_fun_call.rs:87:16
+  --> $DIR/expect_fun_call.rs:96:16
    |
 LL |     Some(true).expect(&format!("key {}, {}", 1, 2));
    |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| panic!("key {}, {}", 1, 2))`
 
 error: use of `expect` followed by a function call
-  --> $DIR/expect_fun_call.rs:93:17
+  --> $DIR/expect_fun_call.rs:102:17
    |
 LL |         opt_ref.expect(&format!("{:?}", opt_ref));
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| panic!("{:?}", opt_ref))`
 
-error: aborting due to 12 previous errors
+error: aborting due to 13 previous errors
 
diff --git a/tests/ui/explicit_write.fixed b/tests/ui/explicit_write.fixed
index 692d2ca675f..74d0e529028 100644
--- a/tests/ui/explicit_write.fixed
+++ b/tests/ui/explicit_write.fixed
@@ -10,6 +10,12 @@ fn stderr() -> String {
     String::new()
 }
 
+macro_rules! one {
+    () => {
+        1
+    };
+}
+
 fn main() {
     // these should warn
     {
@@ -24,6 +30,12 @@ fn main() {
         // including newlines
         println!("test\ntest");
         eprintln!("test\ntest");
+
+        let value = 1;
+        eprintln!("with {}", value);
+        eprintln!("with {} {}", 2, value);
+        eprintln!("with {value}");
+        eprintln!("macro arg {}", one!());
     }
     // these should not warn, different destination
     {
diff --git a/tests/ui/explicit_write.rs b/tests/ui/explicit_write.rs
index 455c5ef55d0..e7a698d3e01 100644
--- a/tests/ui/explicit_write.rs
+++ b/tests/ui/explicit_write.rs
@@ -10,6 +10,12 @@ fn stderr() -> String {
     String::new()
 }
 
+macro_rules! one {
+    () => {
+        1
+    };
+}
+
 fn main() {
     // these should warn
     {
@@ -24,6 +30,12 @@ fn main() {
         // including newlines
         writeln!(std::io::stdout(), "test\ntest").unwrap();
         writeln!(std::io::stderr(), "test\ntest").unwrap();
+
+        let value = 1;
+        writeln!(std::io::stderr(), "with {}", value).unwrap();
+        writeln!(std::io::stderr(), "with {} {}", 2, value).unwrap();
+        writeln!(std::io::stderr(), "with {value}").unwrap();
+        writeln!(std::io::stderr(), "macro arg {}", one!()).unwrap();
     }
     // these should not warn, different destination
     {
diff --git a/tests/ui/explicit_write.stderr b/tests/ui/explicit_write.stderr
index 9feef9c0dc8..29ae0cdece2 100644
--- a/tests/ui/explicit_write.stderr
+++ b/tests/ui/explicit_write.stderr
@@ -1,5 +1,5 @@
 error: use of `write!(stdout(), ...).unwrap()`
-  --> $DIR/explicit_write.rs:17:9
+  --> $DIR/explicit_write.rs:23:9
    |
 LL |         write!(std::io::stdout(), "test").unwrap();
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `print!("test")`
@@ -7,46 +7,70 @@ LL |         write!(std::io::stdout(), "test").unwrap();
    = note: `-D clippy::explicit-write` implied by `-D warnings`
 
 error: use of `write!(stderr(), ...).unwrap()`
-  --> $DIR/explicit_write.rs:18:9
+  --> $DIR/explicit_write.rs:24:9
    |
 LL |         write!(std::io::stderr(), "test").unwrap();
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `eprint!("test")`
 
 error: use of `writeln!(stdout(), ...).unwrap()`
-  --> $DIR/explicit_write.rs:19:9
+  --> $DIR/explicit_write.rs:25:9
    |
 LL |         writeln!(std::io::stdout(), "test").unwrap();
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `println!("test")`
 
 error: use of `writeln!(stderr(), ...).unwrap()`
-  --> $DIR/explicit_write.rs:20:9
+  --> $DIR/explicit_write.rs:26:9
    |
 LL |         writeln!(std::io::stderr(), "test").unwrap();
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `eprintln!("test")`
 
 error: use of `stdout().write_fmt(...).unwrap()`
-  --> $DIR/explicit_write.rs:21:9
+  --> $DIR/explicit_write.rs:27:9
    |
 LL |         std::io::stdout().write_fmt(format_args!("test")).unwrap();
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `print!("test")`
 
 error: use of `stderr().write_fmt(...).unwrap()`
-  --> $DIR/explicit_write.rs:22:9
+  --> $DIR/explicit_write.rs:28:9
    |
 LL |         std::io::stderr().write_fmt(format_args!("test")).unwrap();
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `eprint!("test")`
 
 error: use of `writeln!(stdout(), ...).unwrap()`
-  --> $DIR/explicit_write.rs:25:9
+  --> $DIR/explicit_write.rs:31:9
    |
 LL |         writeln!(std::io::stdout(), "test/ntest").unwrap();
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `println!("test/ntest")`
 
 error: use of `writeln!(stderr(), ...).unwrap()`
-  --> $DIR/explicit_write.rs:26:9
+  --> $DIR/explicit_write.rs:32:9
    |
 LL |         writeln!(std::io::stderr(), "test/ntest").unwrap();
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `eprintln!("test/ntest")`
 
-error: aborting due to 8 previous errors
+error: use of `writeln!(stderr(), ...).unwrap()`
+  --> $DIR/explicit_write.rs:35:9
+   |
+LL |         writeln!(std::io::stderr(), "with {}", value).unwrap();
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `eprintln!("with {}", value)`
+
+error: use of `writeln!(stderr(), ...).unwrap()`
+  --> $DIR/explicit_write.rs:36:9
+   |
+LL |         writeln!(std::io::stderr(), "with {} {}", 2, value).unwrap();
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `eprintln!("with {} {}", 2, value)`
+
+error: use of `writeln!(stderr(), ...).unwrap()`
+  --> $DIR/explicit_write.rs:37:9
+   |
+LL |         writeln!(std::io::stderr(), "with {value}").unwrap();
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `eprintln!("with {value}")`
+
+error: use of `writeln!(stderr(), ...).unwrap()`
+  --> $DIR/explicit_write.rs:38:9
+   |
+LL |         writeln!(std::io::stderr(), "macro arg {}", one!()).unwrap();
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `eprintln!("macro arg {}", one!())`
+
+error: aborting due to 12 previous errors
 
diff --git a/tests/ui/explicit_write_non_rustfix.rs b/tests/ui/explicit_write_non_rustfix.rs
deleted file mode 100644
index f21e8ef935b..00000000000
--- a/tests/ui/explicit_write_non_rustfix.rs
+++ /dev/null
@@ -1,8 +0,0 @@
-#![allow(unused_imports, clippy::blacklisted_name)]
-#![warn(clippy::explicit_write)]
-
-fn main() {
-    use std::io::Write;
-    let bar = "bar";
-    writeln!(std::io::stderr(), "foo {}", bar).unwrap();
-}
diff --git a/tests/ui/explicit_write_non_rustfix.stderr b/tests/ui/explicit_write_non_rustfix.stderr
deleted file mode 100644
index b94ec6403dd..00000000000
--- a/tests/ui/explicit_write_non_rustfix.stderr
+++ /dev/null
@@ -1,11 +0,0 @@
-error: use of `writeln!(stderr(), ...).unwrap()`
-  --> $DIR/explicit_write_non_rustfix.rs:7:5
-   |
-LL |     writeln!(std::io::stderr(), "foo {}", bar).unwrap();
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `-D clippy::explicit-write` implied by `-D warnings`
-   = help: consider using `eprintln!` instead
-
-error: aborting due to previous error
-
diff --git a/tests/ui/manual_assert.edition2018.fixed b/tests/ui/manual_assert.edition2018.fixed
index 6c2a25c37d8..d0bc640db88 100644
--- a/tests/ui/manual_assert.edition2018.fixed
+++ b/tests/ui/manual_assert.edition2018.fixed
@@ -6,6 +6,12 @@
 #![warn(clippy::manual_assert)]
 #![allow(clippy::nonminimal_bool)]
 
+macro_rules! one {
+    () => {
+        1
+    };
+}
+
 fn main() {
     let a = vec![1, 2, 3];
     let c = Some(2);
@@ -42,4 +48,5 @@ fn main() {
     assert!(!(a.is_empty() && !b.is_empty()), "panic3");
     assert!(!(b.is_empty() || a.is_empty()), "panic4");
     assert!(!(a.is_empty() || !b.is_empty()), "panic5");
+    assert!(!a.is_empty(), "with expansion {}", one!());
 }
diff --git a/tests/ui/manual_assert.edition2018.stderr b/tests/ui/manual_assert.edition2018.stderr
index 77511631e44..a0f31afd6eb 100644
--- a/tests/ui/manual_assert.edition2018.stderr
+++ b/tests/ui/manual_assert.edition2018.stderr
@@ -1,5 +1,5 @@
 error: only a `panic!` in `if`-then statement
-  --> $DIR/manual_assert.rs:24:5
+  --> $DIR/manual_assert.rs:30:5
    |
 LL | /     if !a.is_empty() {
 LL | |         panic!("qaqaq{:?}", a);
@@ -9,7 +9,7 @@ LL | |     }
    = note: `-D clippy::manual-assert` implied by `-D warnings`
 
 error: only a `panic!` in `if`-then statement
-  --> $DIR/manual_assert.rs:27:5
+  --> $DIR/manual_assert.rs:33:5
    |
 LL | /     if !a.is_empty() {
 LL | |         panic!("qwqwq");
@@ -17,7 +17,7 @@ LL | |     }
    | |_____^ help: try: `assert!(a.is_empty(), "qwqwq");`
 
 error: only a `panic!` in `if`-then statement
-  --> $DIR/manual_assert.rs:44:5
+  --> $DIR/manual_assert.rs:50:5
    |
 LL | /     if b.is_empty() {
 LL | |         panic!("panic1");
@@ -25,7 +25,7 @@ LL | |     }
    | |_____^ help: try: `assert!(!b.is_empty(), "panic1");`
 
 error: only a `panic!` in `if`-then statement
-  --> $DIR/manual_assert.rs:47:5
+  --> $DIR/manual_assert.rs:53:5
    |
 LL | /     if b.is_empty() && a.is_empty() {
 LL | |         panic!("panic2");
@@ -33,7 +33,7 @@ LL | |     }
    | |_____^ help: try: `assert!(!(b.is_empty() && a.is_empty()), "panic2");`
 
 error: only a `panic!` in `if`-then statement
-  --> $DIR/manual_assert.rs:50:5
+  --> $DIR/manual_assert.rs:56:5
    |
 LL | /     if a.is_empty() && !b.is_empty() {
 LL | |         panic!("panic3");
@@ -41,7 +41,7 @@ LL | |     }
    | |_____^ help: try: `assert!(!(a.is_empty() && !b.is_empty()), "panic3");`
 
 error: only a `panic!` in `if`-then statement
-  --> $DIR/manual_assert.rs:53:5
+  --> $DIR/manual_assert.rs:59:5
    |
 LL | /     if b.is_empty() || a.is_empty() {
 LL | |         panic!("panic4");
@@ -49,12 +49,20 @@ LL | |     }
    | |_____^ help: try: `assert!(!(b.is_empty() || a.is_empty()), "panic4");`
 
 error: only a `panic!` in `if`-then statement
-  --> $DIR/manual_assert.rs:56:5
+  --> $DIR/manual_assert.rs:62:5
    |
 LL | /     if a.is_empty() || !b.is_empty() {
 LL | |         panic!("panic5");
 LL | |     }
    | |_____^ help: try: `assert!(!(a.is_empty() || !b.is_empty()), "panic5");`
 
-error: aborting due to 7 previous errors
+error: only a `panic!` in `if`-then statement
+  --> $DIR/manual_assert.rs:65:5
+   |
+LL | /     if a.is_empty() {
+LL | |         panic!("with expansion {}", one!())
+LL | |     }
+   | |_____^ help: try: `assert!(!a.is_empty(), "with expansion {}", one!());`
+
+error: aborting due to 8 previous errors
 
diff --git a/tests/ui/manual_assert.edition2021.fixed b/tests/ui/manual_assert.edition2021.fixed
index 6c2a25c37d8..d0bc640db88 100644
--- a/tests/ui/manual_assert.edition2021.fixed
+++ b/tests/ui/manual_assert.edition2021.fixed
@@ -6,6 +6,12 @@
 #![warn(clippy::manual_assert)]
 #![allow(clippy::nonminimal_bool)]
 
+macro_rules! one {
+    () => {
+        1
+    };
+}
+
 fn main() {
     let a = vec![1, 2, 3];
     let c = Some(2);
@@ -42,4 +48,5 @@ fn main() {
     assert!(!(a.is_empty() && !b.is_empty()), "panic3");
     assert!(!(b.is_empty() || a.is_empty()), "panic4");
     assert!(!(a.is_empty() || !b.is_empty()), "panic5");
+    assert!(!a.is_empty(), "with expansion {}", one!());
 }
diff --git a/tests/ui/manual_assert.edition2021.stderr b/tests/ui/manual_assert.edition2021.stderr
index 77511631e44..a0f31afd6eb 100644
--- a/tests/ui/manual_assert.edition2021.stderr
+++ b/tests/ui/manual_assert.edition2021.stderr
@@ -1,5 +1,5 @@
 error: only a `panic!` in `if`-then statement
-  --> $DIR/manual_assert.rs:24:5
+  --> $DIR/manual_assert.rs:30:5
    |
 LL | /     if !a.is_empty() {
 LL | |         panic!("qaqaq{:?}", a);
@@ -9,7 +9,7 @@ LL | |     }
    = note: `-D clippy::manual-assert` implied by `-D warnings`
 
 error: only a `panic!` in `if`-then statement
-  --> $DIR/manual_assert.rs:27:5
+  --> $DIR/manual_assert.rs:33:5
    |
 LL | /     if !a.is_empty() {
 LL | |         panic!("qwqwq");
@@ -17,7 +17,7 @@ LL | |     }
    | |_____^ help: try: `assert!(a.is_empty(), "qwqwq");`
 
 error: only a `panic!` in `if`-then statement
-  --> $DIR/manual_assert.rs:44:5
+  --> $DIR/manual_assert.rs:50:5
    |
 LL | /     if b.is_empty() {
 LL | |         panic!("panic1");
@@ -25,7 +25,7 @@ LL | |     }
    | |_____^ help: try: `assert!(!b.is_empty(), "panic1");`
 
 error: only a `panic!` in `if`-then statement
-  --> $DIR/manual_assert.rs:47:5
+  --> $DIR/manual_assert.rs:53:5
    |
 LL | /     if b.is_empty() && a.is_empty() {
 LL | |         panic!("panic2");
@@ -33,7 +33,7 @@ LL | |     }
    | |_____^ help: try: `assert!(!(b.is_empty() && a.is_empty()), "panic2");`
 
 error: only a `panic!` in `if`-then statement
-  --> $DIR/manual_assert.rs:50:5
+  --> $DIR/manual_assert.rs:56:5
    |
 LL | /     if a.is_empty() && !b.is_empty() {
 LL | |         panic!("panic3");
@@ -41,7 +41,7 @@ LL | |     }
    | |_____^ help: try: `assert!(!(a.is_empty() && !b.is_empty()), "panic3");`
 
 error: only a `panic!` in `if`-then statement
-  --> $DIR/manual_assert.rs:53:5
+  --> $DIR/manual_assert.rs:59:5
    |
 LL | /     if b.is_empty() || a.is_empty() {
 LL | |         panic!("panic4");
@@ -49,12 +49,20 @@ LL | |     }
    | |_____^ help: try: `assert!(!(b.is_empty() || a.is_empty()), "panic4");`
 
 error: only a `panic!` in `if`-then statement
-  --> $DIR/manual_assert.rs:56:5
+  --> $DIR/manual_assert.rs:62:5
    |
 LL | /     if a.is_empty() || !b.is_empty() {
 LL | |         panic!("panic5");
 LL | |     }
    | |_____^ help: try: `assert!(!(a.is_empty() || !b.is_empty()), "panic5");`
 
-error: aborting due to 7 previous errors
+error: only a `panic!` in `if`-then statement
+  --> $DIR/manual_assert.rs:65:5
+   |
+LL | /     if a.is_empty() {
+LL | |         panic!("with expansion {}", one!())
+LL | |     }
+   | |_____^ help: try: `assert!(!a.is_empty(), "with expansion {}", one!());`
+
+error: aborting due to 8 previous errors
 
diff --git a/tests/ui/manual_assert.rs b/tests/ui/manual_assert.rs
index d3e0897488f..027747d8386 100644
--- a/tests/ui/manual_assert.rs
+++ b/tests/ui/manual_assert.rs
@@ -6,6 +6,12 @@
 #![warn(clippy::manual_assert)]
 #![allow(clippy::nonminimal_bool)]
 
+macro_rules! one {
+    () => {
+        1
+    };
+}
+
 fn main() {
     let a = vec![1, 2, 3];
     let c = Some(2);
@@ -56,4 +62,7 @@ fn main() {
     if a.is_empty() || !b.is_empty() {
         panic!("panic5");
     }
+    if a.is_empty() {
+        panic!("with expansion {}", one!())
+    }
 }