]> git.lizzy.rs Git - rust.git/commitdiff
Tweak error message
authorscalexm <martin.alex32@hotmail.fr>
Thu, 3 Aug 2017 11:50:06 +0000 (13:50 +0200)
committerscalexm <martin.alex32@hotmail.fr>
Thu, 3 Aug 2017 12:40:40 +0000 (14:40 +0200)
src/librustc_typeck/check/method/confirm.rs
src/librustc_typeck/check/method/mod.rs
src/librustc_typeck/check/method/suggest.rs
src/test/compile-fail/issue-35976.rs [deleted file]
src/test/ui/issue-35976.rs [new file with mode: 0644]
src/test/ui/issue-35976.stderr [new file with mode: 0644]

index 0ab75ad622ce0195660e73f7a5bfff560fe9850a..fd148062372fe427a10d940418f02262cb34fcdb 100644 (file)
@@ -110,8 +110,12 @@ fn confirm(&mut self,
         self.unify_receivers(self_ty, method_sig.inputs()[0]);
 
         // Add any trait/regions obligations specified on the method's type parameters.
-        let method_ty = self.tcx.mk_fn_ptr(ty::Binder(method_sig));
-        self.add_obligations(method_ty, all_substs, &method_predicates);
+        // We won't add these if we encountered an illegal sized bound, so that we can use
+        // a custom error in that case.
+        if !rerun {
+            let method_ty = self.tcx.mk_fn_ptr(ty::Binder(method_sig));
+            self.add_obligations(method_ty, all_substs, &method_predicates);
+        }
 
         // Create the final `MethodCallee`.
         let callee = MethodCallee {
index f929a7ef49e1a5acdb7d5404cb9dede3f5d2c2a7..eda17ab02c49594969c08a5b140e2bfdf4ad6b38 100644 (file)
@@ -60,6 +60,10 @@ pub enum MethodError<'tcx> {
 
     // Found an applicable method, but it is not visible.
     PrivateMatch(Def),
+
+    // Found a `Self: Sized` bound where `Self` is a trait object, also the caller may have
+    // forgotten to import a trait.
+    IllegalSizedBound(Vec<DefId>),
 }
 
 // Contains a list of static methods that may apply, a list of unsatisfied trait predicates which
@@ -112,6 +116,7 @@ pub fn method_exists(&self,
             Err(Ambiguity(..)) => true,
             Err(ClosureAmbiguity(..)) => true,
             Err(PrivateMatch(..)) => allow_private,
+            Err(IllegalSizedBound(..)) => true,
         }
     }
 
@@ -173,13 +178,15 @@ pub fn lookup_method(&self,
                                         self_ty,
                                         call_expr,
                                         ProbeScope::AllTraits) {
+
+                    // If we find a different result the caller probably forgot to import a trait.
                     Ok(ref new_pick) if *new_pick != pick => vec![new_pick.item.container.id()],
-                    Err(MethodError::Ambiguity(ref sources)) => {
+                    Err(Ambiguity(ref sources)) => {
                         sources.iter()
                                .filter_map(|source| {
                                    match *source {
                                        // Note: this cannot come from an inherent impl,
-                                       // because the first probe succeeded.
+                                       // because the first probing succeeded.
                                        ImplSource(def) => self.tcx.trait_id_of_impl(def),
                                        TraitSource(_) => None,
                                    }
@@ -189,19 +196,7 @@ pub fn lookup_method(&self,
                     _ => Vec::new(),
                 };
 
-            // If we find a different result, the caller probably forgot to import a trait.
-            // We span an error with an appropriate help message.
-            if !candidates.is_empty() {
-                let error = MethodError::NoMatch(
-                    NoMatchData::new(Vec::new(), Vec::new(), candidates, probe::Mode::MethodCall)
-                );
-                self.report_method_error(span,
-                                         self_ty,
-                                         segment.name,
-                                         Some(self_expr),
-                                         error,
-                                         None);
-            }
+            return Err(IllegalSizedBound(candidates));
         }
 
         Ok(result.callee)
index 4faf71e0cc94514a279a83267a2320f467cc670a..c480febdec66f5c35be501f629ea8e409d4e7454 100644 (file)
@@ -315,7 +315,42 @@ macro_rules! report_function {
                 let msg = format!("{} `{}` is private", def.kind_name(), item_name);
                 self.tcx.sess.span_err(span, &msg);
             }
+
+            MethodError::IllegalSizedBound(candidates) => {
+                let msg = format!("the `{}` method cannot be invoked on a trait object", item_name);
+                let mut err = self.sess().struct_span_err(span, &msg);
+                if !candidates.is_empty() {
+                    let help = format!("{an}other candidate{s} {were} found in the following \
+                                        trait{s}, perhaps add a `use` for {one_of_them}:",
+                                    an = if candidates.len() == 1 {"an" } else { "" },
+                                    s = if candidates.len() == 1 { "" } else { "s" },
+                                    were = if candidates.len() == 1 { "was" } else { "were" },
+                                    one_of_them = if candidates.len() == 1 {
+                                        "it"
+                                    } else {
+                                        "one_of_them"
+                                    });
+                    self.suggest_use_candidates(&mut err, help, candidates);
+                }
+                err.emit();
+            }
+        }
+    }
+
+    fn suggest_use_candidates(&self,
+                              err: &mut DiagnosticBuilder,
+                              mut msg: String,
+                              candidates: Vec<DefId>) {
+        let limit = if candidates.len() == 5 { 5 } else { 4 };
+        for (i, trait_did) in candidates.iter().take(limit).enumerate() {
+            msg.push_str(&format!("\ncandidate #{}: `use {};`",
+                                    i + 1,
+                                    self.tcx.item_path_str(*trait_did)));
+        }
+        if candidates.len() > limit {
+            msg.push_str(&format!("\nand {} others", candidates.len() - limit));
         }
+        err.note(&msg[..]);
     }
 
     fn suggest_traits_to_import(&self,
@@ -330,30 +365,20 @@ fn suggest_traits_to_import(&self,
             candidates.sort();
             candidates.dedup();
             err.help("items from traits can only be used if the trait is in scope");
-            let mut msg = format!("the following {traits_are} implemented but not in scope, \
-                                   perhaps add a `use` for {one_of_them}:",
-                              traits_are = if candidates.len() == 1 {
-                                  "trait is"
-                              } else {
-                                  "traits are"
-                              },
-                              one_of_them = if candidates.len() == 1 {
-                                  "it"
-                              } else {
-                                  "one of them"
-                              });
-
-            let limit = if candidates.len() == 5 { 5 } else { 4 };
-            for (i, trait_did) in candidates.iter().take(limit).enumerate() {
-                msg.push_str(&format!("\ncandidate #{}: `use {};`",
-                                      i + 1,
-                                      self.tcx.item_path_str(*trait_did)));
-            }
-            if candidates.len() > limit {
-                msg.push_str(&format!("\nand {} others", candidates.len() - limit));
-            }
-            err.note(&msg[..]);
-
+            let msg = format!("the following {traits_are} implemented but not in scope, \
+                               perhaps add a `use` for {one_of_them}:",
+                            traits_are = if candidates.len() == 1 {
+                                "trait is"
+                            } else {
+                                "traits are"
+                            },
+                            one_of_them = if candidates.len() == 1 {
+                                "it"
+                            } else {
+                                "one of them"
+                            });
+
+            self.suggest_use_candidates(err, msg, candidates);
             return;
         }
 
diff --git a/src/test/compile-fail/issue-35976.rs b/src/test/compile-fail/issue-35976.rs
deleted file mode 100644 (file)
index 194616c..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-mod private {
-    pub trait Future {
-        fn wait(&self) where Self: Sized;
-    }
-
-    impl Future for Box<Future> {
-        fn wait(&self) { }
-    }
-}
-
-//use private::Future;
-
-fn bar(arg: Box<private::Future>) {
-    arg.wait();
-    //~^ ERROR no method named `wait` found for type `std::boxed::Box<private::Future + 'static>`
-    //~| the following trait is implemented but not in scope
-    //~| ERROR the trait bound `private::Future + 'static: std::marker::Sized` is not satisfied
-    //~| `private::Future + 'static` does not have a constant size known at compile-time
-}
-
-fn main() {
-
-}
diff --git a/src/test/ui/issue-35976.rs b/src/test/ui/issue-35976.rs
new file mode 100644 (file)
index 0000000..169d7b5
--- /dev/null
@@ -0,0 +1,31 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+mod private {
+    pub trait Future {
+        fn wait(&self) where Self: Sized;
+    }
+
+    impl Future for Box<Future> {
+        fn wait(&self) { }
+    }
+}
+
+//use private::Future;
+
+fn bar(arg: Box<private::Future>) {
+    arg.wait();
+    //~^ ERROR the `wait` method cannot be invoked on a trait object
+    //~| another candidate was found in the following trait, perhaps add a `use` for it:
+}
+
+fn main() {
+
+}
diff --git a/src/test/ui/issue-35976.stderr b/src/test/ui/issue-35976.stderr
new file mode 100644 (file)
index 0000000..9fb6744
--- /dev/null
@@ -0,0 +1,11 @@
+error: the `wait` method cannot be invoked on a trait object
+  --> $DIR/issue-35976.rs:24:9
+   |
+24 |     arg.wait();
+   |         ^^^^
+   |
+   = note: another candidate was found in the following trait, perhaps add a `use` for it:
+           candidate #1: `use private::Future;`
+
+error: aborting due to previous error
+