Skip to content

Commit 38bc2be

Browse files
authored
Rollup merge of rust-lang#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 rust-lang#131004 Fix rust-lang#129966
2 parents 45d8d5f + 62c3c9a commit 38bc2be

File tree

7 files changed

+140
-0
lines changed

7 files changed

+140
-0
lines changed

compiler/rustc_builtin_macros/messages.ftl

+2
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,8 @@ builtin_macros_format_redundant_args = redundant {$n ->
197197
198198
builtin_macros_format_remove_raw_ident = remove the `r#`
199199
200+
builtin_macros_format_reorder_format_parameter = did you mean `{$replacement}`?
201+
200202
builtin_macros_format_requires_string = requires at least a format string argument
201203
202204
builtin_macros_format_string_invalid = invalid format string: {$desc}

compiler/rustc_builtin_macros/src/errors.rs

+11
Original file line numberDiff line numberDiff line change
@@ -618,6 +618,17 @@ pub(crate) enum InvalidFormatStringSuggestion {
618618
#[primary_span]
619619
span: Span,
620620
},
621+
#[suggestion(
622+
builtin_macros_format_reorder_format_parameter,
623+
code = "{replacement}",
624+
style = "verbose",
625+
applicability = "machine-applicable"
626+
)]
627+
ReorderFormatParameter {
628+
#[primary_span]
629+
span: Span,
630+
replacement: String,
631+
},
621632
}
622633

623634
#[derive(Diagnostic)]

compiler/rustc_builtin_macros/src/format.rs

+7
Original file line numberDiff line numberDiff line change
@@ -321,6 +321,13 @@ fn make_format_args(
321321
e.sugg_ = Some(errors::InvalidFormatStringSuggestion::RemoveRawIdent { span })
322322
}
323323
}
324+
parse::Suggestion::ReorderFormatParameter(span, replacement) => {
325+
let span = fmt_span.from_inner(InnerSpan::new(span.start, span.end));
326+
e.sugg_ = Some(errors::InvalidFormatStringSuggestion::ReorderFormatParameter {
327+
span,
328+
replacement,
329+
});
330+
}
324331
}
325332
let guar = ecx.dcx().emit_err(e);
326333
return ExpandResult::Ready(Err(guar));

compiler/rustc_parse_format/src/lib.rs

+35
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,11 @@ pub enum Suggestion {
221221
/// Remove `r#` from identifier:
222222
/// `format!("{r#foo}")` -> `format!("{foo}")`
223223
RemoveRawIdent(InnerSpan),
224+
/// Reorder format parameter:
225+
/// `format!("{foo:?#}")` -> `format!("{foo:#?}")`
226+
/// `format!("{foo:?x}")` -> `format!("{foo:x?}")`
227+
/// `format!("{foo:?X}")` -> `format!("{foo:X?}")`
228+
ReorderFormatParameter(InnerSpan, string::String),
224229
}
225230

226231
/// The parser structure for interpreting the input format string. This is
@@ -731,6 +736,12 @@ impl<'a> Parser<'a> {
731736
}
732737
} else if self.consume('?') {
733738
spec.ty = "?";
739+
if let Some(&(_, maybe)) = self.cur.peek() {
740+
match maybe {
741+
'#' | 'x' | 'X' => self.suggest_format_parameter(maybe),
742+
_ => (),
743+
}
744+
}
734745
} else {
735746
spec.ty = self.word();
736747
if !spec.ty.is_empty() {
@@ -932,6 +943,30 @@ impl<'a> Parser<'a> {
932943
}
933944
}
934945
}
946+
947+
fn suggest_format_parameter(&mut self, c: char) {
948+
let replacement = match c {
949+
'#' => "#?",
950+
'x' => "x?",
951+
'X' => "X?",
952+
_ => return,
953+
};
954+
let Some(pos) = self.consume_pos(c) else {
955+
return;
956+
};
957+
958+
let span = self.span(pos - 1, pos + 1);
959+
let pos = self.to_span_index(pos);
960+
961+
self.errors.insert(0, ParseError {
962+
description: format!("expected `}}`, found `{c}`"),
963+
note: None,
964+
label: "expected `'}'`".into(),
965+
span: pos.to(pos),
966+
secondary_label: None,
967+
suggestion: Suggestion::ReorderFormatParameter(span, format!("{replacement}")),
968+
})
969+
}
935970
}
936971

937972
/// Finds the indices of all characters that have been processed and differ between the actual
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
//! Regression test for https://github.com/rust-lang/rust/issues/129966
2+
//!
3+
//! Ensure we provide suggestion for wrongly ordered format parameters.
4+
5+
//@ run-rustfix
6+
#![allow(dead_code)]
7+
8+
#[derive(Debug)]
9+
struct Foo(u8, u8);
10+
11+
fn main() {
12+
let f = Foo(1, 2);
13+
14+
println!("{f:#?}");
15+
//~^ ERROR invalid format string: expected `}`, found `#`
16+
//~| HELP did you mean `#?`?
17+
18+
println!("{f:x?}");
19+
//~^ ERROR invalid format string: expected `}`, found `x`
20+
//~| HELP did you mean `x?`?
21+
22+
println!("{f:X?}");
23+
//~^ ERROR invalid format string: expected `}`, found `X`
24+
//~| HELP did you mean `X?`?
25+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
//! Regression test for https://github.com/rust-lang/rust/issues/129966
2+
//!
3+
//! Ensure we provide suggestion for wrongly ordered format parameters.
4+
5+
//@ run-rustfix
6+
#![allow(dead_code)]
7+
8+
#[derive(Debug)]
9+
struct Foo(u8, u8);
10+
11+
fn main() {
12+
let f = Foo(1, 2);
13+
14+
println!("{f:?#}");
15+
//~^ ERROR invalid format string: expected `}`, found `#`
16+
//~| HELP did you mean `#?`?
17+
18+
println!("{f:?x}");
19+
//~^ ERROR invalid format string: expected `}`, found `x`
20+
//~| HELP did you mean `x?`?
21+
22+
println!("{f:?X}");
23+
//~^ ERROR invalid format string: expected `}`, found `X`
24+
//~| HELP did you mean `X?`?
25+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
error: invalid format string: expected `}`, found `#`
2+
--> $DIR/suggest-wrongly-order-format-parameter.rs:14:19
3+
|
4+
LL | println!("{f:?#}");
5+
| ^ expected `'}'` in format string
6+
|
7+
help: did you mean `#?`?
8+
|
9+
LL | println!("{f:#?}");
10+
| ~~
11+
12+
error: invalid format string: expected `}`, found `x`
13+
--> $DIR/suggest-wrongly-order-format-parameter.rs:18:19
14+
|
15+
LL | println!("{f:?x}");
16+
| ^ expected `'}'` in format string
17+
|
18+
help: did you mean `x?`?
19+
|
20+
LL | println!("{f:x?}");
21+
| ~~
22+
23+
error: invalid format string: expected `}`, found `X`
24+
--> $DIR/suggest-wrongly-order-format-parameter.rs:22:19
25+
|
26+
LL | println!("{f:?X}");
27+
| ^ expected `'}'` in format string
28+
|
29+
help: did you mean `X?`?
30+
|
31+
LL | println!("{f:X?}");
32+
| ~~
33+
34+
error: aborting due to 3 previous errors
35+

0 commit comments

Comments
 (0)