about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_builtin_macros/src/format.rs40
-rw-r--r--tests/ui/fmt/suggest-inline-args.rs28
-rw-r--r--tests/ui/fmt/suggest-inline-args.stderr57
3 files changed, 113 insertions, 12 deletions
diff --git a/compiler/rustc_builtin_macros/src/format.rs b/compiler/rustc_builtin_macros/src/format.rs
index 590db12a4cd..ede95dbf897 100644
--- a/compiler/rustc_builtin_macros/src/format.rs
+++ b/compiler/rustc_builtin_macros/src/format.rs
@@ -1,6 +1,6 @@
 use rustc_ast::ptr::P;
-use rustc_ast::token;
 use rustc_ast::tokenstream::TokenStream;
+use rustc_ast::{token, StmtKind};
 use rustc_ast::{
     Expr, ExprKind, FormatAlignment, FormatArgPosition, FormatArgPositionKind, FormatArgs,
     FormatArgsPiece, FormatArgument, FormatArgumentKind, FormatArguments, FormatCount,
@@ -163,7 +163,7 @@ fn make_format_args(
 
     let MacroInput { fmtstr: efmt, mut args, is_direct_literal } = input;
 
-    let (fmt_str, fmt_style, fmt_span) = match expr_to_spanned_string(ecx, efmt, msg) {
+    let (fmt_str, fmt_style, fmt_span) = match expr_to_spanned_string(ecx, efmt.clone(), msg) {
         Ok(mut fmt) if append_newline => {
             fmt.0 = Symbol::intern(&format!("{}\n", fmt.0));
             fmt
@@ -171,17 +171,33 @@ fn make_format_args(
         Ok(fmt) => fmt,
         Err(err) => {
             if let Some((mut err, suggested)) = err {
-                let sugg_fmt = match args.explicit_args().len() {
-                    0 => "{}".to_string(),
-                    _ => format!("{}{{}}", "{} ".repeat(args.explicit_args().len())),
-                };
                 if !suggested {
-                    err.span_suggestion(
-                        unexpanded_fmt_span.shrink_to_lo(),
-                        "you might be missing a string literal to format with",
-                        format!("\"{sugg_fmt}\", "),
-                        Applicability::MaybeIncorrect,
-                    );
+                    if let ExprKind::Block(block, None) = &efmt.kind
+                        && block.stmts.len() == 1
+                        && let StmtKind::Expr(expr) = &block.stmts[0].kind
+                        && let ExprKind::Path(None, path) = &expr.kind
+                            && path.is_potential_trivial_const_arg()
+                    {
+                        err.multipart_suggestion(
+                            "quote your inlined format argument to use as string literal",
+                            vec![
+                                (unexpanded_fmt_span.shrink_to_hi(), "\"".to_string()),
+                                (unexpanded_fmt_span.shrink_to_lo(), "\"".to_string()),
+                            ],
+                             Applicability::MaybeIncorrect,
+                        );
+                    } else {
+                        let sugg_fmt = match args.explicit_args().len() {
+                            0 => "{}".to_string(),
+                            _ => format!("{}{{}}", "{} ".repeat(args.explicit_args().len())),
+                        };
+                        err.span_suggestion(
+                            unexpanded_fmt_span.shrink_to_lo(),
+                            "you might be missing a string literal to format with",
+                            format!("\"{sugg_fmt}\", "),
+                            Applicability::MaybeIncorrect,
+                        );
+                    }
                 }
                 err.emit();
             }
diff --git a/tests/ui/fmt/suggest-inline-args.rs b/tests/ui/fmt/suggest-inline-args.rs
new file mode 100644
index 00000000000..515335ed9f4
--- /dev/null
+++ b/tests/ui/fmt/suggest-inline-args.rs
@@ -0,0 +1,28 @@
+mod foo {
+    pub fn bar() -> i32 {
+        1
+    }
+}
+
+fn bar() -> i32 {
+    2
+}
+
+fn main() {
+    let stderr = 3;
+    eprintln!({stderr});
+    //~^ ERROR format argument must be a string literal
+    //~| HELP quote your inlined format argument to use as string literal
+    eprintln!({1});
+    //~^ ERROR format argument must be a string literal
+    //~| HELP you might be missing a string literal to format with
+    eprintln!({foo::bar()});
+    //~^ ERROR format argument must be a string literal
+    //~| HELP you might be missing a string literal to format with
+    eprintln!({bar()});
+    //~^ ERROR format argument must be a string literal
+    //~| HELP you might be missing a string literal to format with
+    eprintln!({1; 2});
+    //~^ ERROR format argument must be a string literal
+    //~| HELP you might be missing a string literal to format with
+}
diff --git a/tests/ui/fmt/suggest-inline-args.stderr b/tests/ui/fmt/suggest-inline-args.stderr
new file mode 100644
index 00000000000..cf70568cf3f
--- /dev/null
+++ b/tests/ui/fmt/suggest-inline-args.stderr
@@ -0,0 +1,57 @@
+error: format argument must be a string literal
+  --> $DIR/suggest-inline-args.rs:13:15
+   |
+LL |     eprintln!({stderr});
+   |               ^^^^^^^^
+   |
+help: quote your inlined format argument to use as string literal
+   |
+LL |     eprintln!("{stderr}");
+   |               +        +
+
+error: format argument must be a string literal
+  --> $DIR/suggest-inline-args.rs:16:15
+   |
+LL |     eprintln!({1});
+   |               ^^^
+   |
+help: you might be missing a string literal to format with
+   |
+LL |     eprintln!("{}", {1});
+   |               +++++
+
+error: format argument must be a string literal
+  --> $DIR/suggest-inline-args.rs:19:15
+   |
+LL |     eprintln!({foo::bar()});
+   |               ^^^^^^^^^^^^
+   |
+help: you might be missing a string literal to format with
+   |
+LL |     eprintln!("{}", {foo::bar()});
+   |               +++++
+
+error: format argument must be a string literal
+  --> $DIR/suggest-inline-args.rs:22:15
+   |
+LL |     eprintln!({bar()});
+   |               ^^^^^^^
+   |
+help: you might be missing a string literal to format with
+   |
+LL |     eprintln!("{}", {bar()});
+   |               +++++
+
+error: format argument must be a string literal
+  --> $DIR/suggest-inline-args.rs:25:15
+   |
+LL |     eprintln!({1; 2});
+   |               ^^^^^^
+   |
+help: you might be missing a string literal to format with
+   |
+LL |     eprintln!("{}", {1; 2});
+   |               +++++
+
+error: aborting due to 5 previous errors
+