Rollup merge of #150765 - ua/missing-colon, r=estebank

rustc_parse_format: improve error for missing `:` before `?` in format args

Detect the `{ident?}` pattern where `?` is immediately followed by `}` and emit a clearer diagnostic explaining that `:` is required for Debug formatting. This avoids falling back to a generic “invalid format string” error and adds a targeted UI test for the case.
This commit is contained in:
Matthias Krüger
2026-01-10 08:33:57 +01:00
committed by GitHub
6 changed files with 55 additions and 5 deletions
+25 -4
View File
@@ -184,6 +184,9 @@ pub enum Suggestion {
/// `format!("{foo:?x}")` -> `format!("{foo:x?}")`
/// `format!("{foo:?X}")` -> `format!("{foo:X?}")`
ReorderFormatParameter(Range<usize>, String),
/// Add missing colon:
/// `format!("{foo?}")` -> `format!("{foo:?}")`
AddMissingColon(Range<usize>),
}
/// The parser structure for interpreting the input format string. This is
@@ -453,10 +456,11 @@ fn missing_closing_brace(&mut self, arg: &Argument<'_>) {
suggestion: Suggestion::None,
});
if let Some((_, _, c)) = self.peek() {
match c {
'?' => self.suggest_format_debug(),
'<' | '^' | '>' => self.suggest_format_align(c),
if let (Some((_, _, c)), Some((_, _, nc))) = (self.peek(), self.peek_ahead()) {
match (c, nc) {
('?', '}') => self.missing_colon_before_debug_formatter(),
('?', _) => self.suggest_format_debug(),
('<' | '^' | '>', _) => self.suggest_format_align(c),
_ => self.suggest_positional_arg_instead_of_captured_arg(arg),
}
}
@@ -849,6 +853,23 @@ fn suggest_format_debug(&mut self) {
}
}
fn missing_colon_before_debug_formatter(&mut self) {
if let Some((range, _)) = self.consume_pos('?') {
let span = range.clone();
self.errors.insert(
0,
ParseError {
description: "expected `}`, found `?`".to_owned(),
note: Some(format!("to print `{{`, you can escape it using `{{{{`",)),
label: "expected `:` before `?` to format with `Debug`".to_owned(),
span: range,
secondary_label: None,
suggestion: Suggestion::AddMissingColon(span),
},
);
}
}
fn suggest_format_align(&mut self, alignment: char) {
if let Some((range, _)) = self.consume_pos(alignment) {
self.errors.insert(