Rollup merge of #119957 - Young-Flash:fix, r=fmease

fix: correct suggestion arg for impl trait

follow up https://github.com/rust-lang/rust/pull/118502, close https://github.com/rust-lang/rust/issues/119775
This commit is contained in:
Matthias Krüger 2024-01-27 10:48:47 +01:00 committed by GitHub
commit c6f0a5cfe3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 137 additions and 9 deletions

View File

@ -1601,23 +1601,33 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.ty_to_value_string(rcvr_ty.peel_refs())
};
if let SelfSource::MethodCall(_) = source {
let first_arg = if let Some(CandidateSource::Impl(impl_did)) = static_candidates.get(0)
&& let Some(assoc) = self.associated_value(*impl_did, item_name)
&& assoc.kind == ty::AssocKind::Fn
{
let first_arg = static_candidates.get(0).and_then(|candidate_source| {
let (assoc_did, self_ty) = match candidate_source {
CandidateSource::Impl(impl_did) => {
(*impl_did, self.tcx.type_of(*impl_did).instantiate_identity())
}
CandidateSource::Trait(trait_did) => (*trait_did, rcvr_ty),
};
let assoc = self.associated_value(assoc_did, item_name)?;
if assoc.kind != ty::AssocKind::Fn {
return None;
}
// for CandidateSource::Impl, `Self` will be instantiated to a concrete type
// but for CandidateSource::Trait, `Self` is still `Self`
let sig = self.tcx.fn_sig(assoc.def_id).instantiate_identity();
sig.inputs().skip_binder().get(0).and_then(|first| {
let impl_ty = self.tcx.type_of(*impl_did).instantiate_identity();
// if the type of first arg is the same as the current impl type, we should take the first arg into assoc function
if first.peel_refs() == impl_ty {
let first_ty = first.peel_refs();
if first_ty == self_ty || first_ty == self.tcx.types.self_param {
Some(first.ref_mutability().map_or("", |mutbl| mutbl.ref_prefix_str()))
} else {
None
}
})
} else {
None
};
});
let mut applicability = Applicability::MachineApplicable;
let args = if let SelfSource::MethodCall(receiver) = source
&& let Some(args) = args

View File

@ -0,0 +1,29 @@
// run-rustfix
struct A {
}
trait M {
fn foo(_a: Self);
fn bar(_a: Self);
fn baz(_a: i32);
}
impl M for A {
fn foo(_a: Self) {}
fn bar(_a: A) {}
fn baz(_a: i32) {}
}
fn main() {
let _a = A {};
A::foo(_a);
//~^ ERROR no method named `foo` found
A::baz(0);
//~^ ERROR no method named `baz` found
let _b = A {};
A::bar(_b);
//~^ ERROR no method named `bar` found
}

View File

@ -0,0 +1,29 @@
// run-rustfix
struct A {
}
trait M {
fn foo(_a: Self);
fn bar(_a: Self);
fn baz(_a: i32);
}
impl M for A {
fn foo(_a: Self) {}
fn bar(_a: A) {}
fn baz(_a: i32) {}
}
fn main() {
let _a = A {};
_a.foo();
//~^ ERROR no method named `foo` found
_a.baz(0);
//~^ ERROR no method named `baz` found
let _b = A {};
_b.bar();
//~^ ERROR no method named `bar` found
}

View File

@ -0,0 +1,60 @@
error[E0599]: no method named `foo` found for struct `A` in the current scope
--> $DIR/suggest-assoc-fn-call-for-impl-trait.rs:21:8
|
LL | struct A {
| -------- method `foo` not found for this struct
...
LL | _a.foo();
| ---^^^--
| | |
| | this is an associated function, not a method
| help: use associated function syntax instead: `A::foo(_a)`
|
= note: found the following associated functions; to be used as methods, functions must have a `self` parameter
note: the candidate is defined in the trait `M`
--> $DIR/suggest-assoc-fn-call-for-impl-trait.rs:8:5
|
LL | fn foo(_a: Self);
| ^^^^^^^^^^^^^^^^^
error[E0599]: no method named `baz` found for struct `A` in the current scope
--> $DIR/suggest-assoc-fn-call-for-impl-trait.rs:23:8
|
LL | struct A {
| -------- method `baz` not found for this struct
...
LL | _a.baz(0);
| ---^^^---
| | |
| | this is an associated function, not a method
| help: use associated function syntax instead: `A::baz(0)`
|
= note: found the following associated functions; to be used as methods, functions must have a `self` parameter
note: the candidate is defined in the trait `M`
--> $DIR/suggest-assoc-fn-call-for-impl-trait.rs:10:5
|
LL | fn baz(_a: i32);
| ^^^^^^^^^^^^^^^^
error[E0599]: no method named `bar` found for struct `A` in the current scope
--> $DIR/suggest-assoc-fn-call-for-impl-trait.rs:27:8
|
LL | struct A {
| -------- method `bar` not found for this struct
...
LL | _b.bar();
| ---^^^--
| | |
| | this is an associated function, not a method
| help: use associated function syntax instead: `A::bar(_b)`
|
= note: found the following associated functions; to be used as methods, functions must have a `self` parameter
note: the candidate is defined in the trait `M`
--> $DIR/suggest-assoc-fn-call-for-impl-trait.rs:9:5
|
LL | fn bar(_a: Self);
| ^^^^^^^^^^^^^^^^^
error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0599`.