limit and delimit available fields in note
Also, don't show the note if no fields are available (usually due to privacy).
This commit is contained in:
parent
bf7e91f61d
commit
2dbfa3995e
11 changed files with 46 additions and 29 deletions
|
|
@ -2957,10 +2957,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
} else {
|
||||
err.span_label(field.span, "unknown field");
|
||||
let struct_variant_def = def.struct_variant();
|
||||
let available_field_names = self.available_field_names(
|
||||
struct_variant_def);
|
||||
err.note(&format!("available fields are: {}",
|
||||
available_field_names.join(", ")));
|
||||
let field_names = self.available_field_names(struct_variant_def);
|
||||
if !field_names.is_empty() {
|
||||
err.note(&format!("available fields are: {}",
|
||||
self.name_series_display(field_names)));
|
||||
}
|
||||
};
|
||||
}
|
||||
ty::TyRawPtr(..) => {
|
||||
|
|
@ -3000,17 +3001,28 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
find_best_match_for_name(names, &name, None)
|
||||
}
|
||||
|
||||
fn available_field_names(&self, variant: &'tcx ty::VariantDef) -> Vec<String> {
|
||||
fn available_field_names(&self, variant: &'tcx ty::VariantDef) -> Vec<ast::Name> {
|
||||
let mut available = Vec::new();
|
||||
for field in variant.fields.iter() {
|
||||
let (_, def_scope) = self.tcx.adjust(field.name, variant.did, self.body_id);
|
||||
if field.vis.is_accessible_from(def_scope, self.tcx) {
|
||||
available.push(field.name.to_string());
|
||||
available.push(field.name);
|
||||
}
|
||||
}
|
||||
available
|
||||
}
|
||||
|
||||
fn name_series_display(&self, names: Vec<ast::Name>) -> String {
|
||||
// dynamic limit, to never omit just one field
|
||||
let limit = if names.len() == 6 { 6 } else { 5 };
|
||||
let mut display = names.iter().take(limit)
|
||||
.map(|n| format!("`{}`", n)).collect::<Vec<_>>().join(", ");
|
||||
if names.len() > limit {
|
||||
display = format!("{} ... and {} others", display, names.len() - limit);
|
||||
}
|
||||
display
|
||||
}
|
||||
|
||||
// Check tuple index expressions
|
||||
fn check_tup_field(&self,
|
||||
expr: &'gcx hir::Expr,
|
||||
|
|
@ -3132,12 +3144,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
format!("`{}` does not have this field", ty));
|
||||
}
|
||||
let available_field_names = self.available_field_names(variant);
|
||||
err.note(&format!("available fields are: {}",
|
||||
available_field_names.join(", ")));
|
||||
if !available_field_names.is_empty() {
|
||||
err.note(&format!("available fields are: {}",
|
||||
self.name_series_display(available_field_names)));
|
||||
}
|
||||
}
|
||||
_ => bug!("non-ADT passed to report_unknown_field")
|
||||
}
|
||||
|
||||
};
|
||||
err.emit();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,5 +16,5 @@ fn main() {
|
|||
let s = Field::Fool { joke: 0 };
|
||||
//~^ ERROR E0559
|
||||
//~| NOTE `Field::Fool` does not have this field
|
||||
//~| NOTE available fields are: x
|
||||
//~| NOTE available fields are: `x`
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,5 +16,5 @@ fn main() {
|
|||
let s = Simba { mother: 1, father: 0 };
|
||||
//~^ ERROR E0560
|
||||
//~| NOTE `Simba` does not have this field
|
||||
//~| NOTE available fields are: mother
|
||||
//~| NOTE available fields are: `mother`
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,5 +16,5 @@ fn main() {
|
|||
let homura = Homura::Akemi { kaname: () };
|
||||
//~^ ERROR variant `Homura::Akemi` has no field named `kaname`
|
||||
//~| NOTE `Homura::Akemi` does not have this field
|
||||
//~| NOTE available fields are: madoka
|
||||
//~| NOTE available fields are: `madoka`
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ fn main() {
|
|||
let s = S{0b1: 10, 0: 11};
|
||||
//~^ ERROR struct `S` has no field named `0b1`
|
||||
//~| NOTE `S` does not have this field
|
||||
//~| NOTE available fields are: 0, 1
|
||||
//~| NOTE available fields are: `0`, `1`
|
||||
match s {
|
||||
S{0: a, 0x1: b, ..} => {}
|
||||
//~^ ERROR does not have a field named `0x1`
|
||||
|
|
|
|||
|
|
@ -18,6 +18,6 @@ fn main() {
|
|||
bar: 0
|
||||
//~^ ERROR struct `BuildData` has no field named `bar`
|
||||
//~| NOTE `BuildData` does not have this field
|
||||
//~| NOTE available fields are: foo
|
||||
//~| NOTE available fields are: `foo`
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ fn main () {
|
|||
bb: 20,
|
||||
//~^ ERROR struct `xc::B` has no field named `bb`
|
||||
//~| NOTE `xc::B` does not have this field
|
||||
//~| NOTE available fields are: a
|
||||
//~| NOTE available fields are: `a`
|
||||
};
|
||||
// local crate struct
|
||||
let l = A {
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ fn main() {
|
|||
let u = U { a: 0, b: 1, c: 2 }; //~ ERROR union expressions should have exactly one field
|
||||
//~^ ERROR union `U` has no field named `c`
|
||||
//~| NOTE `U` does not have this field
|
||||
//~| NOTE available fields are: a, b
|
||||
//~| NOTE available fields are: `a`, `b`
|
||||
let u = U { ..u }; //~ ERROR union expressions should have exactly one field
|
||||
//~^ ERROR functional record update syntax requires a struct
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ error[E0609]: no field `zz` on type `Foo`
|
|||
17 | f.zz;
|
||||
| ^^ unknown field
|
||||
|
|
||||
= note: available fields are: bar
|
||||
= note: available fields are: `bar`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
|
|||
|
|
@ -14,7 +14,11 @@ mod submodule {
|
|||
pub struct Demo {
|
||||
pub favorite_integer: isize,
|
||||
secret_integer: isize,
|
||||
pub innocently_misspellable: ()
|
||||
pub innocently_misspellable: (),
|
||||
another_field: bool,
|
||||
yet_another_field: bool,
|
||||
always_more_fields: bool,
|
||||
and_ever: bool,
|
||||
}
|
||||
|
||||
impl Demo {
|
||||
|
|
@ -34,6 +38,6 @@ fn main() {
|
|||
|
||||
let demo = Demo::default();
|
||||
let innocent_field_misaccess = demo.inocently_mispellable;
|
||||
// note shouldn't suggest private `secret_integer` field
|
||||
// note shouldn't suggest private fields
|
||||
let egregious_field_misaccess = demo.egregiously_nonexistent_field;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,30 +1,30 @@
|
|||
error[E0560]: struct `submodule::Demo` has no field named `inocently_mispellable`
|
||||
--> $DIR/issue-42599_available_fields_note.rs:22:39
|
||||
--> $DIR/issue-42599_available_fields_note.rs:26:39
|
||||
|
|
||||
22 | Self { secret_integer: 2, inocently_mispellable: () }
|
||||
26 | Self { secret_integer: 2, inocently_mispellable: () }
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^ field does not exist - did you mean `innocently_misspellable`?
|
||||
|
||||
error[E0560]: struct `submodule::Demo` has no field named `egregiously_nonexistent_field`
|
||||
--> $DIR/issue-42599_available_fields_note.rs:26:39
|
||||
--> $DIR/issue-42599_available_fields_note.rs:30:39
|
||||
|
|
||||
26 | Self { secret_integer: 3, egregiously_nonexistent_field: () }
|
||||
30 | Self { secret_integer: 3, egregiously_nonexistent_field: () }
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `submodule::Demo` does not have this field
|
||||
|
|
||||
= note: available fields are: favorite_integer, secret_integer, innocently_misspellable
|
||||
= note: available fields are: `favorite_integer`, `secret_integer`, `innocently_misspellable`, `another_field`, `yet_another_field` ... and 2 others
|
||||
|
||||
error[E0609]: no field `inocently_mispellable` on type `submodule::Demo`
|
||||
--> $DIR/issue-42599_available_fields_note.rs:36:41
|
||||
--> $DIR/issue-42599_available_fields_note.rs:40:41
|
||||
|
|
||||
36 | let innocent_field_misaccess = demo.inocently_mispellable;
|
||||
40 | let innocent_field_misaccess = demo.inocently_mispellable;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ did you mean `innocently_misspellable`?
|
||||
|
||||
error[E0609]: no field `egregiously_nonexistent_field` on type `submodule::Demo`
|
||||
--> $DIR/issue-42599_available_fields_note.rs:38:42
|
||||
--> $DIR/issue-42599_available_fields_note.rs:42:42
|
||||
|
|
||||
38 | let egregious_field_misaccess = demo.egregiously_nonexistent_field;
|
||||
42 | let egregious_field_misaccess = demo.egregiously_nonexistent_field;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unknown field
|
||||
|
|
||||
= note: available fields are: favorite_integer, innocently_misspellable
|
||||
= note: available fields are: `favorite_integer`, `innocently_misspellable`
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue