Skip to content

Commit 0b6faca

Browse files
authored
Rollup merge of rust-lang#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 rust-lang#100995 Prerequisite for rust-lang#100996
2 parents 141728f + aebad39 commit 0b6faca

File tree

5 files changed

+24
-9
lines changed

5 files changed

+24
-9
lines changed

Diff for: compiler/rustc_builtin_macros/src/format.rs

+6-6
Original file line numberDiff line numberDiff line change
@@ -541,7 +541,7 @@ impl<'a, 'b> Context<'a, 'b> {
541541
) {
542542
match c {
543543
parse::CountImplied | parse::CountIs(..) => {}
544-
parse::CountIsParam(i) => {
544+
parse::CountIsParam(i) | parse::CountIsStar(i) => {
545545
self.unused_names_lint.maybe_add_positional_named_arg(
546546
self.args.get(i),
547547
named_arg_type,
@@ -589,7 +589,7 @@ impl<'a, 'b> Context<'a, 'b> {
589589
+ self
590590
.arg_with_formatting
591591
.iter()
592-
.filter(|fmt| matches!(fmt.precision, parse::CountIsParam(_)))
592+
.filter(|fmt| matches!(fmt.precision, parse::CountIsStar(_)))
593593
.count();
594594
if self.names.is_empty() && !numbered_position_args && count != self.num_args() {
595595
e = self.ecx.struct_span_err(
@@ -639,7 +639,7 @@ impl<'a, 'b> Context<'a, 'b> {
639639
if let Some(span) = fmt.precision_span {
640640
let span = self.fmtsp.from_inner(InnerSpan::new(span.start, span.end));
641641
match fmt.precision {
642-
parse::CountIsParam(pos) if pos > self.num_args() => {
642+
parse::CountIsParam(pos) if pos >= self.num_args() => {
643643
e.span_label(
644644
span,
645645
&format!(
@@ -651,12 +651,12 @@ impl<'a, 'b> Context<'a, 'b> {
651651
);
652652
zero_based_note = true;
653653
}
654-
parse::CountIsParam(pos) => {
654+
parse::CountIsStar(pos) => {
655655
let count = self.pieces.len()
656656
+ self
657657
.arg_with_formatting
658658
.iter()
659-
.filter(|fmt| matches!(fmt.precision, parse::CountIsParam(_)))
659+
.filter(|fmt| matches!(fmt.precision, parse::CountIsStar(_)))
660660
.count();
661661
e.span_label(
662662
span,
@@ -837,7 +837,7 @@ impl<'a, 'b> Context<'a, 'b> {
837837
};
838838
match c {
839839
parse::CountIs(i) => count(sym::Is, Some(self.ecx.expr_usize(sp, i))),
840-
parse::CountIsParam(i) => {
840+
parse::CountIsParam(i) | parse::CountIsStar(i) => {
841841
// This needs mapping too, as `i` is referring to a macro
842842
// argument. If `i` is not found in `count_positions` then
843843
// the error had already been emitted elsewhere.

Diff for: compiler/rustc_parse_format/src/lib.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,8 @@ pub enum Count<'a> {
167167
CountIsName(&'a str, InnerSpan),
168168
/// The count is specified by the argument at the given index.
169169
CountIsParam(usize),
170+
/// The count is specified by a star (like in `{:.*}`) that refers to the argument at the given index.
171+
CountIsStar(usize),
170172
/// The count is implied and cannot be explicitly specified.
171173
CountImplied,
172174
}
@@ -618,7 +620,7 @@ impl<'a> Parser<'a> {
618620
// We can do this immediately as `position` is resolved later.
619621
let i = self.curarg;
620622
self.curarg += 1;
621-
spec.precision = CountIsParam(i);
623+
spec.precision = CountIsStar(i);
622624
} else {
623625
spec.precision = self.count(start + 1);
624626
}

Diff for: compiler/rustc_parse_format/src/tests.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,7 @@ fn format_counts() {
244244
fill: None,
245245
align: AlignUnknown,
246246
flags: 0,
247-
precision: CountIsParam(0),
247+
precision: CountIsStar(0),
248248
precision_span: Some(InnerSpan { start: 3, end: 5 }),
249249
width: CountImplied,
250250
width_span: None,

Diff for: src/test/ui/fmt/ifmt-bad-arg.rs

+2
Original file line numberDiff line numberDiff line change
@@ -94,4 +94,6 @@ tenth number: {}",
9494
// doesn't exist.
9595
println!("{:.*}");
9696
//~^ ERROR 2 positional arguments in format string, but no arguments were given
97+
println!("{:.0$}");
98+
//~^ ERROR 1 positional argument in format string, but no arguments were given
9799
}

Diff for: src/test/ui/fmt/ifmt-bad-arg.stderr

+12-1
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,17 @@ LL | println!("{:.*}");
273273
= note: positional arguments are zero-based
274274
= note: for information about formatting flags, visit https://doc.rust-lang.org/std/fmt/index.html
275275

276+
error: 1 positional argument in format string, but no arguments were given
277+
--> $DIR/ifmt-bad-arg.rs:97:15
278+
|
279+
LL | println!("{:.0$}");
280+
| ^^---^
281+
| |
282+
| this precision flag expects an `usize` argument at position 0, but no arguments were given
283+
|
284+
= note: positional arguments are zero-based
285+
= note: for information about formatting flags, visit https://doc.rust-lang.org/std/fmt/index.html
286+
276287
error[E0425]: cannot find value `foo` in this scope
277288
--> $DIR/ifmt-bad-arg.rs:27:18
278289
|
@@ -339,7 +350,7 @@ LL | pub fn from_usize(x: &usize) -> ArgumentV1<'_> {
339350
| ^^^^^^^^^^
340351
= 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)
341352

342-
error: aborting due to 37 previous errors
353+
error: aborting due to 38 previous errors
343354

344355
Some errors have detailed explanations: E0308, E0425.
345356
For more information about an error, try `rustc --explain E0308`.

0 commit comments

Comments
 (0)