about summary refs log tree commit diff
diff options
context:
space:
mode:
authorStuart Cook <Zalathar@users.noreply.github.com>2025-01-01 16:35:30 +1100
committerGitHub <noreply@github.com>2025-01-01 16:35:30 +1100
commit1ea1db5b0875c579c9b9e4d078c2ee4bf0ffe6e5 (patch)
tree8bdd10c1ab1834d3237f0139d1b1040e3aac157e
parent0204259780aaf73d715709478c3e758607c39570 (diff)
parent62c3c9a5ae2072a04ba5f5d84055d38dcd043427 (diff)
downloadrust-1ea1db5b0875c579c9b9e4d078c2ee4bf0ffe6e5.tar.gz
rust-1ea1db5b0875c579c9b9e4d078c2ee4bf0ffe6e5.zip
Rollup merge of #134877 - DavisRayM:129966-format-string-help-message, r=estebank
add suggestion for wrongly ordered format parameters

Add suggestion for wrongly ordered format parameters like `?#`.

Supersedes #131004
Fix #129966
-rw-r--r--compiler/rustc_builtin_macros/messages.ftl2
-rw-r--r--compiler/rustc_builtin_macros/src/errors.rs11
-rw-r--r--compiler/rustc_builtin_macros/src/format.rs7
-rw-r--r--compiler/rustc_parse_format/src/lib.rs35
-rw-r--r--tests/ui/fmt/suggest-wrongly-order-format-parameter.fixed25
-rw-r--r--tests/ui/fmt/suggest-wrongly-order-format-parameter.rs25
-rw-r--r--tests/ui/fmt/suggest-wrongly-order-format-parameter.stderr35
7 files changed, 140 insertions, 0 deletions
diff --git a/compiler/rustc_builtin_macros/messages.ftl b/compiler/rustc_builtin_macros/messages.ftl
index 7a31d2a2239..4cac7cb93f5 100644
--- a/compiler/rustc_builtin_macros/messages.ftl
+++ b/compiler/rustc_builtin_macros/messages.ftl
@@ -197,6 +197,8 @@ builtin_macros_format_redundant_args = redundant {$n ->
 
 builtin_macros_format_remove_raw_ident = remove the `r#`
 
+builtin_macros_format_reorder_format_parameter = did you mean `{$replacement}`?
+
 builtin_macros_format_requires_string = requires at least a format string argument
 
 builtin_macros_format_string_invalid = invalid format string: {$desc}
diff --git a/compiler/rustc_builtin_macros/src/errors.rs b/compiler/rustc_builtin_macros/src/errors.rs
index 1abdfdb9c65..6213bd802c7 100644
--- a/compiler/rustc_builtin_macros/src/errors.rs
+++ b/compiler/rustc_builtin_macros/src/errors.rs
@@ -618,6 +618,17 @@ pub(crate) enum InvalidFormatStringSuggestion {
         #[primary_span]
         span: Span,
     },
+    #[suggestion(
+        builtin_macros_format_reorder_format_parameter,
+        code = "{replacement}",
+        style = "verbose",
+        applicability = "machine-applicable"
+    )]
+    ReorderFormatParameter {
+        #[primary_span]
+        span: Span,
+        replacement: String,
+    },
 }
 
 #[derive(Diagnostic)]
diff --git a/compiler/rustc_builtin_macros/src/format.rs b/compiler/rustc_builtin_macros/src/format.rs
index 0112499c509..5202fe26c40 100644
--- a/compiler/rustc_builtin_macros/src/format.rs
+++ b/compiler/rustc_builtin_macros/src/format.rs
@@ -321,6 +321,13 @@ fn make_format_args(
                     e.sugg_ = Some(errors::InvalidFormatStringSuggestion::RemoveRawIdent { span })
                 }
             }
+            parse::Suggestion::ReorderFormatParameter(span, replacement) => {
+                let span = fmt_span.from_inner(InnerSpan::new(span.start, span.end));
+                e.sugg_ = Some(errors::InvalidFormatStringSuggestion::ReorderFormatParameter {
+                    span,
+                    replacement,
+                });
+            }
         }
         let guar = ecx.dcx().emit_err(e);
         return ExpandResult::Ready(Err(guar));
diff --git a/compiler/rustc_parse_format/src/lib.rs b/compiler/rustc_parse_format/src/lib.rs
index 1716f417969..9eb335cb34c 100644
--- a/compiler/rustc_parse_format/src/lib.rs
+++ b/compiler/rustc_parse_format/src/lib.rs
@@ -221,6 +221,11 @@ pub enum Suggestion {
     /// Remove `r#` from identifier:
     /// `format!("{r#foo}")` -> `format!("{foo}")`
     RemoveRawIdent(InnerSpan),
+    /// Reorder format parameter:
+    /// `format!("{foo:?#}")` -> `format!("{foo:#?}")`
+    /// `format!("{foo:?x}")` -> `format!("{foo:x?}")`
+    /// `format!("{foo:?X}")` -> `format!("{foo:X?}")`
+    ReorderFormatParameter(InnerSpan, string::String),
 }
 
 /// The parser structure for interpreting the input format string. This is
@@ -731,6 +736,12 @@ impl<'a> Parser<'a> {
             }
         } else if self.consume('?') {
             spec.ty = "?";
+            if let Some(&(_, maybe)) = self.cur.peek() {
+                match maybe {
+                    '#' | 'x' | 'X' => self.suggest_format_parameter(maybe),
+                    _ => (),
+                }
+            }
         } else {
             spec.ty = self.word();
             if !spec.ty.is_empty() {
@@ -932,6 +943,30 @@ impl<'a> Parser<'a> {
             }
         }
     }
+
+    fn suggest_format_parameter(&mut self, c: char) {
+        let replacement = match c {
+            '#' => "#?",
+            'x' => "x?",
+            'X' => "X?",
+            _ => return,
+        };
+        let Some(pos) = self.consume_pos(c) else {
+            return;
+        };
+
+        let span = self.span(pos - 1, pos + 1);
+        let pos = self.to_span_index(pos);
+
+        self.errors.insert(0, ParseError {
+            description: format!("expected `}}`, found `{c}`"),
+            note: None,
+            label: "expected `'}'`".into(),
+            span: pos.to(pos),
+            secondary_label: None,
+            suggestion: Suggestion::ReorderFormatParameter(span, format!("{replacement}")),
+        })
+    }
 }
 
 /// Finds the indices of all characters that have been processed and differ between the actual
diff --git a/tests/ui/fmt/suggest-wrongly-order-format-parameter.fixed b/tests/ui/fmt/suggest-wrongly-order-format-parameter.fixed
new file mode 100644
index 00000000000..a080a65854a
--- /dev/null
+++ b/tests/ui/fmt/suggest-wrongly-order-format-parameter.fixed
@@ -0,0 +1,25 @@
+//! Regression test for https://github.com/rust-lang/rust/issues/129966
+//!
+//! Ensure we provide suggestion for wrongly ordered format parameters.
+
+//@ run-rustfix
+#![allow(dead_code)]
+
+#[derive(Debug)]
+struct Foo(u8, u8);
+
+fn main() {
+    let f = Foo(1, 2);
+
+    println!("{f:#?}");
+    //~^ ERROR invalid format string: expected `}`, found `#`
+    //~| HELP did you mean `#?`?
+
+    println!("{f:x?}");
+    //~^ ERROR invalid format string: expected `}`, found `x`
+    //~| HELP did you mean `x?`?
+
+    println!("{f:X?}");
+    //~^ ERROR invalid format string: expected `}`, found `X`
+    //~| HELP did you mean `X?`?
+}
diff --git a/tests/ui/fmt/suggest-wrongly-order-format-parameter.rs b/tests/ui/fmt/suggest-wrongly-order-format-parameter.rs
new file mode 100644
index 00000000000..830dafd4479
--- /dev/null
+++ b/tests/ui/fmt/suggest-wrongly-order-format-parameter.rs
@@ -0,0 +1,25 @@
+//! Regression test for https://github.com/rust-lang/rust/issues/129966
+//!
+//! Ensure we provide suggestion for wrongly ordered format parameters.
+
+//@ run-rustfix
+#![allow(dead_code)]
+
+#[derive(Debug)]
+struct Foo(u8, u8);
+
+fn main() {
+    let f = Foo(1, 2);
+
+    println!("{f:?#}");
+    //~^ ERROR invalid format string: expected `}`, found `#`
+    //~| HELP did you mean `#?`?
+
+    println!("{f:?x}");
+    //~^ ERROR invalid format string: expected `}`, found `x`
+    //~| HELP did you mean `x?`?
+
+    println!("{f:?X}");
+    //~^ ERROR invalid format string: expected `}`, found `X`
+    //~| HELP did you mean `X?`?
+}
diff --git a/tests/ui/fmt/suggest-wrongly-order-format-parameter.stderr b/tests/ui/fmt/suggest-wrongly-order-format-parameter.stderr
new file mode 100644
index 00000000000..fe693d2e904
--- /dev/null
+++ b/tests/ui/fmt/suggest-wrongly-order-format-parameter.stderr
@@ -0,0 +1,35 @@
+error: invalid format string: expected `}`, found `#`
+  --> $DIR/suggest-wrongly-order-format-parameter.rs:14:19
+   |
+LL |     println!("{f:?#}");
+   |                   ^ expected `'}'` in format string
+   |
+help: did you mean `#?`?
+   |
+LL |     println!("{f:#?}");
+   |                  ~~
+
+error: invalid format string: expected `}`, found `x`
+  --> $DIR/suggest-wrongly-order-format-parameter.rs:18:19
+   |
+LL |     println!("{f:?x}");
+   |                   ^ expected `'}'` in format string
+   |
+help: did you mean `x?`?
+   |
+LL |     println!("{f:x?}");
+   |                  ~~
+
+error: invalid format string: expected `}`, found `X`
+  --> $DIR/suggest-wrongly-order-format-parameter.rs:22:19
+   |
+LL |     println!("{f:?X}");
+   |                   ^ expected `'}'` in format string
+   |
+help: did you mean `X?`?
+   |
+LL |     println!("{f:X?}");
+   |                  ~~
+
+error: aborting due to 3 previous errors
+