diff options
| author | bors <bors@rust-lang.org> | 2015-01-18 09:21:42 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2015-01-18 09:21:42 +0000 |
| commit | 30f081e54843952e34b0632e1b0ec54547bf6e3c (patch) | |
| tree | de3a3606eb86aa19718f42a68723c05f575ea611 /src | |
| parent | a833337943300db1c310a4cf9c84b7b4ef4e9468 (diff) | |
| parent | ada312ffbbfa03ac15c620f7a5702ef29b6e1321 (diff) | |
| download | rust-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.rs | 79 | ||||
| -rw-r--r-- | src/librustc_typeck/check/method/suggest.rs | 14 | ||||
| -rw-r--r-- | src/test/compile-fail/no-method-suggested-traits.rs | 14 |
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` } |
