Skip to content

Commit 20c1fa1

Browse files
authoredFeb 22, 2021
Rollup merge of #82287 - r00ster91:field_name_and, r=petrochenkov
Make "missing field" error message more natural ```rust struct A { x: i32, y: i32, z: i32, } fn main() { A { }; } ``` ``` error[E0063]: missing fields `x`, `y`, `z` in initializer of `A` --> src/main.rs:8:5 | 8 | A { }; | ^ missing `x`, `y`, `z` ``` This error is now: ``` error[E0063]: missing fields `x`, `y` and `z` in initializer of `A` --> src/main.rs:8:5 | 8 | A { }; | ^ missing `x`, `y` and `z` ``` I thought it looked nicer and more natural this way. Also, if there is >3 fields missing, there is an "and" as well ("missing \`x\`, \`y\`, \`z\` *and* 1 other field"), but for <=3 there is not. As such it improves consistency too. As for the implementation, originally I ended up with a chunky `push_str` algorithm but then I figured I could just do the formatting manually since it's just 3 field names at maximum. It is comparatively readable. As a sidenote, one thing I was wondering about is, isn't there more cases where you have a list of things like field names? Maybe this whole thing can at some point later be made into a more general function to be used in multiple areas.
2 parents a5f6668 + 447ce27 commit 20c1fa1

File tree

9 files changed

+29
-26
lines changed

9 files changed

+29
-26
lines changed
 

‎compiler/rustc_typeck/src/check/expr.rs

+17-14
Original file line numberDiff line numberDiff line change
@@ -1348,33 +1348,36 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
13481348
span: Span,
13491349
remaining_fields: FxHashMap<Ident, (usize, &ty::FieldDef)>,
13501350
) {
1351-
let tcx = self.tcx;
13521351
let len = remaining_fields.len();
13531352

13541353
let mut displayable_field_names =
13551354
remaining_fields.keys().map(|ident| ident.as_str()).collect::<Vec<_>>();
13561355

13571356
displayable_field_names.sort();
13581357

1359-
let truncated_fields_error = if len <= 3 {
1360-
String::new()
1361-
} else {
1362-
format!(" and {} other field{}", (len - 3), if len - 3 == 1 { "" } else { "s" })
1358+
let mut truncated_fields_error = String::new();
1359+
let remaining_fields_names = match &displayable_field_names[..] {
1360+
[field1] => format!("`{}`", field1),
1361+
[field1, field2] => format!("`{}` and `{}`", field1, field2),
1362+
[field1, field2, field3] => format!("`{}`, `{}` and `{}`", field1, field2, field3),
1363+
_ => {
1364+
truncated_fields_error =
1365+
format!(" and {} other field{}", len - 3, pluralize!(len - 3));
1366+
displayable_field_names
1367+
.iter()
1368+
.take(3)
1369+
.map(|n| format!("`{}`", n))
1370+
.collect::<Vec<_>>()
1371+
.join(", ")
1372+
}
13631373
};
13641374

1365-
let remaining_fields_names = displayable_field_names
1366-
.iter()
1367-
.take(3)
1368-
.map(|n| format!("`{}`", n))
1369-
.collect::<Vec<_>>()
1370-
.join(", ");
1371-
13721375
struct_span_err!(
1373-
tcx.sess,
1376+
self.tcx.sess,
13741377
span,
13751378
E0063,
13761379
"missing field{} {}{} in initializer of `{}`",
1377-
pluralize!(remaining_fields.len()),
1380+
pluralize!(len),
13781381
remaining_fields_names,
13791382
truncated_fields_error,
13801383
adt_ty

‎src/test/ui/error-codes/E0063.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ fn main() {
3232
let w = SingleFoo { };
3333
//~^ ERROR missing field `x` in initializer of `SingleFoo`
3434
let x = PluralFoo {x: 1};
35-
//~^ ERROR missing fields `y`, `z` in initializer of `PluralFoo`
35+
//~^ ERROR missing fields `y` and `z` in initializer of `PluralFoo`
3636
let y = TruncatedFoo{x:1};
3737
//~^ missing fields `a`, `b`, `y` and 1 other field in initializer of `TruncatedFoo`
3838
let z = TruncatedPluralFoo{x:1};

‎src/test/ui/error-codes/E0063.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,11 @@ error[E0063]: missing field `x` in initializer of `SingleFoo`
44
LL | let w = SingleFoo { };
55
| ^^^^^^^^^ missing `x`
66

7-
error[E0063]: missing fields `y`, `z` in initializer of `PluralFoo`
7+
error[E0063]: missing fields `y` and `z` in initializer of `PluralFoo`
88
--> $DIR/E0063.rs:34:13
99
|
1010
LL | let x = PluralFoo {x: 1};
11-
| ^^^^^^^^^ missing `y`, `z`
11+
| ^^^^^^^^^ missing `y` and `z`
1212

1313
error[E0063]: missing fields `a`, `b`, `y` and 1 other field in initializer of `TruncatedFoo`
1414
--> $DIR/E0063.rs:36:13

‎src/test/ui/issues/issue-79593.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ fn wrong() {
2323
foo::Enum::Variant { x: () };
2424
//~^ ERROR missing field `y` in initializer of `Enum`
2525
foo::Enum::Variant { };
26-
//~^ ERROR missing fields `x`, `y` in initializer of `Enum`
26+
//~^ ERROR missing fields `x` and `y` in initializer of `Enum`
2727
}
2828

2929
fn main() {}

‎src/test/ui/issues/issue-79593.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,11 @@ error[E0063]: missing field `y` in initializer of `Enum`
2222
LL | foo::Enum::Variant { x: () };
2323
| ^^^^^^^^^^^^^^^^^^ missing `y`
2424

25-
error[E0063]: missing fields `x`, `y` in initializer of `Enum`
25+
error[E0063]: missing fields `x` and `y` in initializer of `Enum`
2626
--> $DIR/issue-79593.rs:25:5
2727
|
2828
LL | foo::Enum::Variant { };
29-
| ^^^^^^^^^^^^^^^^^^ missing `x`, `y`
29+
| ^^^^^^^^^^^^^^^^^^ missing `x` and `y`
3030

3131
error: aborting due to 5 previous errors
3232

‎src/test/ui/parser/issue-52496.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,6 @@ fn main() {
77
let bar = 1.5f32;
88
let _ = Foo { bar.into(), bat: -1, . };
99
//~^ ERROR expected one of
10-
//~| ERROR missing fields `bar`, `baz` in initializer of `Foo`
10+
//~| ERROR missing fields `bar` and `baz` in initializer of `Foo`
1111
//~| ERROR expected identifier, found `.`
1212
}

‎src/test/ui/parser/issue-52496.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,11 @@ error[E0063]: missing field `bat` in initializer of `Foo`
2626
LL | let _ = Foo { bar: .5, baz: 42 };
2727
| ^^^ missing `bat`
2828

29-
error[E0063]: missing fields `bar`, `baz` in initializer of `Foo`
29+
error[E0063]: missing fields `bar` and `baz` in initializer of `Foo`
3030
--> $DIR/issue-52496.rs:8:13
3131
|
3232
LL | let _ = Foo { bar.into(), bat: -1, . };
33-
| ^^^ missing `bar`, `baz`
33+
| ^^^ missing `bar` and `baz`
3434

3535
error: aborting due to 5 previous errors
3636

‎src/test/ui/parser/struct-field-numeric-shorthand.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,5 @@ fn main() {
55
//~^ ERROR expected identifier, found `0`
66
//~| ERROR expected identifier, found `1`
77
//~| ERROR expected identifier, found `2`
8-
//~| ERROR missing fields `0`, `1`, `2` in initializer of `Rgb`
8+
//~| ERROR missing fields `0`, `1` and `2` in initializer of `Rgb`
99
}

‎src/test/ui/parser/struct-field-numeric-shorthand.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,11 @@ LL | let _ = Rgb { 0, 1, 2 };
2222
| |
2323
| while parsing this struct
2424

25-
error[E0063]: missing fields `0`, `1`, `2` in initializer of `Rgb`
25+
error[E0063]: missing fields `0`, `1` and `2` in initializer of `Rgb`
2626
--> $DIR/struct-field-numeric-shorthand.rs:4:13
2727
|
2828
LL | let _ = Rgb { 0, 1, 2 };
29-
| ^^^ missing `0`, `1`, `2`
29+
| ^^^ missing `0`, `1` and `2`
3030

3131
error: aborting due to 4 previous errors
3232

0 commit comments

Comments
 (0)
Please sign in to comment.