Rollup merge of #51135 - estebank:sugg-7575, r=oli-obk
Tweak output on E0599 for assoc fn used as method - Use suggestion instead of `help` when possible - Add primary span label - Remove incorrect `help` suggestion using incorrect syntax - Do not refer to only one possible candidate as `candidate #1`, refer to it as `the candidate`
This commit is contained in:
commit
361a82ca7b
4 changed files with 57 additions and 25 deletions
|
@ -119,11 +119,16 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let note_str = format!("candidate #{} is defined in an impl{} \
|
let note_str = if sources.len() > 1 {
|
||||||
for the type `{}`",
|
format!("candidate #{} is defined in an impl{} for the type `{}`",
|
||||||
idx + 1,
|
idx + 1,
|
||||||
insertion,
|
insertion,
|
||||||
impl_ty);
|
impl_ty)
|
||||||
|
} else {
|
||||||
|
format!("the candidate is defined in an impl{} for the type `{}`",
|
||||||
|
insertion,
|
||||||
|
impl_ty)
|
||||||
|
};
|
||||||
if let Some(note_span) = note_span {
|
if let Some(note_span) = note_span {
|
||||||
// We have a span pointing to the method. Show note with snippet.
|
// We have a span pointing to the method. Show note with snippet.
|
||||||
err.span_note(self.tcx.sess.codemap().def_span(note_span), ¬e_str);
|
err.span_note(self.tcx.sess.codemap().def_span(note_span), ¬e_str);
|
||||||
|
@ -137,11 +142,18 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let item_span = self.tcx.sess.codemap()
|
let item_span = self.tcx.sess.codemap()
|
||||||
.def_span(self.tcx.def_span(item.def_id));
|
.def_span(self.tcx.def_span(item.def_id));
|
||||||
span_note!(err,
|
if sources.len() > 1 {
|
||||||
item_span,
|
span_note!(err,
|
||||||
"candidate #{} is defined in the trait `{}`",
|
item_span,
|
||||||
idx + 1,
|
"candidate #{} is defined in the trait `{}`",
|
||||||
self.tcx.item_path_str(trait_did));
|
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 `{}::{}({}{})` \
|
err.help(&format!("to disambiguate the method call, write `{}::{}({}{})` \
|
||||||
instead",
|
instead",
|
||||||
self.tcx.item_path_str(trait_did),
|
self.tcx.item_path_str(trait_did),
|
||||||
|
@ -285,7 +297,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
tcx.sess.diagnostic().struct_dummy()
|
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) {
|
if let Some(full_sp) = tcx.hir.span_if_local(def.did) {
|
||||||
let def_sp = tcx.sess.codemap().def_span(full_sp);
|
let def_sp = tcx.sess.codemap().def_span(full_sp);
|
||||||
err.span_label(def_sp, format!("{} `{}` not found {}",
|
err.span_label(def_sp, format!("{} `{}` not found {}",
|
||||||
|
@ -368,7 +380,22 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
if !static_sources.is_empty() {
|
if !static_sources.is_empty() {
|
||||||
err.note("found the following associated functions; to be used as methods, \
|
err.note("found the following associated functions; to be used as methods, \
|
||||||
functions must have a `self` parameter");
|
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),
|
||||||
|
"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);
|
report_candidates(&mut err, static_sources);
|
||||||
}
|
}
|
||||||
|
@ -468,9 +495,14 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
} else {
|
} else {
|
||||||
let limit = if candidates.len() == 5 { 5 } else { 4 };
|
let limit = if candidates.len() == 5 { 5 } else { 4 };
|
||||||
for (i, trait_did) in candidates.iter().take(limit).enumerate() {
|
for (i, trait_did) in candidates.iter().take(limit).enumerate() {
|
||||||
msg.push_str(&format!("\ncandidate #{}: `use {};`",
|
if candidates.len() > 1 {
|
||||||
i + 1,
|
msg.push_str(&format!("\ncandidate #{}: `use {};`",
|
||||||
self.tcx.item_path_str(*trait_did)));
|
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 {
|
if candidates.len() > limit {
|
||||||
msg.push_str(&format!("\nand {} others", candidates.len() - limit));
|
msg.push_str(&format!("\nand {} others", candidates.len() - limit));
|
||||||
|
|
|
@ -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
|
= 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:
|
= 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
|
error: aborting due to 3 previous errors
|
||||||
|
|
||||||
|
|
|
@ -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
|
= 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:
|
= 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
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
|
|
@ -2,10 +2,9 @@ error[E0599]: no method named `f9` found for type `usize` in the current scope
|
||||||
--> $DIR/issue-7575.rs:74:18
|
--> $DIR/issue-7575.rs:74:18
|
||||||
|
|
|
|
||||||
LL | u.f8(42) + u.f9(342) + m.fff(42)
|
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
|
= 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`
|
note: candidate #1 is defined in the trait `CtxtFn`
|
||||||
--> $DIR/issue-7575.rs:16:5
|
--> $DIR/issue-7575.rs:16:5
|
||||||
|
|
|
|
||||||
|
@ -37,11 +36,13 @@ LL | struct Myisize(isize);
|
||||||
| ---------------------- method `fff` not found for this
|
| ---------------------- method `fff` not found for this
|
||||||
...
|
...
|
||||||
LL | u.f8(42) + u.f9(342) + m.fff(42)
|
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
|
= note: found the following associated functions; to be used as methods, functions must have a `self` parameter
|
||||||
= help: try with `Myisize::fff`
|
note: the candidate is defined in an impl for the type `Myisize`
|
||||||
note: candidate #1 is defined in an impl for the type `Myisize`
|
|
||||||
--> $DIR/issue-7575.rs:51:5
|
--> $DIR/issue-7575.rs:51:5
|
||||||
|
|
|
|
||||||
LL | fn fff(i: isize) -> isize {
|
LL | fn fff(i: isize) -> isize {
|
||||||
|
@ -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
|
--> $DIR/issue-7575.rs:82:7
|
||||||
|
|
|
|
||||||
LL | t.is_str()
|
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
|
= note: found the following associated functions; to be used as methods, functions must have a `self` parameter
|
||||||
= help: try with `T::is_str`
|
note: the candidate is defined in the trait `ManyImplTrait`
|
||||||
note: candidate #1 is defined in the trait `ManyImplTrait`
|
|
||||||
--> $DIR/issue-7575.rs:57:5
|
--> $DIR/issue-7575.rs:57:5
|
||||||
|
|
|
|
||||||
LL | fn is_str() -> bool {
|
LL | fn is_str() -> bool {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue