extension_candidates: Vec<Candidate<'tcx>>,
impl_dups: HashSet<ast::DefId>,
static_candidates: Vec<CandidateSource>,
- all_traits_search: bool,
}
struct CandidateStep<'tcx> {
steps: Rc::new(steps),
opt_simplified_steps: opt_simplified_steps,
static_candidates: Vec::new(),
- all_traits_search: false,
}
}
// 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()));
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)))
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[]);
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`
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`
}