Auto merge of #118911 - Young-Flash:fix_issue_118819, r=fmease
fix: correct the args for `disambiguate the associated function` diagnostic This is somehow silimar to https://github.com/rust-lang/rust/pull/118502, we shouldn't take receiver as first arg all the cases. close https://github.com/rust-lang/rust/issues/118819
This commit is contained in:
commit
3cdd004e55
@ -3306,6 +3306,7 @@ fn print_disambiguation_help<'tcx>(
|
||||
span: Span,
|
||||
item: ty::AssocItem,
|
||||
) -> Option<String> {
|
||||
let trait_impl_type = trait_ref.self_ty().peel_refs();
|
||||
let trait_ref = if item.fn_has_self_parameter {
|
||||
trait_ref.print_only_trait_name().to_string()
|
||||
} else {
|
||||
@ -3318,27 +3319,34 @@ fn print_disambiguation_help<'tcx>(
|
||||
{
|
||||
let def_kind_descr = tcx.def_kind_descr(item.kind.as_def_kind(), item.def_id);
|
||||
let item_name = item.ident(tcx);
|
||||
let rcvr_ref = tcx
|
||||
.fn_sig(item.def_id)
|
||||
.skip_binder()
|
||||
.skip_binder()
|
||||
.inputs()
|
||||
.get(0)
|
||||
.and_then(|ty| ty.ref_mutability())
|
||||
.map_or("", |mutbl| mutbl.ref_prefix_str());
|
||||
let args = format!(
|
||||
"({}{})",
|
||||
rcvr_ref,
|
||||
std::iter::once(receiver)
|
||||
.chain(args.iter())
|
||||
.map(|arg| tcx
|
||||
.sess
|
||||
.source_map()
|
||||
.span_to_snippet(arg.span)
|
||||
.unwrap_or_else(|_| { "_".to_owned() }))
|
||||
.collect::<Vec<_>>()
|
||||
.join(", "),
|
||||
let first_input =
|
||||
tcx.fn_sig(item.def_id).instantiate_identity().skip_binder().inputs().get(0);
|
||||
let (first_arg_type, rcvr_ref) = (
|
||||
first_input.map(|first| first.peel_refs()),
|
||||
first_input
|
||||
.and_then(|ty| ty.ref_mutability())
|
||||
.map_or("", |mutbl| mutbl.ref_prefix_str()),
|
||||
);
|
||||
|
||||
// If the type of first arg of this assoc function is `Self` or current trait impl type or `arbitrary_self_types`, we need to take the receiver as args. Otherwise, we don't.
|
||||
let args = if let Some(first_arg_type) = first_arg_type
|
||||
&& (first_arg_type == tcx.types.self_param
|
||||
|| first_arg_type == trait_impl_type
|
||||
|| item.fn_has_self_parameter)
|
||||
{
|
||||
Some(receiver)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
.into_iter()
|
||||
.chain(args)
|
||||
.map(|arg| {
|
||||
tcx.sess.source_map().span_to_snippet(arg.span).unwrap_or_else(|_| "_".to_owned())
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
.join(", ");
|
||||
|
||||
let args = format!("({}{})", rcvr_ref, args);
|
||||
err.span_suggestion_verbose(
|
||||
span,
|
||||
format!(
|
||||
|
@ -0,0 +1,49 @@
|
||||
struct A {}
|
||||
|
||||
fn main() {
|
||||
let _a = A {};
|
||||
_a.new(1);
|
||||
//~^ ERROR no method named `new` found for struct `A` in the current scope
|
||||
}
|
||||
|
||||
trait M {
|
||||
fn new(_a: i32);
|
||||
}
|
||||
impl M for A {
|
||||
fn new(_a: i32) {}
|
||||
}
|
||||
|
||||
trait N {
|
||||
fn new(_a: Self, _b: i32);
|
||||
}
|
||||
impl N for A {
|
||||
fn new(_a: Self, _b: i32) {}
|
||||
}
|
||||
|
||||
trait O {
|
||||
fn new(_a: Self, _b: i32);
|
||||
}
|
||||
impl O for A {
|
||||
fn new(_a: A, _b: i32) {}
|
||||
}
|
||||
|
||||
struct S;
|
||||
|
||||
trait TraitA {
|
||||
fn f(self);
|
||||
}
|
||||
trait TraitB {
|
||||
fn f(self);
|
||||
}
|
||||
|
||||
impl<T> TraitA for T {
|
||||
fn f(self) {}
|
||||
}
|
||||
impl<T> TraitB for T {
|
||||
fn f(self) {}
|
||||
}
|
||||
|
||||
fn test() {
|
||||
S.f();
|
||||
//~^ multiple applicable items in scope
|
||||
}
|
@ -0,0 +1,67 @@
|
||||
error[E0599]: no method named `new` found for struct `A` in the current scope
|
||||
--> $DIR/disambiguate-associated-function-first-arg.rs:5:8
|
||||
|
|
||||
LL | struct A {}
|
||||
| -------- method `new` not found for this struct
|
||||
...
|
||||
LL | _a.new(1);
|
||||
| ^^^ 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: candidate #1 is defined in the trait `M`
|
||||
--> $DIR/disambiguate-associated-function-first-arg.rs:10:5
|
||||
|
|
||||
LL | fn new(_a: i32);
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
note: candidate #2 is defined in the trait `N`
|
||||
--> $DIR/disambiguate-associated-function-first-arg.rs:17:5
|
||||
|
|
||||
LL | fn new(_a: Self, _b: i32);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
note: candidate #3 is defined in the trait `O`
|
||||
--> $DIR/disambiguate-associated-function-first-arg.rs:24:5
|
||||
|
|
||||
LL | fn new(_a: Self, _b: i32);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
help: disambiguate the associated function for candidate #1
|
||||
|
|
||||
LL | <A as M>::new(1);
|
||||
| ~~~~~~~~~~~~~~~~
|
||||
help: disambiguate the associated function for candidate #2
|
||||
|
|
||||
LL | <A as N>::new(_a, 1);
|
||||
| ~~~~~~~~~~~~~~~~~~~~
|
||||
help: disambiguate the associated function for candidate #3
|
||||
|
|
||||
LL | <A as O>::new(_a, 1);
|
||||
| ~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
error[E0034]: multiple applicable items in scope
|
||||
--> $DIR/disambiguate-associated-function-first-arg.rs:47:7
|
||||
|
|
||||
LL | S.f();
|
||||
| ^ multiple `f` found
|
||||
|
|
||||
note: candidate #1 is defined in an impl of the trait `TraitA` for the type `T`
|
||||
--> $DIR/disambiguate-associated-function-first-arg.rs:40:5
|
||||
|
|
||||
LL | fn f(self) {}
|
||||
| ^^^^^^^^^^
|
||||
note: candidate #2 is defined in an impl of the trait `TraitB` for the type `T`
|
||||
--> $DIR/disambiguate-associated-function-first-arg.rs:43:5
|
||||
|
|
||||
LL | fn f(self) {}
|
||||
| ^^^^^^^^^^
|
||||
help: disambiguate the method for candidate #1
|
||||
|
|
||||
LL | TraitA::f(S);
|
||||
| ~~~~~~~~~~~~
|
||||
help: disambiguate the method for candidate #2
|
||||
|
|
||||
LL | TraitB::f(S);
|
||||
| ~~~~~~~~~~~~
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0034, E0599.
|
||||
For more information about an error, try `rustc --explain E0034`.
|
@ -20,12 +20,12 @@ LL | fn foo() {}
|
||||
| ^^^^^^^^
|
||||
help: disambiguate the associated function for candidate #1
|
||||
|
|
||||
LL | <Qux as Foo>::foo(Qux);
|
||||
| ~~~~~~~~~~~~~~~~~~~~~~
|
||||
LL | <Qux as Foo>::foo();
|
||||
| ~~~~~~~~~~~~~~~~~~~
|
||||
help: disambiguate the associated function for candidate #2
|
||||
|
|
||||
LL | <Qux as FooBar>::foo(Qux);
|
||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
LL | <Qux as FooBar>::foo();
|
||||
| ~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user