about summary refs log tree commit diff
diff options
context:
space:
mode:
authorStuart Cook <Zalathar@users.noreply.github.com>2025-05-04 13:21:07 +1000
committerGitHub <noreply@github.com>2025-05-04 13:21:07 +1000
commit9c949b0373ad51a9285c9dc86ee853a6137bc9f9 (patch)
tree2241d8d3ea056eb96d0f06ea010bf82f499f5914
parented7590f1a0932341f938e34bfb69c72bbc255fcf (diff)
parent873ca5fa04b79da80ca779e0e577f06a07cea8d3 (diff)
downloadrust-9c949b0373ad51a9285c9dc86ee853a6137bc9f9.tar.gz
rust-9c949b0373ad51a9285c9dc86ee853a6137bc9f9.zip
Rollup merge of #140286 - xizheyin:issue-139104, r=lcnr
Check if format argument is identifier to avoid error err-emit

Fixes #139104

When `argument` is not an identifier, it should not be considered a field access. I checked this and if not emit an invalid format string error. I think we could do with a little finer error handling, I'll open an issue to track this down later.

The first commit submits the ui test, the second commits the code and the changes to the test output.

r? compiler
-rw-r--r--compiler/rustc_parse_format/src/lib.rs29
-rw-r--r--tests/ui/parser/issues/invalid-parse-format-issue-139104.rs13
-rw-r--r--tests/ui/parser/issues/invalid-parse-format-issue-139104.stderr92
3 files changed, 134 insertions, 0 deletions
diff --git a/compiler/rustc_parse_format/src/lib.rs b/compiler/rustc_parse_format/src/lib.rs
index c59e6cb5c33..999e7159274 100644
--- a/compiler/rustc_parse_format/src/lib.rs
+++ b/compiler/rustc_parse_format/src/lib.rs
@@ -100,6 +100,30 @@ pub struct Argument<'a> {
     pub format: FormatSpec<'a>,
 }
 
+impl<'a> Argument<'a> {
+    pub fn is_identifier(&self) -> bool {
+        matches!(self.position, Position::ArgumentNamed(_))
+            && matches!(
+                self.format,
+                FormatSpec {
+                    fill: None,
+                    fill_span: None,
+                    align: AlignUnknown,
+                    sign: None,
+                    alternate: false,
+                    zero_pad: false,
+                    debug_hex: None,
+                    precision: CountImplied,
+                    precision_span: None,
+                    width: CountImplied,
+                    width_span: None,
+                    ty: "",
+                    ty_span: None,
+                },
+            )
+    }
+}
+
 /// Specification for the formatting of an argument in the format string.
 #[derive(Copy, Clone, Debug, PartialEq)]
 pub struct FormatSpec<'a> {
@@ -894,6 +918,11 @@ impl<'a> Parser<'a> {
     }
 
     fn suggest_positional_arg_instead_of_captured_arg(&mut self, arg: Argument<'a>) {
+        // If the argument is not an identifier, it is not a field access.
+        if !arg.is_identifier() {
+            return;
+        }
+
         if let Some(end) = self.consume_pos('.') {
             let byte_pos = self.to_span_index(end);
             let start = InnerOffset(byte_pos.0 + 1);
diff --git a/tests/ui/parser/issues/invalid-parse-format-issue-139104.rs b/tests/ui/parser/issues/invalid-parse-format-issue-139104.rs
new file mode 100644
index 00000000000..7644df8be49
--- /dev/null
+++ b/tests/ui/parser/issues/invalid-parse-format-issue-139104.rs
@@ -0,0 +1,13 @@
+fn main() {
+    println!("{foo:_1.4}", foo = 3.14); //~ ERROR invalid format string: expected `}`, found `.`
+    println!("{0:_1.4}", 1.11); //~ ERROR invalid format string: expected `}`, found `.`
+    println!("{:_1.4}", 3.14); //~ ERROR invalid format string: expected `}`, found `.`
+
+    println!("{foo:_1.4", foo = 3.14); //~ ERROR invalid format string: expected `}`, found `.`
+    println!("{0:_1.4", 1.11); //~ ERROR invalid format string: expected `}`, found `.`
+    println!("{:_1.4", 3.14); //~ ERROR invalid format string: expected `}`, found `.`
+
+    println!("{  0", 1.11); //~ ERROR invalid format string: expected `}`, found `0`
+    println!("{foo:1.4_1.4}", foo = 3.14); //~ ERROR invalid format string: expected `}`, found `.`
+    println!("{0:1.4_1.4}", 3.14); //~ ERROR invalid format string: expected `}`, found `.`
+}
diff --git a/tests/ui/parser/issues/invalid-parse-format-issue-139104.stderr b/tests/ui/parser/issues/invalid-parse-format-issue-139104.stderr
new file mode 100644
index 00000000000..202aa450cab
--- /dev/null
+++ b/tests/ui/parser/issues/invalid-parse-format-issue-139104.stderr
@@ -0,0 +1,92 @@
+error: invalid format string: expected `}`, found `.`
+  --> $DIR/invalid-parse-format-issue-139104.rs:2:22
+   |
+LL |     println!("{foo:_1.4}", foo = 3.14);
+   |               -      ^ expected `}` in format string
+   |               |
+   |               because of this opening brace
+   |
+   = note: if you intended to print `{`, you can escape it using `{{`
+
+error: invalid format string: expected `}`, found `.`
+  --> $DIR/invalid-parse-format-issue-139104.rs:3:20
+   |
+LL |     println!("{0:_1.4}", 1.11);
+   |               -    ^ expected `}` in format string
+   |               |
+   |               because of this opening brace
+   |
+   = note: if you intended to print `{`, you can escape it using `{{`
+
+error: invalid format string: expected `}`, found `.`
+  --> $DIR/invalid-parse-format-issue-139104.rs:4:19
+   |
+LL |     println!("{:_1.4}", 3.14);
+   |               -   ^ expected `}` in format string
+   |               |
+   |               because of this opening brace
+   |
+   = note: if you intended to print `{`, you can escape it using `{{`
+
+error: invalid format string: expected `}`, found `.`
+  --> $DIR/invalid-parse-format-issue-139104.rs:6:22
+   |
+LL |     println!("{foo:_1.4", foo = 3.14);
+   |               -      ^ expected `}` in format string
+   |               |
+   |               because of this opening brace
+   |
+   = note: if you intended to print `{`, you can escape it using `{{`
+
+error: invalid format string: expected `}`, found `.`
+  --> $DIR/invalid-parse-format-issue-139104.rs:7:20
+   |
+LL |     println!("{0:_1.4", 1.11);
+   |               -    ^ expected `}` in format string
+   |               |
+   |               because of this opening brace
+   |
+   = note: if you intended to print `{`, you can escape it using `{{`
+
+error: invalid format string: expected `}`, found `.`
+  --> $DIR/invalid-parse-format-issue-139104.rs:8:19
+   |
+LL |     println!("{:_1.4", 3.14);
+   |               -   ^ expected `}` in format string
+   |               |
+   |               because of this opening brace
+   |
+   = note: if you intended to print `{`, you can escape it using `{{`
+
+error: invalid format string: expected `}`, found `0`
+  --> $DIR/invalid-parse-format-issue-139104.rs:10:18
+   |
+LL |     println!("{  0", 1.11);
+   |               -  ^ expected `}` in format string
+   |               |
+   |               because of this opening brace
+   |
+   = note: if you intended to print `{`, you can escape it using `{{`
+
+error: invalid format string: expected `}`, found `.`
+  --> $DIR/invalid-parse-format-issue-139104.rs:11:25
+   |
+LL |     println!("{foo:1.4_1.4}", foo = 3.14);
+   |               -         ^ expected `}` in format string
+   |               |
+   |               because of this opening brace
+   |
+   = note: if you intended to print `{`, you can escape it using `{{`
+
+error: invalid format string: expected `}`, found `.`
+  --> $DIR/invalid-parse-format-issue-139104.rs:12:23
+   |
+LL |     println!("{0:1.4_1.4}", 3.14);
+   |               -       ^ expected `}` in format string
+   |               |
+   |               because of this opening brace
+   |
+   = note: if you intended to print `{`, you can escape it using `{{`
+
+error: aborting due to 9 previous errors
+