Skip to content

Commit 447d894

Browse files
committed
Use suggestion for assoc fn called like method
When encountering an unexisting method for a given trait where an associated function has the same name, suggest using the appropriate syntax, instead of using `help` text. When only one candidate is found, do not call it "candidate #1", just call it "the candidate".
1 parent dcb4056 commit 447d894

File tree

4 files changed

+51
-24
lines changed

4 files changed

+51
-24
lines changed

src/librustc_typeck/check/method/suggest.rs

+38-14
Original file line numberDiff line numberDiff line change
@@ -119,11 +119,16 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
119119
}
120120
};
121121

122-
let note_str = format!("candidate #{} is defined in an impl{} \
123-
for the type `{}`",
124-
idx + 1,
125-
insertion,
126-
impl_ty);
122+
let note_str = if sources.len() > 1 {
123+
format!("candidate #{} is defined in an impl{} for the type `{}`",
124+
idx + 1,
125+
insertion,
126+
impl_ty)
127+
} else {
128+
format!("the candidate is defined in an impl{} for the type `{}`",
129+
insertion,
130+
impl_ty)
131+
};
127132
if let Some(note_span) = note_span {
128133
// We have a span pointing to the method. Show note with snippet.
129134
err.span_note(self.tcx.sess.codemap().def_span(note_span), &note_str);
@@ -137,11 +142,18 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
137142
.unwrap();
138143
let item_span = self.tcx.sess.codemap()
139144
.def_span(self.tcx.def_span(item.def_id));
140-
span_note!(err,
141-
item_span,
142-
"candidate #{} is defined in the trait `{}`",
143-
idx + 1,
144-
self.tcx.item_path_str(trait_did));
145+
if sources.len() > 1 {
146+
span_note!(err,
147+
item_span,
148+
"candidate #{} is defined in the trait `{}`",
149+
idx + 1,
150+
self.tcx.item_path_str(trait_did));
151+
} else {
152+
span_note!(err,
153+
item_span,
154+
"the candidate is defined in the trait `{}`",
155+
self.tcx.item_path_str(trait_did));
156+
}
145157
err.help(&format!("to disambiguate the method call, write `{}::{}({}{})` \
146158
instead",
147159
self.tcx.item_path_str(trait_did),
@@ -368,7 +380,14 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
368380
if !static_sources.is_empty() {
369381
err.note("found the following associated functions; to be used as methods, \
370382
functions must have a `self` parameter");
371-
err.help(&format!("try with `{}::{}`", self.ty_to_string(actual), item_name));
383+
if let Some(expr) = rcvr_expr {
384+
err.span_suggestion(expr.span.to(span),
385+
"use associated function syntax intead",
386+
format!("{}::{}", self.ty_to_string(actual), item_name));
387+
} else {
388+
err.help(&format!("try with `{}::{}`",
389+
self.ty_to_string(actual), item_name));
390+
}
372391

373392
report_candidates(&mut err, static_sources);
374393
}
@@ -468,9 +487,14 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
468487
} else {
469488
let limit = if candidates.len() == 5 { 5 } else { 4 };
470489
for (i, trait_did) in candidates.iter().take(limit).enumerate() {
471-
msg.push_str(&format!("\ncandidate #{}: `use {};`",
472-
i + 1,
473-
self.tcx.item_path_str(*trait_did)));
490+
if candidates.len() > 1 {
491+
msg.push_str(&format!("\ncandidate #{}: `use {};`",
492+
i + 1,
493+
self.tcx.item_path_str(*trait_did)));
494+
} else {
495+
msg.push_str(&format!("\n`use {};`",
496+
self.tcx.item_path_str(*trait_did)));
497+
}
474498
}
475499
if candidates.len() > limit {
476500
msg.push_str(&format!("\nand {} others", candidates.len() - limit));

src/test/ui/hygiene/no_implicit_prelude.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ LL | ().clone() //~ ERROR no method named `clone` found
2222
|
2323
= help: items from traits can only be used if the trait is in scope
2424
= note: the following trait is implemented but not in scope, perhaps add a `use` for it:
25-
candidate #1: `use std::clone::Clone;`
25+
`use std::clone::Clone;`
2626

2727
error: aborting due to 3 previous errors
2828

src/test/ui/hygiene/trait_items.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ LL | pub macro m() { ().f() } //~ ERROR no method named `f` found for type `
99
|
1010
= help: items from traits can only be used if the trait is in scope
1111
= note: the following trait is implemented but not in scope, perhaps add a `use` for it:
12-
candidate #1: `use foo::T;`
12+
`use foo::T;`
1313

1414
error: aborting due to previous error
1515

src/test/ui/span/issue-7575.stderr

+11-8
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,11 @@ error[E0599]: no method named `f9` found for type `usize` in the current scope
22
--> $DIR/issue-7575.rs:74:18
33
|
44
LL | u.f8(42) + u.f9(342) + m.fff(42)
5-
| ^^
5+
| --^^
6+
| |
7+
| help: use associated function syntax intead: `usize::f9`
68
|
79
= note: found the following associated functions; to be used as methods, functions must have a `self` parameter
8-
= help: try with `usize::f9`
910
note: candidate #1 is defined in the trait `CtxtFn`
1011
--> $DIR/issue-7575.rs:16:5
1112
|
@@ -37,11 +38,12 @@ LL | struct Myisize(isize);
3738
| ---------------------- method `fff` not found for this
3839
...
3940
LL | u.f8(42) + u.f9(342) + m.fff(42)
40-
| ^^^
41+
| --^^^
42+
| |
43+
| help: use associated function syntax intead: `Myisize::fff`
4144
|
4245
= note: found the following associated functions; to be used as methods, functions must have a `self` parameter
43-
= help: try with `Myisize::fff`
44-
note: candidate #1 is defined in an impl for the type `Myisize`
46+
note: the candidate is defined in an impl for the type `Myisize`
4547
--> $DIR/issue-7575.rs:51:5
4648
|
4749
LL | fn fff(i: isize) -> isize {
@@ -51,11 +53,12 @@ error[E0599]: no method named `is_str` found for type `T` in the current scope
5153
--> $DIR/issue-7575.rs:82:7
5254
|
5355
LL | t.is_str()
54-
| ^^^^^^
56+
| --^^^^^^
57+
| |
58+
| help: use associated function syntax intead: `T::is_str`
5559
|
5660
= note: found the following associated functions; to be used as methods, functions must have a `self` parameter
57-
= help: try with `T::is_str`
58-
note: candidate #1 is defined in the trait `ManyImplTrait`
61+
note: the candidate is defined in the trait `ManyImplTrait`
5962
--> $DIR/issue-7575.rs:57:5
6063
|
6164
LL | fn is_str() -> bool {

0 commit comments

Comments
 (0)