Skip to content

Commit 3cdd004

Browse files
committed
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 #118502, we shouldn't take receiver as first arg all the cases. close #118819
2 parents 29abb90 + 9e9353c commit 3cdd004

File tree

4 files changed

+148
-24
lines changed

4 files changed

+148
-24
lines changed

compiler/rustc_hir_typeck/src/method/suggest.rs

+28-20
Original file line numberDiff line numberDiff line change
@@ -3306,6 +3306,7 @@ fn print_disambiguation_help<'tcx>(
33063306
span: Span,
33073307
item: ty::AssocItem,
33083308
) -> Option<String> {
3309+
let trait_impl_type = trait_ref.self_ty().peel_refs();
33093310
let trait_ref = if item.fn_has_self_parameter {
33103311
trait_ref.print_only_trait_name().to_string()
33113312
} else {
@@ -3318,27 +3319,34 @@ fn print_disambiguation_help<'tcx>(
33183319
{
33193320
let def_kind_descr = tcx.def_kind_descr(item.kind.as_def_kind(), item.def_id);
33203321
let item_name = item.ident(tcx);
3321-
let rcvr_ref = tcx
3322-
.fn_sig(item.def_id)
3323-
.skip_binder()
3324-
.skip_binder()
3325-
.inputs()
3326-
.get(0)
3327-
.and_then(|ty| ty.ref_mutability())
3328-
.map_or("", |mutbl| mutbl.ref_prefix_str());
3329-
let args = format!(
3330-
"({}{})",
3331-
rcvr_ref,
3332-
std::iter::once(receiver)
3333-
.chain(args.iter())
3334-
.map(|arg| tcx
3335-
.sess
3336-
.source_map()
3337-
.span_to_snippet(arg.span)
3338-
.unwrap_or_else(|_| { "_".to_owned() }))
3339-
.collect::<Vec<_>>()
3340-
.join(", "),
3322+
let first_input =
3323+
tcx.fn_sig(item.def_id).instantiate_identity().skip_binder().inputs().get(0);
3324+
let (first_arg_type, rcvr_ref) = (
3325+
first_input.map(|first| first.peel_refs()),
3326+
first_input
3327+
.and_then(|ty| ty.ref_mutability())
3328+
.map_or("", |mutbl| mutbl.ref_prefix_str()),
33413329
);
3330+
3331+
// 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.
3332+
let args = if let Some(first_arg_type) = first_arg_type
3333+
&& (first_arg_type == tcx.types.self_param
3334+
|| first_arg_type == trait_impl_type
3335+
|| item.fn_has_self_parameter)
3336+
{
3337+
Some(receiver)
3338+
} else {
3339+
None
3340+
}
3341+
.into_iter()
3342+
.chain(args)
3343+
.map(|arg| {
3344+
tcx.sess.source_map().span_to_snippet(arg.span).unwrap_or_else(|_| "_".to_owned())
3345+
})
3346+
.collect::<Vec<_>>()
3347+
.join(", ");
3348+
3349+
let args = format!("({}{})", rcvr_ref, args);
33423350
err.span_suggestion_verbose(
33433351
span,
33443352
format!(
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
struct A {}
2+
3+
fn main() {
4+
let _a = A {};
5+
_a.new(1);
6+
//~^ ERROR no method named `new` found for struct `A` in the current scope
7+
}
8+
9+
trait M {
10+
fn new(_a: i32);
11+
}
12+
impl M for A {
13+
fn new(_a: i32) {}
14+
}
15+
16+
trait N {
17+
fn new(_a: Self, _b: i32);
18+
}
19+
impl N for A {
20+
fn new(_a: Self, _b: i32) {}
21+
}
22+
23+
trait O {
24+
fn new(_a: Self, _b: i32);
25+
}
26+
impl O for A {
27+
fn new(_a: A, _b: i32) {}
28+
}
29+
30+
struct S;
31+
32+
trait TraitA {
33+
fn f(self);
34+
}
35+
trait TraitB {
36+
fn f(self);
37+
}
38+
39+
impl<T> TraitA for T {
40+
fn f(self) {}
41+
}
42+
impl<T> TraitB for T {
43+
fn f(self) {}
44+
}
45+
46+
fn test() {
47+
S.f();
48+
//~^ multiple applicable items in scope
49+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
error[E0599]: no method named `new` found for struct `A` in the current scope
2+
--> $DIR/disambiguate-associated-function-first-arg.rs:5:8
3+
|
4+
LL | struct A {}
5+
| -------- method `new` not found for this struct
6+
...
7+
LL | _a.new(1);
8+
| ^^^ this is an associated function, not a method
9+
|
10+
= note: found the following associated functions; to be used as methods, functions must have a `self` parameter
11+
note: candidate #1 is defined in the trait `M`
12+
--> $DIR/disambiguate-associated-function-first-arg.rs:10:5
13+
|
14+
LL | fn new(_a: i32);
15+
| ^^^^^^^^^^^^^^^^
16+
note: candidate #2 is defined in the trait `N`
17+
--> $DIR/disambiguate-associated-function-first-arg.rs:17:5
18+
|
19+
LL | fn new(_a: Self, _b: i32);
20+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
21+
note: candidate #3 is defined in the trait `O`
22+
--> $DIR/disambiguate-associated-function-first-arg.rs:24:5
23+
|
24+
LL | fn new(_a: Self, _b: i32);
25+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
26+
help: disambiguate the associated function for candidate #1
27+
|
28+
LL | <A as M>::new(1);
29+
| ~~~~~~~~~~~~~~~~
30+
help: disambiguate the associated function for candidate #2
31+
|
32+
LL | <A as N>::new(_a, 1);
33+
| ~~~~~~~~~~~~~~~~~~~~
34+
help: disambiguate the associated function for candidate #3
35+
|
36+
LL | <A as O>::new(_a, 1);
37+
| ~~~~~~~~~~~~~~~~~~~~
38+
39+
error[E0034]: multiple applicable items in scope
40+
--> $DIR/disambiguate-associated-function-first-arg.rs:47:7
41+
|
42+
LL | S.f();
43+
| ^ multiple `f` found
44+
|
45+
note: candidate #1 is defined in an impl of the trait `TraitA` for the type `T`
46+
--> $DIR/disambiguate-associated-function-first-arg.rs:40:5
47+
|
48+
LL | fn f(self) {}
49+
| ^^^^^^^^^^
50+
note: candidate #2 is defined in an impl of the trait `TraitB` for the type `T`
51+
--> $DIR/disambiguate-associated-function-first-arg.rs:43:5
52+
|
53+
LL | fn f(self) {}
54+
| ^^^^^^^^^^
55+
help: disambiguate the method for candidate #1
56+
|
57+
LL | TraitA::f(S);
58+
| ~~~~~~~~~~~~
59+
help: disambiguate the method for candidate #2
60+
|
61+
LL | TraitB::f(S);
62+
| ~~~~~~~~~~~~
63+
64+
error: aborting due to 2 previous errors
65+
66+
Some errors have detailed explanations: E0034, E0599.
67+
For more information about an error, try `rustc --explain E0034`.

tests/ui/methods/method-ambiguity-no-rcvr.stderr

+4-4
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,12 @@ LL | fn foo() {}
2020
| ^^^^^^^^
2121
help: disambiguate the associated function for candidate #1
2222
|
23-
LL | <Qux as Foo>::foo(Qux);
24-
| ~~~~~~~~~~~~~~~~~~~~~~
23+
LL | <Qux as Foo>::foo();
24+
| ~~~~~~~~~~~~~~~~~~~
2525
help: disambiguate the associated function for candidate #2
2626
|
27-
LL | <Qux as FooBar>::foo(Qux);
28-
| ~~~~~~~~~~~~~~~~~~~~~~~~~
27+
LL | <Qux as FooBar>::foo();
28+
| ~~~~~~~~~~~~~~~~~~~~~~
2929

3030
error: aborting due to 1 previous error
3131

0 commit comments

Comments
 (0)