1
Fork 0

Rollup merge of #101000 - m-ou-se:count-is-star, r=nagisa

Separate CountIsStar from CountIsParam in rustc_parse_format.

`rustc_parse_format`'s parser would result in the exact same output for `{:.*}` and `{:.0$}`, making it hard for diagnostics to handle these cases properly.

This splits those cases by adding a new `CountIsStar` enum variant.

This fixes #100995

Prerequisite for https://github.com/rust-lang/rust/pull/100996
This commit is contained in:
Dylan DPC 2022-08-29 16:49:45 +05:30 committed by GitHub
commit 0b6faca670
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 24 additions and 9 deletions

View file

@ -541,7 +541,7 @@ impl<'a, 'b> Context<'a, 'b> {
) { ) {
match c { match c {
parse::CountImplied | parse::CountIs(..) => {} parse::CountImplied | parse::CountIs(..) => {}
parse::CountIsParam(i) => { parse::CountIsParam(i) | parse::CountIsStar(i) => {
self.unused_names_lint.maybe_add_positional_named_arg( self.unused_names_lint.maybe_add_positional_named_arg(
self.args.get(i), self.args.get(i),
named_arg_type, named_arg_type,
@ -589,7 +589,7 @@ impl<'a, 'b> Context<'a, 'b> {
+ self + self
.arg_with_formatting .arg_with_formatting
.iter() .iter()
.filter(|fmt| matches!(fmt.precision, parse::CountIsParam(_))) .filter(|fmt| matches!(fmt.precision, parse::CountIsStar(_)))
.count(); .count();
if self.names.is_empty() && !numbered_position_args && count != self.num_args() { if self.names.is_empty() && !numbered_position_args && count != self.num_args() {
e = self.ecx.struct_span_err( e = self.ecx.struct_span_err(
@ -639,7 +639,7 @@ impl<'a, 'b> Context<'a, 'b> {
if let Some(span) = fmt.precision_span { if let Some(span) = fmt.precision_span {
let span = self.fmtsp.from_inner(InnerSpan::new(span.start, span.end)); let span = self.fmtsp.from_inner(InnerSpan::new(span.start, span.end));
match fmt.precision { match fmt.precision {
parse::CountIsParam(pos) if pos > self.num_args() => { parse::CountIsParam(pos) if pos >= self.num_args() => {
e.span_label( e.span_label(
span, span,
&format!( &format!(
@ -651,12 +651,12 @@ impl<'a, 'b> Context<'a, 'b> {
); );
zero_based_note = true; zero_based_note = true;
} }
parse::CountIsParam(pos) => { parse::CountIsStar(pos) => {
let count = self.pieces.len() let count = self.pieces.len()
+ self + self
.arg_with_formatting .arg_with_formatting
.iter() .iter()
.filter(|fmt| matches!(fmt.precision, parse::CountIsParam(_))) .filter(|fmt| matches!(fmt.precision, parse::CountIsStar(_)))
.count(); .count();
e.span_label( e.span_label(
span, span,
@ -837,7 +837,7 @@ impl<'a, 'b> Context<'a, 'b> {
}; };
match c { match c {
parse::CountIs(i) => count(sym::Is, Some(self.ecx.expr_usize(sp, i))), parse::CountIs(i) => count(sym::Is, Some(self.ecx.expr_usize(sp, i))),
parse::CountIsParam(i) => { parse::CountIsParam(i) | parse::CountIsStar(i) => {
// This needs mapping too, as `i` is referring to a macro // This needs mapping too, as `i` is referring to a macro
// argument. If `i` is not found in `count_positions` then // argument. If `i` is not found in `count_positions` then
// the error had already been emitted elsewhere. // the error had already been emitted elsewhere.

View file

@ -167,6 +167,8 @@ pub enum Count<'a> {
CountIsName(&'a str, InnerSpan), CountIsName(&'a str, InnerSpan),
/// The count is specified by the argument at the given index. /// The count is specified by the argument at the given index.
CountIsParam(usize), CountIsParam(usize),
/// The count is specified by a star (like in `{:.*}`) that refers to the argument at the given index.
CountIsStar(usize),
/// The count is implied and cannot be explicitly specified. /// The count is implied and cannot be explicitly specified.
CountImplied, CountImplied,
} }
@ -618,7 +620,7 @@ impl<'a> Parser<'a> {
// We can do this immediately as `position` is resolved later. // We can do this immediately as `position` is resolved later.
let i = self.curarg; let i = self.curarg;
self.curarg += 1; self.curarg += 1;
spec.precision = CountIsParam(i); spec.precision = CountIsStar(i);
} else { } else {
spec.precision = self.count(start + 1); spec.precision = self.count(start + 1);
} }

View file

@ -244,7 +244,7 @@ fn format_counts() {
fill: None, fill: None,
align: AlignUnknown, align: AlignUnknown,
flags: 0, flags: 0,
precision: CountIsParam(0), precision: CountIsStar(0),
precision_span: Some(InnerSpan { start: 3, end: 5 }), precision_span: Some(InnerSpan { start: 3, end: 5 }),
width: CountImplied, width: CountImplied,
width_span: None, width_span: None,

View file

@ -94,4 +94,6 @@ tenth number: {}",
// doesn't exist. // doesn't exist.
println!("{:.*}"); println!("{:.*}");
//~^ ERROR 2 positional arguments in format string, but no arguments were given //~^ ERROR 2 positional arguments in format string, but no arguments were given
println!("{:.0$}");
//~^ ERROR 1 positional argument in format string, but no arguments were given
} }

View file

@ -273,6 +273,17 @@ LL | println!("{:.*}");
= note: positional arguments are zero-based = note: positional arguments are zero-based
= note: for information about formatting flags, visit https://doc.rust-lang.org/std/fmt/index.html = note: for information about formatting flags, visit https://doc.rust-lang.org/std/fmt/index.html
error: 1 positional argument in format string, but no arguments were given
--> $DIR/ifmt-bad-arg.rs:97:15
|
LL | println!("{:.0$}");
| ^^---^
| |
| this precision flag expects an `usize` argument at position 0, but no arguments were given
|
= note: positional arguments are zero-based
= note: for information about formatting flags, visit https://doc.rust-lang.org/std/fmt/index.html
error[E0425]: cannot find value `foo` in this scope error[E0425]: cannot find value `foo` in this scope
--> $DIR/ifmt-bad-arg.rs:27:18 --> $DIR/ifmt-bad-arg.rs:27:18
| |
@ -339,7 +350,7 @@ LL | pub fn from_usize(x: &usize) -> ArgumentV1<'_> {
| ^^^^^^^^^^ | ^^^^^^^^^^
= note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to 37 previous errors error: aborting due to 38 previous errors
Some errors have detailed explanations: E0308, E0425. Some errors have detailed explanations: E0308, E0425.
For more information about an error, try `rustc --explain E0308`. For more information about an error, try `rustc --explain E0308`.