]> git.lizzy.rs Git - rust.git/commitdiff
Address nits in trait suggestions.
authorHuon Wilson <dbau.pp+github@gmail.com>
Sat, 17 Jan 2015 01:29:26 +0000 (12:29 +1100)
committerHuon Wilson <dbau.pp+github@gmail.com>
Sat, 17 Jan 2015 01:47:49 +0000 (12:47 +1100)
src/librustc_typeck/check/method/probe.rs
src/librustc_typeck/check/method/suggest.rs
src/test/compile-fail/no-method-suggested-traits.rs

index 9df8875152e3b94e0f9bc40434f9005597a0bb49..9bbc7b258e244986cd8521c0f4b220ea12e60e75 100644 (file)
@@ -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 @@ fn new(fcx: &'a FnCtxt<'a,'tcx>,
             steps: Rc::new(steps),
             opt_simplified_steps: opt_simplified_steps,
             static_candidates: Vec::new(),
-            all_traits_search: false,
         }
     }
 
@@ -724,60 +722,53 @@ fn assemble_where_clause_candidates(&mut self,
     // 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()));
 
index 013c6e2f953a07f4d931106b3fbd87aa0e54afcd..2a89a1d28bfc6e344828072857649f48662036dd 100644 (file)
@@ -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[]);
index 277800778a87ebc67c493c2e15f13c7e545e1d3c..ba8121eb5cc35883be6c409cbc72de4d3a8bc783 100644 (file)
@@ -26,24 +26,24 @@ impl Bar for char {}
 
 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`
 }