about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2015-01-18 09:21:42 +0000
committerbors <bors@rust-lang.org>2015-01-18 09:21:42 +0000
commit30f081e54843952e34b0632e1b0ec54547bf6e3c (patch)
treede3a3606eb86aa19718f42a68723c05f575ea611 /src
parenta833337943300db1c310a4cf9c84b7b4ef4e9468 (diff)
parentada312ffbbfa03ac15c620f7a5702ef29b6e1321 (diff)
downloadrust-30f081e54843952e34b0632e1b0ec54547bf6e3c.tar.gz
rust-30f081e54843952e34b0632e1b0ec54547bf6e3c.zip
auto merge of #21276 : huonw/rust/trait-suggestion-nits, r=nikomatsakis
Follow up to #21008.

r? @nikomatsakis 
Diffstat (limited to 'src')
-rw-r--r--src/librustc_typeck/check/method/probe.rs79
-rw-r--r--src/librustc_typeck/check/method/suggest.rs14
-rw-r--r--src/test/compile-fail/no-method-suggested-traits.rs14
3 files changed, 50 insertions, 57 deletions
diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs
index 9df8875152e..9bbc7b258e2 100644
--- a/src/librustc_typeck/check/method/probe.rs
+++ b/src/librustc_typeck/check/method/probe.rs
@@ -44,7 +44,6 @@ struct ProbeContext<'a, 'tcx:'a> {
     extension_candidates: Vec<Candidate<'tcx>>,
     impl_dups: HashSet<ast::DefId>,
     static_candidates: Vec<CandidateSource>,
-    all_traits_search: bool,
 }
 
 struct CandidateStep<'tcx> {
@@ -211,7 +210,6 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
             steps: Rc::new(steps),
             opt_simplified_steps: opt_simplified_steps,
             static_candidates: Vec::new(),
-            all_traits_search: false,
         }
     }
 
@@ -724,60 +722,53 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
     // THE ACTUAL SEARCH
 
     fn pick(mut self) -> PickResult<'tcx> {
-        let steps = self.steps.clone();
-
-        for step in steps.iter() {
-            match self.pick_step(step) {
-                Some(r) => {
-                    return r;
-                }
-                None => { }
-            }
+        match self.pick_core() {
+            Some(r) => return r,
+            None => {}
         }
 
         let static_candidates = mem::replace(&mut self.static_candidates, vec![]);
 
-        let out_of_scope_traits = if !self.all_traits_search {
-            // things failed, and we haven't yet looked through all
-            // traits, so lets do that now:
-            self.reset();
-            self.all_traits_search = true;
-
-            let span = self.span;
-            let tcx = self.tcx();
-
-            self.assemble_extension_candidates_for_all_traits();
-
-            match self.pick() {
-                Ok(p) => vec![p.method_ty.container.id()],
-                Err(Ambiguity(v)) => v.into_iter().map(|source| {
-                    match source {
-                        TraitSource(id) => id,
-                        ImplSource(impl_id) => {
-                            match ty::trait_id_of_impl(tcx, impl_id) {
-                                Some(id) => id,
-                                None => tcx.sess.span_bug(span,
-                                                          "found inherent method when looking \
-                                                           at traits")
-                            }
+        // things failed, so lets look at all traits, for diagnostic purposes now:
+        self.reset();
+
+        let span = self.span;
+        let tcx = self.tcx();
+
+        self.assemble_extension_candidates_for_all_traits();
+
+        let out_of_scope_traits = match self.pick_core() {
+            Some(Ok(p)) => vec![p.method_ty.container.id()],
+            Some(Err(Ambiguity(v))) => v.into_iter().map(|source| {
+                match source {
+                    TraitSource(id) => id,
+                    ImplSource(impl_id) => {
+                        match ty::trait_id_of_impl(tcx, impl_id) {
+                            Some(id) => id,
+                            None =>
+                                tcx.sess.span_bug(span,
+                                                  "found inherent method when looking at traits")
                         }
                     }
-                }).collect(),
-                // it'd be really weird for this assertion to trigger,
-                // given the `vec![]` in the else branch below
-                Err(NoMatch(_, others)) => {
-                    assert!(others.is_empty());
-                    vec![]
                 }
+            }).collect(),
+            Some(Err(NoMatch(_, others))) => {
+                assert!(others.is_empty());
+                vec![]
             }
-        } else {
-            // we've just looked through all traits and didn't find
-            // anything at all.
-            vec![]
+            None => vec![],
         };
+;
         Err(NoMatch(static_candidates, out_of_scope_traits))
     }
 
+    fn pick_core(&mut self) -> Option<PickResult<'tcx>> {
+        let steps = self.steps.clone();
+
+        // find the first step that works
+        steps.iter().filter_map(|step| self.pick_step(step)).next()
+    }
+
     fn pick_step(&mut self, step: &CandidateStep<'tcx>) -> Option<PickResult<'tcx>> {
         debug!("pick_step: step={}", step.repr(self.tcx()));
 
diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs
index 013c6e2f953..2a89a1d28bf 100644
--- a/src/librustc_typeck/check/method/suggest.rs
+++ b/src/librustc_typeck/check/method/suggest.rs
@@ -147,16 +147,16 @@ fn suggest_traits_to_import<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
         candidates.sort();
         let msg = format!(
             "methods from traits can only be called if the trait is in scope; \
-             the following {traits_are} implemented and {define} a method `{name}`:",
+             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"},
-            define = if candidates.len() == 1 {"defines"} else {"define"},
-            name = method_ustring);
+            one_of_them = if candidates.len() == 1 {"it"} else {"one of them"});
 
         fcx.sess().fileline_help(span, &msg[]);
 
         for (i, trait_did) in candidates.iter().enumerate() {
             fcx.sess().fileline_help(span,
-                                     &*format!("candidate #{}: `{}`",
+                                     &*format!("candidate #{}: use `{}`",
                                                i + 1,
                                                ty::item_path_str(fcx.tcx(), *trait_did)))
 
@@ -174,9 +174,11 @@ fn suggest_traits_to_import<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
         candidates.sort_by(|a, b| a.cmp(b).reverse());
 
         let msg = format!(
-            "methods from traits can only be called if the trait is implemented and \
-             in scope; no such traits are but the following {traits_define} a method `{name}`:",
+            "methods from traits can only be called if the trait is implemented and in scope; \
+             the following {traits_define} a method `{name}`, \
+             perhaps you need to implement {one_of_them}:",
             traits_define = if candidates.len() == 1 {"trait defines"} else {"traits define"},
+            one_of_them = if candidates.len() == 1 {"it"} else {"one of them"},
             name = method_ustring);
 
         fcx.sess().fileline_help(span, &msg[]);
diff --git a/src/test/compile-fail/no-method-suggested-traits.rs b/src/test/compile-fail/no-method-suggested-traits.rs
index 277800778a8..ba8121eb5cc 100644
--- a/src/test/compile-fail/no-method-suggested-traits.rs
+++ b/src/test/compile-fail/no-method-suggested-traits.rs
@@ -26,24 +26,24 @@ mod foo {
 
 fn main() {
     1u32.method();
-    //~^ ERROR does not implement
-    //~^^ HELP the following traits are implemented and define a method `method`
+    //~^ HELP following traits are implemented but not in scope, perhaps add a `use` for one of them
+    //~^^ ERROR does not implement
     //~^^^ HELP `foo::Bar`
     //~^^^^ HELP `no_method_suggested_traits::foo::PubPub`
 
     'a'.method();
     //~^ ERROR does not implement
-    //~^^ HELP the following trait is implemented and defines a method `method`
+    //~^^ HELP the following trait is implemented but not in scope, perhaps add a `use` for it:
     //~^^^ HELP `foo::Bar`
 
     1i32.method();
     //~^ ERROR does not implement
-    //~^^ HELP the following trait is implemented and defines a method `method`
+    //~^^ HELP the following trait is implemented but not in scope, perhaps add a `use` for it:
     //~^^^ HELP `no_method_suggested_traits::foo::PubPub`
 
     1u64.method();
     //~^ ERROR does not implement
-    //~^^ HELP the following traits define a method `method`
+    //~^^ HELP following traits define a method `method`, perhaps you need to implement one of them
     //~^^^ HELP `foo::Bar`
     //~^^^^ HELP `no_method_suggested_traits::foo::PubPub`
     //~^^^^^ HELP `no_method_suggested_traits::reexport::Reexported`
@@ -53,10 +53,10 @@ fn main() {
 
     1u64.method2();
     //~^ ERROR does not implement
-    //~^^ HELP the following trait defines a method `method2`
+    //~^^ HELP the following trait defines a method `method2`, perhaps you need to implement it
     //~^^^ HELP `foo::Bar`
     1u64.method3();
     //~^ ERROR does not implement
-    //~^^ HELP the following trait defines a method `method3`
+    //~^^ HELP the following trait defines a method `method3`, perhaps you need to implement it
     //~^^^ HELP `no_method_suggested_traits::foo::PubPub`
 }