Properly account for self ty in method disambiguation suggestion

Fix #116703.
This commit is contained in:
Esteban Küber 2023-10-13 23:31:35 +00:00
parent 93e62a260f
commit 5cc9216ff3
5 changed files with 115 additions and 3 deletions

View File

@ -1322,7 +1322,7 @@ fn note_candidates_on_method_error(
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 @@ fn note_candidates_on_method_error(
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 @@ fn note_candidates_on_method_error(
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,

View File

@ -0,0 +1,27 @@
trait A {
fn foo(&self);
}
trait B {
fn foo(&self);
}
#[derive(Debug)]
struct S;
impl<T: std::fmt::Debug> A for T {
fn foo(&self) {} //~ NOTE candidate #1
}
impl<T: std::fmt::Debug> 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
}

View File

@ -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 | <T as A>::foo(&s);
| ~~~~~~~~~~
help: disambiguate the method for candidate #2
|
LL | <T as B>::foo(&s);
| ~~~~~~~~~~
error: aborting due to previous error
For more information about this error, try `rustc --explain E0034`.

View File

@ -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
}

View File

@ -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 | <S as A>::foo(&s);
| ~~~~~~~~~~
help: disambiguate the method for candidate #2
|
LL | <S as B>::foo(&s);
| ~~~~~~~~~~
error: aborting due to previous error
For more information about this error, try `rustc --explain E0034`.