Skip to content

Commit ada312f

Browse files
committed
Address nits in trait suggestions.
1 parent 0a55aac commit ada312f

File tree

3 files changed

+50
-57
lines changed

3 files changed

+50
-57
lines changed

src/librustc_typeck/check/method/probe.rs

+35-44
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,6 @@ struct ProbeContext<'a, 'tcx:'a> {
4444
extension_candidates: Vec<Candidate<'tcx>>,
4545
impl_dups: HashSet<ast::DefId>,
4646
static_candidates: Vec<CandidateSource>,
47-
all_traits_search: bool,
4847
}
4948

5049
struct CandidateStep<'tcx> {
@@ -211,7 +210,6 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
211210
steps: Rc::new(steps),
212211
opt_simplified_steps: opt_simplified_steps,
213212
static_candidates: Vec::new(),
214-
all_traits_search: false,
215213
}
216214
}
217215

@@ -724,60 +722,53 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
724722
// THE ACTUAL SEARCH
725723

726724
fn pick(mut self) -> PickResult<'tcx> {
727-
let steps = self.steps.clone();
728-
729-
for step in steps.iter() {
730-
match self.pick_step(step) {
731-
Some(r) => {
732-
return r;
733-
}
734-
None => { }
735-
}
725+
match self.pick_core() {
726+
Some(r) => return r,
727+
None => {}
736728
}
737729

738730
let static_candidates = mem::replace(&mut self.static_candidates, vec![]);
739731

740-
let out_of_scope_traits = if !self.all_traits_search {
741-
// things failed, and we haven't yet looked through all
742-
// traits, so lets do that now:
743-
self.reset();
744-
self.all_traits_search = true;
745-
746-
let span = self.span;
747-
let tcx = self.tcx();
748-
749-
self.assemble_extension_candidates_for_all_traits();
750-
751-
match self.pick() {
752-
Ok(p) => vec![p.method_ty.container.id()],
753-
Err(Ambiguity(v)) => v.into_iter().map(|source| {
754-
match source {
755-
TraitSource(id) => id,
756-
ImplSource(impl_id) => {
757-
match ty::trait_id_of_impl(tcx, impl_id) {
758-
Some(id) => id,
759-
None => tcx.sess.span_bug(span,
760-
"found inherent method when looking \
761-
at traits")
762-
}
732+
// things failed, so lets look at all traits, for diagnostic purposes now:
733+
self.reset();
734+
735+
let span = self.span;
736+
let tcx = self.tcx();
737+
738+
self.assemble_extension_candidates_for_all_traits();
739+
740+
let out_of_scope_traits = match self.pick_core() {
741+
Some(Ok(p)) => vec![p.method_ty.container.id()],
742+
Some(Err(Ambiguity(v))) => v.into_iter().map(|source| {
743+
match source {
744+
TraitSource(id) => id,
745+
ImplSource(impl_id) => {
746+
match ty::trait_id_of_impl(tcx, impl_id) {
747+
Some(id) => id,
748+
None =>
749+
tcx.sess.span_bug(span,
750+
"found inherent method when looking at traits")
763751
}
764752
}
765-
}).collect(),
766-
// it'd be really weird for this assertion to trigger,
767-
// given the `vec![]` in the else branch below
768-
Err(NoMatch(_, others)) => {
769-
assert!(others.is_empty());
770-
vec![]
771753
}
754+
}).collect(),
755+
Some(Err(NoMatch(_, others))) => {
756+
assert!(others.is_empty());
757+
vec![]
772758
}
773-
} else {
774-
// we've just looked through all traits and didn't find
775-
// anything at all.
776-
vec![]
759+
None => vec![],
777760
};
761+
;
778762
Err(NoMatch(static_candidates, out_of_scope_traits))
779763
}
780764

765+
fn pick_core(&mut self) -> Option<PickResult<'tcx>> {
766+
let steps = self.steps.clone();
767+
768+
// find the first step that works
769+
steps.iter().filter_map(|step| self.pick_step(step)).next()
770+
}
771+
781772
fn pick_step(&mut self, step: &CandidateStep<'tcx>) -> Option<PickResult<'tcx>> {
782773
debug!("pick_step: step={}", step.repr(self.tcx()));
783774

src/librustc_typeck/check/method/suggest.rs

+8-6
Original file line numberDiff line numberDiff line change
@@ -147,16 +147,16 @@ fn suggest_traits_to_import<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
147147
candidates.sort();
148148
let msg = format!(
149149
"methods from traits can only be called if the trait is in scope; \
150-
the following {traits_are} implemented and {define} a method `{name}`:",
150+
the following {traits_are} implemented but not in scope, \
151+
perhaps add a `use` for {one_of_them}:",
151152
traits_are = if candidates.len() == 1 {"trait is"} else {"traits are"},
152-
define = if candidates.len() == 1 {"defines"} else {"define"},
153-
name = method_ustring);
153+
one_of_them = if candidates.len() == 1 {"it"} else {"one of them"});
154154

155155
fcx.sess().fileline_help(span, &msg[]);
156156

157157
for (i, trait_did) in candidates.iter().enumerate() {
158158
fcx.sess().fileline_help(span,
159-
&*format!("candidate #{}: `{}`",
159+
&*format!("candidate #{}: use `{}`",
160160
i + 1,
161161
ty::item_path_str(fcx.tcx(), *trait_did)))
162162

@@ -174,9 +174,11 @@ fn suggest_traits_to_import<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
174174
candidates.sort_by(|a, b| a.cmp(b).reverse());
175175

176176
let msg = format!(
177-
"methods from traits can only be called if the trait is implemented and \
178-
in scope; no such traits are but the following {traits_define} a method `{name}`:",
177+
"methods from traits can only be called if the trait is implemented and in scope; \
178+
the following {traits_define} a method `{name}`, \
179+
perhaps you need to implement {one_of_them}:",
179180
traits_define = if candidates.len() == 1 {"trait defines"} else {"traits define"},
181+
one_of_them = if candidates.len() == 1 {"it"} else {"one of them"},
180182
name = method_ustring);
181183

182184
fcx.sess().fileline_help(span, &msg[]);

src/test/compile-fail/no-method-suggested-traits.rs

+7-7
Original file line numberDiff line numberDiff line change
@@ -26,24 +26,24 @@ mod foo {
2626

2727
fn main() {
2828
1u32.method();
29-
//~^ ERROR does not implement
30-
//~^^ HELP the following traits are implemented and define a method `method`
29+
//~^ HELP following traits are implemented but not in scope, perhaps add a `use` for one of them
30+
//~^^ ERROR does not implement
3131
//~^^^ HELP `foo::Bar`
3232
//~^^^^ HELP `no_method_suggested_traits::foo::PubPub`
3333

3434
'a'.method();
3535
//~^ ERROR does not implement
36-
//~^^ HELP the following trait is implemented and defines a method `method`
36+
//~^^ HELP the following trait is implemented but not in scope, perhaps add a `use` for it:
3737
//~^^^ HELP `foo::Bar`
3838

3939
1i32.method();
4040
//~^ ERROR does not implement
41-
//~^^ HELP the following trait is implemented and defines a method `method`
41+
//~^^ HELP the following trait is implemented but not in scope, perhaps add a `use` for it:
4242
//~^^^ HELP `no_method_suggested_traits::foo::PubPub`
4343

4444
1u64.method();
4545
//~^ ERROR does not implement
46-
//~^^ HELP the following traits define a method `method`
46+
//~^^ HELP following traits define a method `method`, perhaps you need to implement one of them
4747
//~^^^ HELP `foo::Bar`
4848
//~^^^^ HELP `no_method_suggested_traits::foo::PubPub`
4949
//~^^^^^ HELP `no_method_suggested_traits::reexport::Reexported`
@@ -53,10 +53,10 @@ fn main() {
5353

5454
1u64.method2();
5555
//~^ ERROR does not implement
56-
//~^^ HELP the following trait defines a method `method2`
56+
//~^^ HELP the following trait defines a method `method2`, perhaps you need to implement it
5757
//~^^^ HELP `foo::Bar`
5858
1u64.method3();
5959
//~^ ERROR does not implement
60-
//~^^ HELP the following trait defines a method `method3`
60+
//~^^ HELP the following trait defines a method `method3`, perhaps you need to implement it
6161
//~^^^ HELP `no_method_suggested_traits::foo::PubPub`
6262
}

0 commit comments

Comments
 (0)