Skip to content

Commit a558a3f

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

File tree

3 files changed

+92
-63
lines changed

3 files changed

+92
-63
lines changed

compiler/rustc_parse_format/src/lib.rs

+85-44
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,51 +918,68 @@ 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;
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+
}
905969
}
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-
};
970+
} else {
971+
if let ArgumentNamed(arg_name) = arg.position {
972+
self.errors.insert(
973+
0,
974+
ParseError {
975+
description: format!("invalid format string for argument `{}`", arg_name),
976+
note: None,
977+
label: format!("invalid format specifier for this argument"),
978+
span: InnerSpan::new(arg.position_span.start, arg.position_span.end),
979+
secondary_label: None,
980+
suggestion: Suggestion::None,
981+
},
982+
);
942983
}
943984
}
944985
}
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
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-
}
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+
}
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,14 @@
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
20-
|
21-
LL - println!("{foo:1.4_1.4}", foo = 3.14);
22-
LL + println!("{0}", foo:1.4_1.4, foo = 3.14);
23-
|
11+
| ^^^ invalid format specifier for this argument in format string
2412

2513
error: aborting due to 2 previous errors
2614

0 commit comments

Comments
 (0)