about summary refs log tree commit diff
diff options
context:
space:
mode:
authorxizheyin <xizheyin@smail.nju.edu.cn>2025-04-25 17:53:40 +0800
committerxizheyin <xizheyin@smail.nju.edu.cn>2025-04-25 19:07:30 +0800
commit64867c68f4eb537215e65268903803f44f1fe6b6 (patch)
tree5b03dbfce6aafbf1522b659fa2532064fcbefd81
parent44232a67c320c8df31e2b82ae15d2ec7c83ec759 (diff)
downloadrust-64867c68f4eb537215e65268903803f44f1fe6b6.tar.gz
rust-64867c68f4eb537215e65268903803f44f1fe6b6.zip
Check if format argument is identifier to avoid error err-emit
Signed-off-by: xizheyin <xizheyin@smail.nju.edu.cn>
-rw-r--r--compiler/rustc_parse_format/src/lib.rs135
-rw-r--r--tests/ui/parser/issues/invalid-parse-format-issue-139104.rs10
-rw-r--r--tests/ui/parser/issues/invalid-parse-format-issue-139104.stderr52
3 files changed, 109 insertions, 88 deletions
diff --git a/compiler/rustc_parse_format/src/lib.rs b/compiler/rustc_parse_format/src/lib.rs
index c59e6cb5c33..c356a97a55a 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,52 +918,73 @@ impl<'a> Parser<'a> {
     }
 
     fn suggest_positional_arg_instead_of_captured_arg(&mut self, arg: Argument<'a>) {
-        if let Some(end) = self.consume_pos('.') {
-            let byte_pos = self.to_span_index(end);
-            let start = InnerOffset(byte_pos.0 + 1);
-            let field = self.argument(start);
-            // We can only parse simple `foo.bar` field access or `foo.0` tuple index access, any
-            // deeper nesting, or another type of expression, like method calls, are not supported
-            if !self.consume('}') {
-                return;
-            }
-            if let ArgumentNamed(_) = arg.position {
-                match field.position {
-                    ArgumentNamed(_) => {
-                        self.errors.insert(
-                            0,
-                            ParseError {
-                                description: "field access isn't supported".to_string(),
-                                note: None,
-                                label: "not supported".to_string(),
-                                span: InnerSpan::new(
-                                    arg.position_span.start,
-                                    field.position_span.end,
-                                ),
-                                secondary_label: None,
-                                suggestion: Suggestion::UsePositional,
-                            },
-                        );
-                    }
-                    ArgumentIs(_) => {
-                        self.errors.insert(
-                            0,
-                            ParseError {
-                                description: "tuple index access isn't supported".to_string(),
-                                note: None,
-                                label: "not supported".to_string(),
-                                span: InnerSpan::new(
-                                    arg.position_span.start,
-                                    field.position_span.end,
-                                ),
-                                secondary_label: None,
-                                suggestion: Suggestion::UsePositional,
-                            },
-                        );
-                    }
-                    _ => {}
-                };
+        // If the argument is an identifier, it may be a field access.
+        if arg.is_identifier() {
+            if let Some(end) = self.consume_pos('.') {
+                let byte_pos = self.to_span_index(end);
+                let start = InnerOffset(byte_pos.0 + 1);
+                let field = self.argument(start);
+                // We can only parse simple `foo.bar` field access or `foo.0` tuple index access, any
+                // deeper nesting, or another type of expression, like method calls, are not supported
+                if !self.consume('}') {
+                    return;
+                }
+                if let ArgumentNamed(_) = arg.position {
+                    match field.position {
+                        ArgumentNamed(_) => {
+                            self.errors.insert(
+                                0,
+                                ParseError {
+                                    description: "field access isn't supported".to_string(),
+                                    note: None,
+                                    label: "not supported".to_string(),
+                                    span: InnerSpan::new(
+                                        arg.position_span.start,
+                                        field.position_span.end,
+                                    ),
+                                    secondary_label: None,
+                                    suggestion: Suggestion::UsePositional,
+                                },
+                            );
+                        }
+                        ArgumentIs(_) => {
+                            self.errors.insert(
+                                0,
+                                ParseError {
+                                    description: "tuple index access isn't supported".to_string(),
+                                    note: None,
+                                    label: "not supported".to_string(),
+                                    span: InnerSpan::new(
+                                        arg.position_span.start,
+                                        field.position_span.end,
+                                    ),
+                                    secondary_label: None,
+                                    suggestion: Suggestion::UsePositional,
+                                },
+                            );
+                        }
+                        _ => {}
+                    };
+                }
             }
+        } else if matches!(arg.position, ArgumentNamed(_) | ArgumentIs(_)) {
+            let arg_name = match arg.position {
+                ArgumentNamed(arg_name) => &format!("`{arg_name}`"),
+                ArgumentIs(arg_index) => &format!("at index `{arg_index}`"),
+                _ => unreachable!(),
+            };
+
+            self.errors.insert(
+                0,
+                ParseError {
+                    description: format!("invalid format string for argument {}", arg_name),
+                    note: None,
+                    label: format!("invalid format specifier for this argument"),
+                    span: InnerSpan::new(arg.position_span.start, arg.position_span.end),
+                    secondary_label: None,
+                    suggestion: Suggestion::None,
+                },
+            );
         }
     }
 
diff --git a/tests/ui/parser/issues/invalid-parse-format-issue-139104.rs b/tests/ui/parser/issues/invalid-parse-format-issue-139104.rs
index 40af6262356..0809235bb6d 100644
--- a/tests/ui/parser/issues/invalid-parse-format-issue-139104.rs
+++ b/tests/ui/parser/issues/invalid-parse-format-issue-139104.rs
@@ -1,8 +1,8 @@
 fn main() {
-    println!("{foo:_1.4}", foo = 3.14); //~ ERROR invalid format string: tuple index access isn't supported
-    println!("{foo:1.4_1.4}", foo = 3.14); //~ ERROR invalid format string: tuple index access isn't supported
-    println!("xxx{0:_1.4", 1.11); //~ ERROR invalid format string: expected `}`, found `.`
-    println!("{foo:_1.4", foo = 3.14); //~ ERROR invalid format string: expected `}`, found `.`
-    println!("xxx{0:_1.4", 1.11); //~ ERROR invalid format string: expected `}`, found `.`
+    println!("{foo:_1.4}", foo = 3.14); //~ ERROR invalid format string: invalid format string for argument `foo`
+    println!("{foo:1.4_1.4}", foo = 3.14); //~ ERROR invalid format string: invalid format string for argument `foo`
+    println!("xxx{0:_1.4}", 1.11); //~ ERROR invalid format string: invalid format string for argument at index `0`
+    println!("{foo:_1.4", foo = 3.14); //~ ERROR invalid format string: invalid format string for argument `foo`
+    println!("xxx{0:_1.4", 1.11); //~ ERROR invalid format string: invalid format string for argument at index `0`
     println!("xxx{  0", 1.11); //~ ERROR invalid format string: expected `}`, found `0`
 }
diff --git a/tests/ui/parser/issues/invalid-parse-format-issue-139104.stderr b/tests/ui/parser/issues/invalid-parse-format-issue-139104.stderr
index d0a8d0998a4..ceae8d051e5 100644
--- a/tests/ui/parser/issues/invalid-parse-format-issue-139104.stderr
+++ b/tests/ui/parser/issues/invalid-parse-format-issue-139104.stderr
@@ -1,56 +1,32 @@
-error: invalid format string: tuple index access isn't supported
+error: invalid format string: invalid format string for argument `foo`
   --> $DIR/invalid-parse-format-issue-139104.rs:2:16
    |
 LL |     println!("{foo:_1.4}", foo = 3.14);
-   |                ^^^^^^^^ not supported in format string
-   |
-help: consider using a positional formatting argument instead
-   |
-LL -     println!("{foo:_1.4}", foo = 3.14);
-LL +     println!("{0}", foo:_1.4, foo = 3.14);
-   |
+   |                ^^^ invalid format specifier for this argument in format string
 
-error: invalid format string: tuple index access isn't supported
+error: invalid format string: invalid format string for argument `foo`
   --> $DIR/invalid-parse-format-issue-139104.rs:3:16
    |
 LL |     println!("{foo:1.4_1.4}", foo = 3.14);
-   |                ^^^^^^^^^^^ not supported in format string
-   |
-help: consider using a positional formatting argument instead
-   |
-LL -     println!("{foo:1.4_1.4}", foo = 3.14);
-LL +     println!("{0}", foo:1.4_1.4, foo = 3.14);
-   |
+   |                ^^^ invalid format specifier for this argument in format string
 
-error: invalid format string: expected `}`, found `.`
-  --> $DIR/invalid-parse-format-issue-139104.rs:4:23
+error: invalid format string: invalid format string for argument at index `0`
+  --> $DIR/invalid-parse-format-issue-139104.rs:4:19
    |
-LL |     println!("xxx{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 `{{`
+LL |     println!("xxx{0:_1.4}", 1.11);
+   |                   ^ invalid format specifier for this argument in format string
 
-error: invalid format string: expected `}`, found `.`
-  --> $DIR/invalid-parse-format-issue-139104.rs:5:22
+error: invalid format string: invalid format string for argument `foo`
+  --> $DIR/invalid-parse-format-issue-139104.rs:5:16
    |
 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 `{{`
+   |                ^^^ invalid format specifier for this argument in format string
 
-error: invalid format string: expected `}`, found `.`
-  --> $DIR/invalid-parse-format-issue-139104.rs:6:23
+error: invalid format string: invalid format string for argument at index `0`
+  --> $DIR/invalid-parse-format-issue-139104.rs:6:19
    |
 LL |     println!("xxx{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 `{{`
+   |                   ^ invalid format specifier for this argument in format string
 
 error: invalid format string: expected `}`, found `0`
   --> $DIR/invalid-parse-format-issue-139104.rs:7:21