mirror of
https://github.com/rust-lang/rust.git
synced 2025-04-28 11:07:42 +00:00
auto merge of #21276 : huonw/rust/trait-suggestion-nits, r=nikomatsakis
Follow up to #21008. r? @nikomatsakis
This commit is contained in:
commit
30f081e548
@ -44,7 +44,6 @@ struct ProbeContext<'a, 'tcx:'a> {
|
|||||||
extension_candidates: Vec<Candidate<'tcx>>,
|
extension_candidates: Vec<Candidate<'tcx>>,
|
||||||
impl_dups: HashSet<ast::DefId>,
|
impl_dups: HashSet<ast::DefId>,
|
||||||
static_candidates: Vec<CandidateSource>,
|
static_candidates: Vec<CandidateSource>,
|
||||||
all_traits_search: bool,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct CandidateStep<'tcx> {
|
struct CandidateStep<'tcx> {
|
||||||
@ -211,7 +210,6 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
|
|||||||
steps: Rc::new(steps),
|
steps: Rc::new(steps),
|
||||||
opt_simplified_steps: opt_simplified_steps,
|
opt_simplified_steps: opt_simplified_steps,
|
||||||
static_candidates: Vec::new(),
|
static_candidates: Vec::new(),
|
||||||
all_traits_search: false,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -724,60 +722,53 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
|
|||||||
// THE ACTUAL SEARCH
|
// THE ACTUAL SEARCH
|
||||||
|
|
||||||
fn pick(mut self) -> PickResult<'tcx> {
|
fn pick(mut self) -> PickResult<'tcx> {
|
||||||
let steps = self.steps.clone();
|
match self.pick_core() {
|
||||||
|
Some(r) => return r,
|
||||||
for step in steps.iter() {
|
None => {}
|
||||||
match self.pick_step(step) {
|
|
||||||
Some(r) => {
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
None => { }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let static_candidates = mem::replace(&mut self.static_candidates, vec![]);
|
let static_candidates = mem::replace(&mut self.static_candidates, vec![]);
|
||||||
|
|
||||||
let out_of_scope_traits = if !self.all_traits_search {
|
// things failed, so lets look at all traits, for diagnostic purposes now:
|
||||||
// things failed, and we haven't yet looked through all
|
self.reset();
|
||||||
// traits, so lets do that now:
|
|
||||||
self.reset();
|
|
||||||
self.all_traits_search = true;
|
|
||||||
|
|
||||||
let span = self.span;
|
let span = self.span;
|
||||||
let tcx = self.tcx();
|
let tcx = self.tcx();
|
||||||
|
|
||||||
self.assemble_extension_candidates_for_all_traits();
|
self.assemble_extension_candidates_for_all_traits();
|
||||||
|
|
||||||
match self.pick() {
|
let out_of_scope_traits = match self.pick_core() {
|
||||||
Ok(p) => vec![p.method_ty.container.id()],
|
Some(Ok(p)) => vec![p.method_ty.container.id()],
|
||||||
Err(Ambiguity(v)) => v.into_iter().map(|source| {
|
Some(Err(Ambiguity(v))) => v.into_iter().map(|source| {
|
||||||
match source {
|
match source {
|
||||||
TraitSource(id) => id,
|
TraitSource(id) => id,
|
||||||
ImplSource(impl_id) => {
|
ImplSource(impl_id) => {
|
||||||
match ty::trait_id_of_impl(tcx, impl_id) {
|
match ty::trait_id_of_impl(tcx, impl_id) {
|
||||||
Some(id) => id,
|
Some(id) => id,
|
||||||
None => tcx.sess.span_bug(span,
|
None =>
|
||||||
"found inherent method when looking \
|
tcx.sess.span_bug(span,
|
||||||
at traits")
|
"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 {
|
None => vec![],
|
||||||
// we've just looked through all traits and didn't find
|
|
||||||
// anything at all.
|
|
||||||
vec![]
|
|
||||||
};
|
};
|
||||||
|
;
|
||||||
Err(NoMatch(static_candidates, out_of_scope_traits))
|
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>> {
|
fn pick_step(&mut self, step: &CandidateStep<'tcx>) -> Option<PickResult<'tcx>> {
|
||||||
debug!("pick_step: step={}", step.repr(self.tcx()));
|
debug!("pick_step: step={}", step.repr(self.tcx()));
|
||||||
|
|
||||||
|
@ -147,16 +147,16 @@ fn suggest_traits_to_import<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
|
|||||||
candidates.sort();
|
candidates.sort();
|
||||||
let msg = format!(
|
let msg = format!(
|
||||||
"methods from traits can only be called if the trait is in scope; \
|
"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"},
|
traits_are = if candidates.len() == 1 {"trait is"} else {"traits are"},
|
||||||
define = if candidates.len() == 1 {"defines"} else {"define"},
|
one_of_them = if candidates.len() == 1 {"it"} else {"one of them"});
|
||||||
name = method_ustring);
|
|
||||||
|
|
||||||
fcx.sess().fileline_help(span, &msg[]);
|
fcx.sess().fileline_help(span, &msg[]);
|
||||||
|
|
||||||
for (i, trait_did) in candidates.iter().enumerate() {
|
for (i, trait_did) in candidates.iter().enumerate() {
|
||||||
fcx.sess().fileline_help(span,
|
fcx.sess().fileline_help(span,
|
||||||
&*format!("candidate #{}: `{}`",
|
&*format!("candidate #{}: use `{}`",
|
||||||
i + 1,
|
i + 1,
|
||||||
ty::item_path_str(fcx.tcx(), *trait_did)))
|
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());
|
candidates.sort_by(|a, b| a.cmp(b).reverse());
|
||||||
|
|
||||||
let msg = format!(
|
let msg = format!(
|
||||||
"methods from traits can only be called if the trait is implemented and \
|
"methods from traits can only be called if the trait is implemented and in scope; \
|
||||||
in scope; no such traits are but the following {traits_define} a method `{name}`:",
|
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"},
|
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);
|
name = method_ustring);
|
||||||
|
|
||||||
fcx.sess().fileline_help(span, &msg[]);
|
fcx.sess().fileline_help(span, &msg[]);
|
||||||
|
@ -26,24 +26,24 @@ mod foo {
|
|||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
1u32.method();
|
1u32.method();
|
||||||
//~^ ERROR does not implement
|
//~^ HELP following traits are implemented but not in scope, perhaps add a `use` for one of them
|
||||||
//~^^ HELP the following traits are implemented and define a method `method`
|
//~^^ ERROR does not implement
|
||||||
//~^^^ HELP `foo::Bar`
|
//~^^^ HELP `foo::Bar`
|
||||||
//~^^^^ HELP `no_method_suggested_traits::foo::PubPub`
|
//~^^^^ HELP `no_method_suggested_traits::foo::PubPub`
|
||||||
|
|
||||||
'a'.method();
|
'a'.method();
|
||||||
//~^ ERROR does not implement
|
//~^ 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`
|
//~^^^ HELP `foo::Bar`
|
||||||
|
|
||||||
1i32.method();
|
1i32.method();
|
||||||
//~^ ERROR does not implement
|
//~^ 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`
|
//~^^^ HELP `no_method_suggested_traits::foo::PubPub`
|
||||||
|
|
||||||
1u64.method();
|
1u64.method();
|
||||||
//~^ ERROR does not implement
|
//~^ 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 `foo::Bar`
|
||||||
//~^^^^ HELP `no_method_suggested_traits::foo::PubPub`
|
//~^^^^ HELP `no_method_suggested_traits::foo::PubPub`
|
||||||
//~^^^^^ HELP `no_method_suggested_traits::reexport::Reexported`
|
//~^^^^^ HELP `no_method_suggested_traits::reexport::Reexported`
|
||||||
@ -53,10 +53,10 @@ fn main() {
|
|||||||
|
|
||||||
1u64.method2();
|
1u64.method2();
|
||||||
//~^ ERROR does not implement
|
//~^ 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`
|
//~^^^ HELP `foo::Bar`
|
||||||
1u64.method3();
|
1u64.method3();
|
||||||
//~^ ERROR does not implement
|
//~^ 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`
|
//~^^^ HELP `no_method_suggested_traits::foo::PubPub`
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user