diff options
| author | Matthias Krüger <matthias.krueger@famsik.de> | 2024-01-27 10:48:47 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-01-27 10:48:47 +0100 |
| commit | c6f0a5cfe376b365523bd080c9886301c7e973e4 (patch) | |
| tree | 85eb5b9824f07b6bce662c69eb9b1d896ee350a1 | |
| parent | b35a3f89bd4cb5e9e7cc5b62de0e1334f04a6c5b (diff) | |
| parent | 8b3a681a34ed183510af5365e9fab17cca06baf7 (diff) | |
| download | rust-c6f0a5cfe376b365523bd080c9886301c7e973e4.tar.gz rust-c6f0a5cfe376b365523bd080c9886301c7e973e4.zip | |
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
4 files changed, 137 insertions, 9 deletions
diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 0b8a25eedaf..47f6e3f934e 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -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 diff --git a/tests/ui/suggestions/suggest-assoc-fn-call-for-impl-trait.fixed b/tests/ui/suggestions/suggest-assoc-fn-call-for-impl-trait.fixed new file mode 100644 index 00000000000..86ac07a93a3 --- /dev/null +++ b/tests/ui/suggestions/suggest-assoc-fn-call-for-impl-trait.fixed @@ -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 +} diff --git a/tests/ui/suggestions/suggest-assoc-fn-call-for-impl-trait.rs b/tests/ui/suggestions/suggest-assoc-fn-call-for-impl-trait.rs new file mode 100644 index 00000000000..9a57ffb7740 --- /dev/null +++ b/tests/ui/suggestions/suggest-assoc-fn-call-for-impl-trait.rs @@ -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 +} diff --git a/tests/ui/suggestions/suggest-assoc-fn-call-for-impl-trait.stderr b/tests/ui/suggestions/suggest-assoc-fn-call-for-impl-trait.stderr new file mode 100644 index 00000000000..0df2b08d3be --- /dev/null +++ b/tests/ui/suggestions/suggest-assoc-fn-call-for-impl-trait.stderr @@ -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`. |
