From d9ddf9e0c20dc2b71ddeca74b73fad087be9e41a Mon Sep 17 00:00:00 2001 From: Marijn Schouten Date: Thu, 6 Feb 2025 12:15:06 +0100 Subject: [PATCH] warn on empty precision, but only when width present --- compiler/rustc_builtin_macros/src/format.rs | 25 +++++++++++++++---- compiler/rustc_parse_format/src/lib.rs | 20 +++++++++++++-- ...n-on-possible-precision-width-confusion.rs | 8 ++++++ ...-possible-precision-width-confusion.stderr | 14 +++++++++++ 4 files changed, 60 insertions(+), 7 deletions(-) create mode 100644 tests/ui/fmt/warn-on-possible-precision-width-confusion.rs create mode 100644 tests/ui/fmt/warn-on-possible-precision-width-confusion.stderr diff --git a/compiler/rustc_builtin_macros/src/format.rs b/compiler/rustc_builtin_macros/src/format.rs index 1caa0e823090a..3656b5f3d7dc9 100644 --- a/compiler/rustc_builtin_macros/src/format.rs +++ b/compiler/rustc_builtin_macros/src/format.rs @@ -289,10 +289,9 @@ fn make_format_args( let is_source_literal = parser.is_source_literal; - if !parser.errors.is_empty() { - let err = parser.errors.remove(0); - let sp = if is_source_literal { - fmt_span.from_inner(InnerSpan::new(err.span.start, err.span.end)) + let snippetify = |span: &Range| { + if is_source_literal { + fmt_span.from_inner(InnerSpan::new(span.start, span.end)) } else { // The format string could be another macro invocation, e.g.: // format!(concat!("abc", "{}"), 4); @@ -303,9 +302,25 @@ fn make_format_args( // Therefore, we conservatively report the error for the entire // argument span here. fmt_span + } + }; + + for w in &parser.warnings { + let warn = errors::InvalidFormatString { + span: snippetify(&w.span), + note_: w.note.clone().map(|note| errors::InvalidFormatStringNote { note }), + label_: None, + sugg_: None, + desc: w.description.clone(), + label1: w.label.clone(), }; + ecx.dcx().emit_warn(warn); + } + + if !parser.errors.is_empty() { + let err = parser.errors.remove(0); let mut e = errors::InvalidFormatString { - span: sp, + span: snippetify(&err.span), note_: None, label_: None, sugg_: None, diff --git a/compiler/rustc_parse_format/src/lib.rs b/compiler/rustc_parse_format/src/lib.rs index 20f4646490a6b..7b654355bea62 100644 --- a/compiler/rustc_parse_format/src/lib.rs +++ b/compiler/rustc_parse_format/src/lib.rs @@ -206,6 +206,8 @@ pub struct Parser<'input> { input_vec: Vec<(Range, usize, char)>, /// Index into input_vec input_vec_index: usize, + /// Warnings accumulated during parsing + pub warnings: Vec, /// Error messages accumulated during parsing pub errors: Vec, /// Current position of implicit positional argument pointer @@ -406,6 +408,7 @@ impl<'input> Parser<'input> { input, input_vec, input_vec_index: 0, + warnings: vec![], errors: vec![], curarg: 0, arg_places: vec![], @@ -681,8 +684,21 @@ impl<'input> Parser<'input> { } else { spec.precision = self.count(); } - spec.precision_span = - Some(range.start..self.input_vec_index2range(self.input_vec_index).start); + let span = range.start..self.input_vec_index2range(self.input_vec_index).start; + if spec.precision == CountImplied && spec.width != CountImplied { + self.warnings.push(ParseError { + description: + "precision specifier without precision value (but with a width value)" + .to_string(), + note: None, + label: "precision specifier without precision value".to_string(), + span, + secondary_label: None, + suggestion: Suggestion::None, + }); + } else { + spec.precision_span = Some(span); + } } let start_idx = self.input_vec_index; diff --git a/tests/ui/fmt/warn-on-possible-precision-width-confusion.rs b/tests/ui/fmt/warn-on-possible-precision-width-confusion.rs new file mode 100644 index 0000000000000..19fdf5832099f --- /dev/null +++ b/tests/ui/fmt/warn-on-possible-precision-width-confusion.rs @@ -0,0 +1,8 @@ +//@ run-pass +fn main() { + let float = 0.123_456_789; + println!("Missing precision: {float:.} {float:3.} {float:_^12.}"); + //~^ WARNING invalid format string: precision specifier without precision value + //~| WARNING invalid format string: precision specifier without precision value + println!("Given precision: {float:.6} {float:3.15} {float:_^12.7}"); +} diff --git a/tests/ui/fmt/warn-on-possible-precision-width-confusion.stderr b/tests/ui/fmt/warn-on-possible-precision-width-confusion.stderr new file mode 100644 index 0000000000000..a99deb745d4e3 --- /dev/null +++ b/tests/ui/fmt/warn-on-possible-precision-width-confusion.stderr @@ -0,0 +1,14 @@ +warning: invalid format string: precision specifier without precision value (but with a width value) + --> $DIR/warn-on-possible-precision-width-confusion.rs:4:52 + | +LL | println!("Missing precision: {float:.} {float:3.} {float:_^12.}"); + | ^ precision specifier without precision value in format string + +warning: invalid format string: precision specifier without precision value (but with a width value) + --> $DIR/warn-on-possible-precision-width-confusion.rs:4:66 + | +LL | println!("Missing precision: {float:.} {float:3.} {float:_^12.}"); + | ^ precision specifier without precision value in format string + +warning: 2 warnings emitted +