Skip to content

Commit 2dbfa39

Browse files
committed
limit and delimit available fields in note
Also, don't show the note if no fields are available (usually due to privacy).
1 parent bf7e91f commit 2dbfa39

11 files changed

+46
-29
lines changed

src/librustc_typeck/check/mod.rs

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2957,10 +2957,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
29572957
} else {
29582958
err.span_label(field.span, "unknown field");
29592959
let struct_variant_def = def.struct_variant();
2960-
let available_field_names = self.available_field_names(
2961-
struct_variant_def);
2962-
err.note(&format!("available fields are: {}",
2963-
available_field_names.join(", ")));
2960+
let field_names = self.available_field_names(struct_variant_def);
2961+
if !field_names.is_empty() {
2962+
err.note(&format!("available fields are: {}",
2963+
self.name_series_display(field_names)));
2964+
}
29642965
};
29652966
}
29662967
ty::TyRawPtr(..) => {
@@ -3000,17 +3001,28 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
30003001
find_best_match_for_name(names, &name, None)
30013002
}
30023003

3003-
fn available_field_names(&self, variant: &'tcx ty::VariantDef) -> Vec<String> {
3004+
fn available_field_names(&self, variant: &'tcx ty::VariantDef) -> Vec<ast::Name> {
30043005
let mut available = Vec::new();
30053006
for field in variant.fields.iter() {
30063007
let (_, def_scope) = self.tcx.adjust(field.name, variant.did, self.body_id);
30073008
if field.vis.is_accessible_from(def_scope, self.tcx) {
3008-
available.push(field.name.to_string());
3009+
available.push(field.name);
30093010
}
30103011
}
30113012
available
30123013
}
30133014

3015+
fn name_series_display(&self, names: Vec<ast::Name>) -> String {
3016+
// dynamic limit, to never omit just one field
3017+
let limit = if names.len() == 6 { 6 } else { 5 };
3018+
let mut display = names.iter().take(limit)
3019+
.map(|n| format!("`{}`", n)).collect::<Vec<_>>().join(", ");
3020+
if names.len() > limit {
3021+
display = format!("{} ... and {} others", display, names.len() - limit);
3022+
}
3023+
display
3024+
}
3025+
30143026
// Check tuple index expressions
30153027
fn check_tup_field(&self,
30163028
expr: &'gcx hir::Expr,
@@ -3132,12 +3144,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
31323144
format!("`{}` does not have this field", ty));
31333145
}
31343146
let available_field_names = self.available_field_names(variant);
3135-
err.note(&format!("available fields are: {}",
3136-
available_field_names.join(", ")));
3147+
if !available_field_names.is_empty() {
3148+
err.note(&format!("available fields are: {}",
3149+
self.name_series_display(available_field_names)));
3150+
}
31373151
}
31383152
_ => bug!("non-ADT passed to report_unknown_field")
31393153
}
3140-
31413154
};
31423155
err.emit();
31433156
}

src/test/compile-fail/E0559.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,5 +16,5 @@ fn main() {
1616
let s = Field::Fool { joke: 0 };
1717
//~^ ERROR E0559
1818
//~| NOTE `Field::Fool` does not have this field
19-
//~| NOTE available fields are: x
19+
//~| NOTE available fields are: `x`
2020
}

src/test/compile-fail/E0560.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,5 +16,5 @@ fn main() {
1616
let s = Simba { mother: 1, father: 0 };
1717
//~^ ERROR E0560
1818
//~| NOTE `Simba` does not have this field
19-
//~| NOTE available fields are: mother
19+
//~| NOTE available fields are: `mother`
2020
}

src/test/compile-fail/issue-19922.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,5 +16,5 @@ fn main() {
1616
let homura = Homura::Akemi { kaname: () };
1717
//~^ ERROR variant `Homura::Akemi` has no field named `kaname`
1818
//~| NOTE `Homura::Akemi` does not have this field
19-
//~| NOTE available fields are: madoka
19+
//~| NOTE available fields are: `madoka`
2020
}

src/test/compile-fail/numeric-fields.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ fn main() {
1414
let s = S{0b1: 10, 0: 11};
1515
//~^ ERROR struct `S` has no field named `0b1`
1616
//~| NOTE `S` does not have this field
17-
//~| NOTE available fields are: 0, 1
17+
//~| NOTE available fields are: `0`, `1`
1818
match s {
1919
S{0: a, 0x1: b, ..} => {}
2020
//~^ ERROR does not have a field named `0x1`

src/test/compile-fail/struct-fields-too-many.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,6 @@ fn main() {
1818
bar: 0
1919
//~^ ERROR struct `BuildData` has no field named `bar`
2020
//~| NOTE `BuildData` does not have this field
21-
//~| NOTE available fields are: foo
21+
//~| NOTE available fields are: `foo`
2222
};
2323
}

src/test/compile-fail/suggest-private-fields.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ fn main () {
2828
bb: 20,
2929
//~^ ERROR struct `xc::B` has no field named `bb`
3030
//~| NOTE `xc::B` does not have this field
31-
//~| NOTE available fields are: a
31+
//~| NOTE available fields are: `a`
3232
};
3333
// local crate struct
3434
let l = A {

src/test/compile-fail/union/union-fields.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ fn main() {
2020
let u = U { a: 0, b: 1, c: 2 }; //~ ERROR union expressions should have exactly one field
2121
//~^ ERROR union `U` has no field named `c`
2222
//~| NOTE `U` does not have this field
23-
//~| NOTE available fields are: a, b
23+
//~| NOTE available fields are: `a`, `b`
2424
let u = U { ..u }; //~ ERROR union expressions should have exactly one field
2525
//~^ ERROR functional record update syntax requires a struct
2626

src/test/ui/did_you_mean/issue-36798_unknown_field.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ error[E0609]: no field `zz` on type `Foo`
44
17 | f.zz;
55
| ^^ unknown field
66
|
7-
= note: available fields are: bar
7+
= note: available fields are: `bar`
88

99
error: aborting due to previous error
1010

src/test/ui/did_you_mean/issue-42599_available_fields_note.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,11 @@ mod submodule {
1414
pub struct Demo {
1515
pub favorite_integer: isize,
1616
secret_integer: isize,
17-
pub innocently_misspellable: ()
17+
pub innocently_misspellable: (),
18+
another_field: bool,
19+
yet_another_field: bool,
20+
always_more_fields: bool,
21+
and_ever: bool,
1822
}
1923

2024
impl Demo {
@@ -34,6 +38,6 @@ fn main() {
3438

3539
let demo = Demo::default();
3640
let innocent_field_misaccess = demo.inocently_mispellable;
37-
// note shouldn't suggest private `secret_integer` field
41+
// note shouldn't suggest private fields
3842
let egregious_field_misaccess = demo.egregiously_nonexistent_field;
3943
}
Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,30 @@
11
error[E0560]: struct `submodule::Demo` has no field named `inocently_mispellable`
2-
--> $DIR/issue-42599_available_fields_note.rs:22:39
2+
--> $DIR/issue-42599_available_fields_note.rs:26:39
33
|
4-
22 | Self { secret_integer: 2, inocently_mispellable: () }
4+
26 | Self { secret_integer: 2, inocently_mispellable: () }
55
| ^^^^^^^^^^^^^^^^^^^^^^ field does not exist - did you mean `innocently_misspellable`?
66

77
error[E0560]: struct `submodule::Demo` has no field named `egregiously_nonexistent_field`
8-
--> $DIR/issue-42599_available_fields_note.rs:26:39
8+
--> $DIR/issue-42599_available_fields_note.rs:30:39
99
|
10-
26 | Self { secret_integer: 3, egregiously_nonexistent_field: () }
10+
30 | Self { secret_integer: 3, egregiously_nonexistent_field: () }
1111
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `submodule::Demo` does not have this field
1212
|
13-
= note: available fields are: favorite_integer, secret_integer, innocently_misspellable
13+
= note: available fields are: `favorite_integer`, `secret_integer`, `innocently_misspellable`, `another_field`, `yet_another_field` ... and 2 others
1414

1515
error[E0609]: no field `inocently_mispellable` on type `submodule::Demo`
16-
--> $DIR/issue-42599_available_fields_note.rs:36:41
16+
--> $DIR/issue-42599_available_fields_note.rs:40:41
1717
|
18-
36 | let innocent_field_misaccess = demo.inocently_mispellable;
18+
40 | let innocent_field_misaccess = demo.inocently_mispellable;
1919
| ^^^^^^^^^^^^^^^^^^^^^ did you mean `innocently_misspellable`?
2020

2121
error[E0609]: no field `egregiously_nonexistent_field` on type `submodule::Demo`
22-
--> $DIR/issue-42599_available_fields_note.rs:38:42
22+
--> $DIR/issue-42599_available_fields_note.rs:42:42
2323
|
24-
38 | let egregious_field_misaccess = demo.egregiously_nonexistent_field;
24+
42 | let egregious_field_misaccess = demo.egregiously_nonexistent_field;
2525
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unknown field
2626
|
27-
= note: available fields are: favorite_integer, innocently_misspellable
27+
= note: available fields are: `favorite_integer`, `innocently_misspellable`
2828

2929
error: aborting due to 4 previous errors
3030

0 commit comments

Comments
 (0)