Skip to content

Commit 884e5e3

Browse files
committed
Check if format argument is identifier to avoid error err-emit
Signed-off-by: xizheyin <[email protected]>
1 parent 44232a6 commit 884e5e3

File tree

3 files changed

+112
-71
lines changed

3 files changed

+112
-71
lines changed

compiler/rustc_parse_format/src/lib.rs

+90-45
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,30 @@ pub struct Argument<'a> {
100100
pub format: FormatSpec<'a>,
101101
}
102102

103+
impl<'a> Argument<'a> {
104+
pub fn is_identifier(&self) -> bool {
105+
matches!(self.position, Position::ArgumentNamed(_))
106+
&& matches!(
107+
self.format,
108+
FormatSpec {
109+
fill: None,
110+
fill_span: None,
111+
align: AlignUnknown,
112+
sign: None,
113+
alternate: false,
114+
zero_pad: false,
115+
debug_hex: None,
116+
precision: CountImplied,
117+
precision_span: None,
118+
width: CountImplied,
119+
width_span: None,
120+
ty: "",
121+
ty_span: None,
122+
},
123+
)
124+
}
125+
}
126+
103127
/// Specification for the formatting of an argument in the format string.
104128
#[derive(Copy, Clone, Debug, PartialEq)]
105129
pub struct FormatSpec<'a> {
@@ -894,52 +918,73 @@ impl<'a> Parser<'a> {
894918
}
895919

896920
fn suggest_positional_arg_instead_of_captured_arg(&mut self, arg: Argument<'a>) {
897-
if let Some(end) = self.consume_pos('.') {
898-
let byte_pos = self.to_span_index(end);
899-
let start = InnerOffset(byte_pos.0 + 1);
900-
let field = self.argument(start);
901-
// We can only parse simple `foo.bar` field access or `foo.0` tuple index access, any
902-
// deeper nesting, or another type of expression, like method calls, are not supported
903-
if !self.consume('}') {
904-
return;
905-
}
906-
if let ArgumentNamed(_) = arg.position {
907-
match field.position {
908-
ArgumentNamed(_) => {
909-
self.errors.insert(
910-
0,
911-
ParseError {
912-
description: "field access isn't supported".to_string(),
913-
note: None,
914-
label: "not supported".to_string(),
915-
span: InnerSpan::new(
916-
arg.position_span.start,
917-
field.position_span.end,
918-
),
919-
secondary_label: None,
920-
suggestion: Suggestion::UsePositional,
921-
},
922-
);
923-
}
924-
ArgumentIs(_) => {
925-
self.errors.insert(
926-
0,
927-
ParseError {
928-
description: "tuple index access isn't supported".to_string(),
929-
note: None,
930-
label: "not supported".to_string(),
931-
span: InnerSpan::new(
932-
arg.position_span.start,
933-
field.position_span.end,
934-
),
935-
secondary_label: None,
936-
suggestion: Suggestion::UsePositional,
937-
},
938-
);
939-
}
940-
_ => {}
941-
};
921+
// If the argument is an identifier, it may be a field access.
922+
if arg.is_identifier() {
923+
if let Some(end) = self.consume_pos('.') {
924+
let byte_pos = self.to_span_index(end);
925+
let start = InnerOffset(byte_pos.0 + 1);
926+
let field = self.argument(start);
927+
// We can only parse simple `foo.bar` field access or `foo.0` tuple index access, any
928+
// deeper nesting, or another type of expression, like method calls, are not supported
929+
if !self.consume('}') {
930+
return;
931+
}
932+
if let ArgumentNamed(_) = arg.position {
933+
match field.position {
934+
ArgumentNamed(_) => {
935+
self.errors.insert(
936+
0,
937+
ParseError {
938+
description: "field access isn't supported".to_string(),
939+
note: None,
940+
label: "not supported".to_string(),
941+
span: InnerSpan::new(
942+
arg.position_span.start,
943+
field.position_span.end,
944+
),
945+
secondary_label: None,
946+
suggestion: Suggestion::UsePositional,
947+
},
948+
);
949+
}
950+
ArgumentIs(_) => {
951+
self.errors.insert(
952+
0,
953+
ParseError {
954+
description: "tuple index access isn't supported".to_string(),
955+
note: None,
956+
label: "not supported".to_string(),
957+
span: InnerSpan::new(
958+
arg.position_span.start,
959+
field.position_span.end,
960+
),
961+
secondary_label: None,
962+
suggestion: Suggestion::UsePositional,
963+
},
964+
);
965+
}
966+
_ => {}
967+
};
968+
}
942969
}
970+
} else if matches!(arg.position, ArgumentNamed(_) | ArgumentIs(_)) {
971+
let arg_name = match arg.position {
972+
ArgumentNamed(arg_name) => &format!("`{arg_name}`"),
973+
ArgumentIs(arg_index) => &format!("at index `{arg_index}`"),
974+
_ => unreachable!(),
975+
};
976+
977+
self.errors.insert(
978+
0,
979+
ParseError {
980+
description: format!("invalid format string for argument {}", arg_name),
981+
note: None,
982+
label: format!("invalid format specifier for this argument"),
983+
span: InnerSpan::new(arg.position_span.start, arg.position_span.end),
984+
secondary_label: None,
985+
suggestion: Suggestion::None,
986+
},
987+
);
943988
}
944989
}
945990

Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
fn main() {
2-
println!("{foo:_1.4}", foo = 3.14); //~ ERROR invalid format string: tuple index access isn't supported
3-
println!("{foo:1.4_1.4}", foo = 3.14); //~ ERROR invalid format string: tuple index access isn't supported
4-
println!("xxx{0:_1.4", 1.11); //~ ERROR invalid format string: expected `}`, found `.`
5-
println!("{foo:_1.4", foo = 3.14); //~ ERROR invalid format string: expected `}`, found `.`
6-
println!("xxx{0:_1.4", 1.11); //~ ERROR invalid format string: expected `}`, found `.`
2+
println!("{foo:_1.4}", foo = 3.14); //~ ERROR invalid format string: invalid format string for argument `foo`
3+
println!("{foo:1.4_1.4}", foo = 3.14); //~ ERROR invalid format string: invalid format string for argument `foo`
4+
println!("xxx{0:_1.4}", 1.11); //~ ERROR invalid format string: invalid format string for argument at index `0`
5+
println!("{foo:_1.4", foo = 3.14); //~ ERROR invalid format string: invalid format string for argument `foo`
6+
println!("xxx{0:_1.4", 1.11); //~ ERROR invalid format string: invalid format string for argument at index `0`
77
println!("xxx{ 0", 1.11); //~ ERROR invalid format string: expected `}`, found `0`
88
}

tests/ui/parser/issues/invalid-parse-format-issue-139104.stderr

+17-21
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,32 @@
1-
error: invalid format string: tuple index access isn't supported
1+
error: invalid format string: invalid format string for argument `foo`
22
--> $DIR/invalid-parse-format-issue-139104.rs:2:16
33
|
44
LL | println!("{foo:_1.4}", foo = 3.14);
5-
| ^^^^^^^^ not supported in format string
6-
|
7-
help: consider using a positional formatting argument instead
8-
|
9-
LL - println!("{foo:_1.4}", foo = 3.14);
10-
LL + println!("{0}", foo:_1.4, foo = 3.14);
11-
|
5+
| ^^^ invalid format specifier for this argument in format string
126

13-
error: invalid format string: tuple index access isn't supported
7+
error: invalid format string: invalid format string for argument `foo`
148
--> $DIR/invalid-parse-format-issue-139104.rs:3:16
159
|
1610
LL | println!("{foo:1.4_1.4}", foo = 3.14);
17-
| ^^^^^^^^^^^ not supported in format string
18-
|
19-
help: consider using a positional formatting argument instead
11+
| ^^^ invalid format specifier for this argument in format string
12+
13+
error: invalid format string: invalid format string for argument at index `0`
14+
--> $DIR/invalid-parse-format-issue-139104.rs:4:19
2015
|
21-
LL - println!("{foo:1.4_1.4}", foo = 3.14);
22-
LL + println!("{0}", foo:1.4_1.4, foo = 3.14);
16+
LL | println!("xxx{0:_1.4}", 1.11);
17+
| ^ invalid format specifier for this argument in format string
18+
19+
error: invalid format string: invalid format string for argument `foo`
20+
--> $DIR/invalid-parse-format-issue-139104.rs:5:16
2321
|
22+
LL | println!("{foo:_1.4", foo = 3.14);
23+
| ^^^ invalid format specifier for this argument in format string
2424

25-
error: invalid format string: expected `}`, found `.`
26-
--> $DIR/invalid-parse-format-issue-139104.rs:4:23
25+
error: invalid format string: invalid format string for argument at index `0`
26+
--> $DIR/invalid-parse-format-issue-139104.rs:6:19
2727
|
2828
LL | println!("xxx{0:_1.4", 1.11);
29-
| - ^ expected `}` in format string
30-
| |
31-
| because of this opening brace
32-
|
33-
= note: if you intended to print `{`, you can escape it using `{{`
29+
| ^ invalid format specifier for this argument in format string
3430

3531
error: invalid format string: expected `}`, found `.`
3632
--> $DIR/invalid-parse-format-issue-139104.rs:5:22

0 commit comments

Comments
 (0)