about summary refs log tree commit diff
diff options
context:
space:
mode:
authorZack M. Davis <code@zackmdavis.net>2017-07-31 00:31:32 -0700
committerZack M. Davis <code@zackmdavis.net>2017-07-31 18:45:02 -0700
commit2dbfa3995e44af6ce4fbeaa2f9de4730e5d2fbd5 (patch)
treea80b279ec5726f8737c00742ca0559c15a3e3f33
parentbf7e91f61da8a5ca74c7d97f6f2bc978c0366256 (diff)
downloadrust-2dbfa3995e44af6ce4fbeaa2f9de4730e5d2fbd5.tar.gz
rust-2dbfa3995e44af6ce4fbeaa2f9de4730e5d2fbd5.zip
limit and delimit available fields in note
Also, don't show the note if no fields are available (usually due to
privacy).
-rw-r--r--src/librustc_typeck/check/mod.rs31
-rw-r--r--src/test/compile-fail/E0559.rs2
-rw-r--r--src/test/compile-fail/E0560.rs2
-rw-r--r--src/test/compile-fail/issue-19922.rs2
-rw-r--r--src/test/compile-fail/numeric-fields.rs2
-rw-r--r--src/test/compile-fail/struct-fields-too-many.rs2
-rw-r--r--src/test/compile-fail/suggest-private-fields.rs2
-rw-r--r--src/test/compile-fail/union/union-fields.rs2
-rw-r--r--src/test/ui/did_you_mean/issue-36798_unknown_field.stderr2
-rw-r--r--src/test/ui/did_you_mean/issue-42599_available_fields_note.rs8
-rw-r--r--src/test/ui/did_you_mean/issue-42599_available_fields_note.stderr20
11 files changed, 46 insertions, 29 deletions
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index 4b40a46f74e..178331afabe 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -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();
     }
diff --git a/src/test/compile-fail/E0559.rs b/src/test/compile-fail/E0559.rs
index 21bb2dc7002..e8b0915d2b5 100644
--- a/src/test/compile-fail/E0559.rs
+++ b/src/test/compile-fail/E0559.rs
@@ -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`
 }
diff --git a/src/test/compile-fail/E0560.rs b/src/test/compile-fail/E0560.rs
index 7aa6b2e86d6..955ef7ca99c 100644
--- a/src/test/compile-fail/E0560.rs
+++ b/src/test/compile-fail/E0560.rs
@@ -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`
 }
diff --git a/src/test/compile-fail/issue-19922.rs b/src/test/compile-fail/issue-19922.rs
index 429c4384117..938ccb343d4 100644
--- a/src/test/compile-fail/issue-19922.rs
+++ b/src/test/compile-fail/issue-19922.rs
@@ -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`
 }
diff --git a/src/test/compile-fail/numeric-fields.rs b/src/test/compile-fail/numeric-fields.rs
index 242c3a3a33d..d6e091a1472 100644
--- a/src/test/compile-fail/numeric-fields.rs
+++ b/src/test/compile-fail/numeric-fields.rs
@@ -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`
diff --git a/src/test/compile-fail/struct-fields-too-many.rs b/src/test/compile-fail/struct-fields-too-many.rs
index 78ab94d5fb4..b1af142ad0f 100644
--- a/src/test/compile-fail/struct-fields-too-many.rs
+++ b/src/test/compile-fail/struct-fields-too-many.rs
@@ -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`
     };
 }
diff --git a/src/test/compile-fail/suggest-private-fields.rs b/src/test/compile-fail/suggest-private-fields.rs
index 959932af9b1..d0752b5f02f 100644
--- a/src/test/compile-fail/suggest-private-fields.rs
+++ b/src/test/compile-fail/suggest-private-fields.rs
@@ -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 {
diff --git a/src/test/compile-fail/union/union-fields.rs b/src/test/compile-fail/union/union-fields.rs
index 2bcc2204e33..124b16f99b1 100644
--- a/src/test/compile-fail/union/union-fields.rs
+++ b/src/test/compile-fail/union/union-fields.rs
@@ -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
 
diff --git a/src/test/ui/did_you_mean/issue-36798_unknown_field.stderr b/src/test/ui/did_you_mean/issue-36798_unknown_field.stderr
index 610466c894a..20bb7d4c91d 100644
--- a/src/test/ui/did_you_mean/issue-36798_unknown_field.stderr
+++ b/src/test/ui/did_you_mean/issue-36798_unknown_field.stderr
@@ -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
 
diff --git a/src/test/ui/did_you_mean/issue-42599_available_fields_note.rs b/src/test/ui/did_you_mean/issue-42599_available_fields_note.rs
index 4b0cc7b96a7..7fe99508012 100644
--- a/src/test/ui/did_you_mean/issue-42599_available_fields_note.rs
+++ b/src/test/ui/did_you_mean/issue-42599_available_fields_note.rs
@@ -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;
 }
diff --git a/src/test/ui/did_you_mean/issue-42599_available_fields_note.stderr b/src/test/ui/did_you_mean/issue-42599_available_fields_note.stderr
index 17edac92fd9..e2bb7fbd9a8 100644
--- a/src/test/ui/did_you_mean/issue-42599_available_fields_note.stderr
+++ b/src/test/ui/did_you_mean/issue-42599_available_fields_note.stderr
@@ -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