Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tweak output on E0599 for assoc fn used as method #51135

Merged
merged 5 commits into from
Jun 2, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 47 additions & 15 deletions src/librustc_typeck/check/method/suggest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,11 +119,16 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
}
};

let note_str = format!("candidate #{} is defined in an impl{} \
for the type `{}`",
idx + 1,
insertion,
impl_ty);
let note_str = if sources.len() > 1 {
format!("candidate #{} is defined in an impl{} for the type `{}`",
idx + 1,
insertion,
impl_ty)
} else {
format!("the candidate is defined in an impl{} for the type `{}`",
insertion,
impl_ty)
};
if let Some(note_span) = note_span {
// We have a span pointing to the method. Show note with snippet.
err.span_note(self.tcx.sess.codemap().def_span(note_span), &note_str);
Expand All @@ -137,11 +142,18 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
.unwrap();
let item_span = self.tcx.sess.codemap()
.def_span(self.tcx.def_span(item.def_id));
span_note!(err,
item_span,
"candidate #{} is defined in the trait `{}`",
idx + 1,
self.tcx.item_path_str(trait_did));
if sources.len() > 1 {
span_note!(err,
item_span,
"candidate #{} is defined in the trait `{}`",
idx + 1,
self.tcx.item_path_str(trait_did));
} else {
span_note!(err,
item_span,
"the candidate is defined in the trait `{}`",
self.tcx.item_path_str(trait_did));
}
err.help(&format!("to disambiguate the method call, write `{}::{}({}{})` \
instead",
self.tcx.item_path_str(trait_did),
Expand Down Expand Up @@ -285,7 +297,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
tcx.sess.diagnostic().struct_dummy()
};

if let Some(def) = actual.ty_adt_def() {
if let Some(def) = actual.ty_adt_def() {
if let Some(full_sp) = tcx.hir.span_if_local(def.did) {
let def_sp = tcx.sess.codemap().def_span(full_sp);
err.span_label(def_sp, format!("{} `{}` not found {}",
Expand Down Expand Up @@ -368,7 +380,22 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
if !static_sources.is_empty() {
err.note("found the following associated functions; to be used as methods, \
functions must have a `self` parameter");
err.help(&format!("try with `{}::{}`", self.ty_to_string(actual), item_name));
err.span_label(span, "this is an associated function, not a method");
}
if static_sources.len() == 1 {
if let Some(expr) = rcvr_expr {
err.span_suggestion(expr.span.to(span),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is only the single source case a suggestion?

"use associated function syntax instead",
format!("{}::{}",
self.ty_to_string(actual),
item_name));
} else {
err.help(&format!("try with `{}::{}`",
self.ty_to_string(actual), item_name));
}

report_candidates(&mut err, static_sources);
} else if static_sources.len() > 1 {

report_candidates(&mut err, static_sources);
}
Expand Down Expand Up @@ -468,9 +495,14 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
} else {
let limit = if candidates.len() == 5 { 5 } else { 4 };
for (i, trait_did) in candidates.iter().take(limit).enumerate() {
msg.push_str(&format!("\ncandidate #{}: `use {};`",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These should probably become a real suggestion, in which case you don't need manual limiting anymore, because the renderer takes care of that

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The suggestions for inserting use statements do that already

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestions currently do not preserve their position in the output, they always come at then end. I need to change that for the first requested fix.

i + 1,
self.tcx.item_path_str(*trait_did)));
if candidates.len() > 1 {
msg.push_str(&format!("\ncandidate #{}: `use {};`",
i + 1,
self.tcx.item_path_str(*trait_did)));
} else {
msg.push_str(&format!("\n`use {};`",
self.tcx.item_path_str(*trait_did)));
}
}
if candidates.len() > limit {
msg.push_str(&format!("\nand {} others", candidates.len() - limit));
Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/hygiene/no_implicit_prelude.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ LL | ().clone() //~ ERROR no method named `clone` found
|
= help: items from traits can only be used if the trait is in scope
= note: the following trait is implemented but not in scope, perhaps add a `use` for it:
candidate #1: `use std::clone::Clone;`
`use std::clone::Clone;`

error: aborting due to 3 previous errors

Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/hygiene/trait_items.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ LL | pub macro m() { ().f() } //~ ERROR no method named `f` found for type `
|
= help: items from traits can only be used if the trait is in scope
= note: the following trait is implemented but not in scope, perhaps add a `use` for it:
candidate #1: `use foo::T;`
`use foo::T;`

error: aborting due to previous error

Expand Down
16 changes: 8 additions & 8 deletions src/test/ui/span/issue-7575.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,9 @@ error[E0599]: no method named `f9` found for type `usize` in the current scope
--> $DIR/issue-7575.rs:74:18
|
LL | u.f8(42) + u.f9(342) + m.fff(42)
| ^^
| ^^ this is an associated function, not a method
|
= note: found the following associated functions; to be used as methods, functions must have a `self` parameter
= help: try with `usize::f9`
note: candidate #1 is defined in the trait `CtxtFn`
--> $DIR/issue-7575.rs:16:5
|
Expand Down Expand Up @@ -37,11 +36,13 @@ LL | struct Myisize(isize);
| ---------------------- method `fff` not found for this
...
LL | u.f8(42) + u.f9(342) + m.fff(42)
| ^^^
| --^^^
| | |
| | this is an associated function, not a method
| help: use associated function syntax instead: `Myisize::fff`
|
= note: found the following associated functions; to be used as methods, functions must have a `self` parameter
= help: try with `Myisize::fff`
note: candidate #1 is defined in an impl for the type `Myisize`
note: the candidate is defined in an impl for the type `Myisize`
--> $DIR/issue-7575.rs:51:5
|
LL | fn fff(i: isize) -> isize {
Expand All @@ -51,11 +52,10 @@ error[E0599]: no method named `is_str` found for type `T` in the current scope
--> $DIR/issue-7575.rs:82:7
|
LL | t.is_str()
| ^^^^^^
| ^^^^^^ this is an associated function, not a method
|
= note: found the following associated functions; to be used as methods, functions must have a `self` parameter
= help: try with `T::is_str`
note: candidate #1 is defined in the trait `ManyImplTrait`
note: the candidate is defined in the trait `ManyImplTrait`
--> $DIR/issue-7575.rs:57:5
|
LL | fn is_str() -> bool {
Expand Down