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.
Signed-off-by: Usman Akinyemi <usmanakinyemi202@gmail.com>
This commit is contained in:
parent
d9617c8d9a
commit
b0e65da2af
6 changed files with 55 additions and 5 deletions
|
|
@ -182,6 +182,8 @@ builtin_macros_expected_other = expected operand, {$is_inline_asm ->
|
|||
|
||||
builtin_macros_export_macro_rules = cannot export macro_rules! macros from a `proc-macro` crate type currently
|
||||
|
||||
builtin_macros_format_add_missing_colon = add a colon before the format specifier
|
||||
|
||||
builtin_macros_format_duplicate_arg = duplicate argument named `{$ident}`
|
||||
.label1 = previously here
|
||||
.label2 = duplicate argument
|
||||
|
|
|
|||
|
|
@ -643,6 +643,15 @@ pub(crate) enum InvalidFormatStringSuggestion {
|
|||
span: Span,
|
||||
replacement: String,
|
||||
},
|
||||
#[suggestion(
|
||||
builtin_macros_format_add_missing_colon,
|
||||
code = ":?",
|
||||
applicability = "machine-applicable"
|
||||
)]
|
||||
AddMissingColon {
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
|
|
|
|||
|
|
@ -329,6 +329,10 @@ fn make_format_args(
|
|||
replacement,
|
||||
});
|
||||
}
|
||||
parse::Suggestion::AddMissingColon(span) => {
|
||||
let span = fmt_span.from_inner(InnerSpan::new(span.start, span.end));
|
||||
e.sugg_ = Some(errors::InvalidFormatStringSuggestion::AddMissingColon { span });
|
||||
}
|
||||
}
|
||||
let guar = ecx.dcx().emit_err(e);
|
||||
return ExpandResult::Ready(Err(guar));
|
||||
|
|
|
|||
|
|
@ -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 @@ impl<'input> Parser<'input> {
|
|||
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 @@ impl<'input> Parser<'input> {
|
|||
}
|
||||
}
|
||||
|
||||
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(
|
||||
|
|
|
|||
|
|
@ -83,4 +83,7 @@ raw { \n
|
|||
|
||||
println!(r#"\x7B}\u8 {"#, 1);
|
||||
//~^ ERROR invalid format string: unmatched `}` found
|
||||
|
||||
println!("{x?}, world!",);
|
||||
//~^ ERROR invalid format string: expected `}`, found `?`
|
||||
}
|
||||
|
|
|
|||
|
|
@ -177,5 +177,16 @@ LL | println!(r#"\x7B}\u8 {"#, 1);
|
|||
|
|
||||
= note: if you intended to print `}`, you can escape it using `}}`
|
||||
|
||||
error: aborting due to 18 previous errors
|
||||
error: invalid format string: expected `}`, found `?`
|
||||
--> $DIR/format-string-error-2.rs:87:17
|
||||
|
|
||||
LL | println!("{x?}, world!",);
|
||||
| ^
|
||||
| |
|
||||
| expected `:` before `?` to format with `Debug` in format string
|
||||
| help: add a colon before the format specifier: `:?`
|
||||
|
|
||||
= note: to print `{`, you can escape it using `{{`
|
||||
|
||||
error: aborting due to 19 previous errors
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue