From a85517894408e4388a37f2db74768ad91c97d43b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 13 Oct 2023 23:31:35 +0000 Subject: [PATCH] Properly account for self ty in method disambiguation suggestion Fix #116703. --- .../rustc_hir_typeck/src/method/suggest.rs | 9 ++++-- .../disambiguate-multiple-blanket-impl.rs | 27 ++++++++++++++++++ .../disambiguate-multiple-blanket-impl.stderr | 28 +++++++++++++++++++ .../ui/methods/disambiguate-multiple-impl.rs | 26 +++++++++++++++++ .../methods/disambiguate-multiple-impl.stderr | 28 +++++++++++++++++++ 5 files changed, 115 insertions(+), 3 deletions(-) create mode 100644 tests/ui/methods/disambiguate-multiple-blanket-impl.rs create mode 100644 tests/ui/methods/disambiguate-multiple-blanket-impl.stderr create mode 100644 tests/ui/methods/disambiguate-multiple-impl.rs create mode 100644 tests/ui/methods/disambiguate-multiple-impl.stderr diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 8ea0280c5e9be..56d7b94d493ab 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -1322,7 +1322,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let path = self.tcx.def_path_str(trait_ref.skip_binder().def_id); let ty = match item.kind { - ty::AssocKind::Const | ty::AssocKind::Type => rcvr_ty, + ty::AssocKind::Const | ty::AssocKind::Type => impl_ty, ty::AssocKind::Fn => self .tcx .fn_sig(item.def_id) @@ -1340,6 +1340,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { err, path, ty, + impl_ty, item.kind, self.tcx.def_kind_descr(item.kind.as_def_kind(), item.def_id), sugg_span, @@ -1376,6 +1377,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { err, path, rcvr_ty, + rcvr_ty, item.kind, self.tcx.def_kind_descr(item.kind.as_def_kind(), item.def_id), sugg_span, @@ -3146,6 +3148,7 @@ fn print_disambiguation_help<'tcx>( err: &mut Diagnostic, trait_name: String, rcvr_ty: Ty<'_>, + self_ty: Ty<'_>, kind: ty::AssocKind, def_kind_descr: &'static str, span: Span, @@ -3172,13 +3175,13 @@ fn print_disambiguation_help<'tcx>( .join(", "), ); let trait_name = if !fn_has_self_parameter { - format!("<{rcvr_ty} as {trait_name}>") + format!("<{self_ty} as {trait_name}>") } else { trait_name }; (span, format!("{trait_name}::{item_name}{args}")) } else { - (span.with_hi(item_name.span.lo()), format!("<{rcvr_ty} as {trait_name}>::")) + (span.with_hi(item_name.span.lo()), format!("<{self_ty} as {trait_name}>::")) }; err.span_suggestion_verbose( span, diff --git a/tests/ui/methods/disambiguate-multiple-blanket-impl.rs b/tests/ui/methods/disambiguate-multiple-blanket-impl.rs new file mode 100644 index 0000000000000..39ac3389aab88 --- /dev/null +++ b/tests/ui/methods/disambiguate-multiple-blanket-impl.rs @@ -0,0 +1,27 @@ +trait A { + fn foo(&self); +} + +trait B { + fn foo(&self); +} + +#[derive(Debug)] +struct S; + +impl A for T { + fn foo(&self) {} //~ NOTE candidate #1 +} + +impl B for T { + fn foo(&self) {} //~ NOTE candidate #2 +} + +fn main() { + let s = S; + S::foo(&s); //~ ERROR multiple applicable items in scope + //~^ NOTE multiple `foo` found + //~| HELP disambiguate + //~| HELP disambiguate +} + diff --git a/tests/ui/methods/disambiguate-multiple-blanket-impl.stderr b/tests/ui/methods/disambiguate-multiple-blanket-impl.stderr new file mode 100644 index 0000000000000..dd0af051bb926 --- /dev/null +++ b/tests/ui/methods/disambiguate-multiple-blanket-impl.stderr @@ -0,0 +1,28 @@ +error[E0034]: multiple applicable items in scope + --> $DIR/disambiguate-multiple-blanket-impl.rs:22:8 + | +LL | S::foo(&s); + | ^^^ multiple `foo` found + | +note: candidate #1 is defined in an impl of the trait `A` for the type `T` + --> $DIR/disambiguate-multiple-blanket-impl.rs:13:5 + | +LL | fn foo(&self) {} + | ^^^^^^^^^^^^^ +note: candidate #2 is defined in an impl of the trait `B` for the type `T` + --> $DIR/disambiguate-multiple-blanket-impl.rs:17:5 + | +LL | fn foo(&self) {} + | ^^^^^^^^^^^^^ +help: disambiguate the method for candidate #1 + | +LL | ::foo(&s); + | ~~~~~~~~~~ +help: disambiguate the method for candidate #2 + | +LL | ::foo(&s); + | ~~~~~~~~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0034`. diff --git a/tests/ui/methods/disambiguate-multiple-impl.rs b/tests/ui/methods/disambiguate-multiple-impl.rs new file mode 100644 index 0000000000000..fa9942c745ade --- /dev/null +++ b/tests/ui/methods/disambiguate-multiple-impl.rs @@ -0,0 +1,26 @@ +trait A { + fn foo(&self); +} + +trait B { + fn foo(&self); +} + +struct S; + +impl A for S { + fn foo(&self) {} //~ NOTE candidate #1 +} + +impl B for S { + fn foo(&self) {} //~ NOTE candidate #2 +} + +fn main() { + let s = S; + S::foo(&s); //~ ERROR multiple applicable items in scope + //~^ NOTE multiple `foo` found + //~| HELP disambiguate + //~| HELP disambiguate +} + diff --git a/tests/ui/methods/disambiguate-multiple-impl.stderr b/tests/ui/methods/disambiguate-multiple-impl.stderr new file mode 100644 index 0000000000000..b9fd10dba8d79 --- /dev/null +++ b/tests/ui/methods/disambiguate-multiple-impl.stderr @@ -0,0 +1,28 @@ +error[E0034]: multiple applicable items in scope + --> $DIR/disambiguate-multiple-impl.rs:21:8 + | +LL | S::foo(&s); + | ^^^ multiple `foo` found + | +note: candidate #1 is defined in an impl of the trait `A` for the type `S` + --> $DIR/disambiguate-multiple-impl.rs:12:5 + | +LL | fn foo(&self) {} + | ^^^^^^^^^^^^^ +note: candidate #2 is defined in an impl of the trait `B` for the type `S` + --> $DIR/disambiguate-multiple-impl.rs:16:5 + | +LL | fn foo(&self) {} + | ^^^^^^^^^^^^^ +help: disambiguate the method for candidate #1 + | +LL | ::foo(&s); + | ~~~~~~~~~~ +help: disambiguate the method for candidate #2 + | +LL | ::foo(&s); + | ~~~~~~~~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0034`.