diff options
Diffstat (limited to 'compiler')
| -rw-r--r-- | compiler/rustc_builtin_macros/messages.ftl | 2 | ||||
| -rw-r--r-- | compiler/rustc_builtin_macros/src/errors.rs | 11 | ||||
| -rw-r--r-- | compiler/rustc_builtin_macros/src/format.rs | 7 | ||||
| -rw-r--r-- | compiler/rustc_parse_format/src/lib.rs | 35 |
4 files changed, 55 insertions, 0 deletions
diff --git a/compiler/rustc_builtin_macros/messages.ftl b/compiler/rustc_builtin_macros/messages.ftl index 7a31d2a2239..4cac7cb93f5 100644 --- a/compiler/rustc_builtin_macros/messages.ftl +++ b/compiler/rustc_builtin_macros/messages.ftl @@ -197,6 +197,8 @@ builtin_macros_format_redundant_args = redundant {$n -> builtin_macros_format_remove_raw_ident = remove the `r#` +builtin_macros_format_reorder_format_parameter = did you mean `{$replacement}`? + builtin_macros_format_requires_string = requires at least a format string argument builtin_macros_format_string_invalid = invalid format string: {$desc} diff --git a/compiler/rustc_builtin_macros/src/errors.rs b/compiler/rustc_builtin_macros/src/errors.rs index 1abdfdb9c65..6213bd802c7 100644 --- a/compiler/rustc_builtin_macros/src/errors.rs +++ b/compiler/rustc_builtin_macros/src/errors.rs @@ -618,6 +618,17 @@ pub(crate) enum InvalidFormatStringSuggestion { #[primary_span] span: Span, }, + #[suggestion( + builtin_macros_format_reorder_format_parameter, + code = "{replacement}", + style = "verbose", + applicability = "machine-applicable" + )] + ReorderFormatParameter { + #[primary_span] + span: Span, + replacement: String, + }, } #[derive(Diagnostic)] diff --git a/compiler/rustc_builtin_macros/src/format.rs b/compiler/rustc_builtin_macros/src/format.rs index 0112499c509..5202fe26c40 100644 --- a/compiler/rustc_builtin_macros/src/format.rs +++ b/compiler/rustc_builtin_macros/src/format.rs @@ -321,6 +321,13 @@ fn make_format_args( e.sugg_ = Some(errors::InvalidFormatStringSuggestion::RemoveRawIdent { span }) } } + parse::Suggestion::ReorderFormatParameter(span, replacement) => { + let span = fmt_span.from_inner(InnerSpan::new(span.start, span.end)); + e.sugg_ = Some(errors::InvalidFormatStringSuggestion::ReorderFormatParameter { + span, + replacement, + }); + } } let guar = ecx.dcx().emit_err(e); return ExpandResult::Ready(Err(guar)); diff --git a/compiler/rustc_parse_format/src/lib.rs b/compiler/rustc_parse_format/src/lib.rs index 1716f417969..9eb335cb34c 100644 --- a/compiler/rustc_parse_format/src/lib.rs +++ b/compiler/rustc_parse_format/src/lib.rs @@ -221,6 +221,11 @@ pub enum Suggestion { /// Remove `r#` from identifier: /// `format!("{r#foo}")` -> `format!("{foo}")` RemoveRawIdent(InnerSpan), + /// Reorder format parameter: + /// `format!("{foo:?#}")` -> `format!("{foo:#?}")` + /// `format!("{foo:?x}")` -> `format!("{foo:x?}")` + /// `format!("{foo:?X}")` -> `format!("{foo:X?}")` + ReorderFormatParameter(InnerSpan, string::String), } /// The parser structure for interpreting the input format string. This is @@ -731,6 +736,12 @@ impl<'a> Parser<'a> { } } else if self.consume('?') { spec.ty = "?"; + if let Some(&(_, maybe)) = self.cur.peek() { + match maybe { + '#' | 'x' | 'X' => self.suggest_format_parameter(maybe), + _ => (), + } + } } else { spec.ty = self.word(); if !spec.ty.is_empty() { @@ -932,6 +943,30 @@ impl<'a> Parser<'a> { } } } + + fn suggest_format_parameter(&mut self, c: char) { + let replacement = match c { + '#' => "#?", + 'x' => "x?", + 'X' => "X?", + _ => return, + }; + let Some(pos) = self.consume_pos(c) else { + return; + }; + + let span = self.span(pos - 1, pos + 1); + let pos = self.to_span_index(pos); + + self.errors.insert(0, ParseError { + description: format!("expected `}}`, found `{c}`"), + note: None, + label: "expected `'}'`".into(), + span: pos.to(pos), + secondary_label: None, + suggestion: Suggestion::ReorderFormatParameter(span, format!("{replacement}")), + }) + } } /// Finds the indices of all characters that have been processed and differ between the actual |
