From a761f3d3c28f06cf07a37400b7b0805cc45cc4c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 16 Oct 2023 01:22:25 +0000 Subject: [PATCH] review comments + more tests --- .../rustc_hir_typeck/src/method/suggest.rs | 17 ++- .../disambiguate-multiple-blanket-impl.rs | 15 +- .../disambiguate-multiple-blanket-impl.stderr | 49 ++++++- .../ui/methods/disambiguate-multiple-impl.rs | 15 +- .../methods/disambiguate-multiple-impl.stderr | 49 ++++++- .../methods/disambiguate-multiple-trait-2.rs | 57 ++++++++ .../disambiguate-multiple-trait-2.stderr | 138 ++++++++++++++++++ .../ui/methods/disambiguate-multiple-trait.rs | 34 +++++ .../disambiguate-multiple-trait.stderr | 67 +++++++++ 9 files changed, 421 insertions(+), 20 deletions(-) create mode 100644 tests/ui/methods/disambiguate-multiple-trait-2.rs create mode 100644 tests/ui/methods/disambiguate-multiple-trait-2.stderr create mode 100644 tests/ui/methods/disambiguate-multiple-trait.rs create mode 100644 tests/ui/methods/disambiguate-multiple-trait.stderr diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 56d7b94d493ab..f3441b313cb59 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -1340,7 +1340,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { err, path, ty, - impl_ty, + Some(impl_ty), item.kind, self.tcx.def_kind_descr(item.kind.as_def_kind(), item.def_id), sugg_span, @@ -1377,7 +1377,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { err, path, rcvr_ty, - rcvr_ty, + None, item.kind, self.tcx.def_kind_descr(item.kind.as_def_kind(), item.def_id), sugg_span, @@ -3148,7 +3148,7 @@ fn print_disambiguation_help<'tcx>( err: &mut Diagnostic, trait_name: String, rcvr_ty: Ty<'_>, - self_ty: Ty<'_>, + impl_self_ty: Option>, kind: ty::AssocKind, def_kind_descr: &'static str, span: Span, @@ -3174,20 +3174,21 @@ fn print_disambiguation_help<'tcx>( .collect::>() .join(", "), ); - let trait_name = if !fn_has_self_parameter { - format!("<{self_ty} as {trait_name}>") + let trait_name = if !fn_has_self_parameter && let Some(impl_self_ty) = impl_self_ty { + format!("<{impl_self_ty} as {trait_name}>") } else { trait_name }; (span, format!("{trait_name}::{item_name}{args}")) + } else if let Some(impl_self_ty) = impl_self_ty { + (span.with_hi(item_name.span.lo()), format!("<{impl_self_ty} as {trait_name}>::")) } else { - (span.with_hi(item_name.span.lo()), format!("<{self_ty} as {trait_name}>::")) + (span.with_hi(item_name.span.lo()), format!("{trait_name}::")) }; err.span_suggestion_verbose( span, format!( - "disambiguate the {} for {}", - def_kind_descr, + "disambiguate the {def_kind_descr} for {}", if let Some(candidate) = candidate { format!("candidate #{candidate}") } else { diff --git a/tests/ui/methods/disambiguate-multiple-blanket-impl.rs b/tests/ui/methods/disambiguate-multiple-blanket-impl.rs index 39ac3389aab88..f8fb8439ddc50 100644 --- a/tests/ui/methods/disambiguate-multiple-blanket-impl.rs +++ b/tests/ui/methods/disambiguate-multiple-blanket-impl.rs @@ -1,8 +1,12 @@ trait A { + type Type; + const CONST: usize; fn foo(&self); } trait B { + type Type; + const CONST: usize; fn foo(&self); } @@ -10,10 +14,14 @@ trait B { struct S; impl A for T { + type Type = (); + const CONST: usize = 1; //~ NOTE candidate #1 fn foo(&self) {} //~ NOTE candidate #1 } impl B for T { + type Type = (); + const CONST: usize = 2; //~ NOTE candidate #2 fn foo(&self) {} //~ NOTE candidate #2 } @@ -23,5 +31,10 @@ fn main() { //~^ NOTE multiple `foo` found //~| HELP disambiguate //~| HELP disambiguate + S::CONST; //~ ERROR multiple applicable items in scope + //~^ NOTE multiple `CONST` found + //~| HELP disambiguate + //~| HELP disambiguate + let _: S::Type; //~ ERROR ambiguous associated type + //~^ HELP use the fully-qualified path } - diff --git a/tests/ui/methods/disambiguate-multiple-blanket-impl.stderr b/tests/ui/methods/disambiguate-multiple-blanket-impl.stderr index dd0af051bb926..5138e7fa2cb05 100644 --- a/tests/ui/methods/disambiguate-multiple-blanket-impl.stderr +++ b/tests/ui/methods/disambiguate-multiple-blanket-impl.stderr @@ -1,16 +1,29 @@ +error[E0223]: ambiguous associated type + --> $DIR/disambiguate-multiple-blanket-impl.rs:38:12 + | +LL | let _: S::Type; + | ^^^^^^^ + | +help: use the fully-qualified path + | +LL | let _: ::Type; + | ~~~~~~~~~~~~~~ +LL | let _: ::Type; + | ~~~~~~~~~~~~~~ + error[E0034]: multiple applicable items in scope - --> $DIR/disambiguate-multiple-blanket-impl.rs:22:8 + --> $DIR/disambiguate-multiple-blanket-impl.rs:30: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 + --> $DIR/disambiguate-multiple-blanket-impl.rs:19: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 + --> $DIR/disambiguate-multiple-blanket-impl.rs:25:5 | LL | fn foo(&self) {} | ^^^^^^^^^^^^^ @@ -23,6 +36,32 @@ help: disambiguate the method for candidate #2 LL | ::foo(&s); | ~~~~~~~~~~ -error: aborting due to previous error +error[E0034]: multiple applicable items in scope + --> $DIR/disambiguate-multiple-blanket-impl.rs:34:8 + | +LL | S::CONST; + | ^^^^^ multiple `CONST` found + | +note: candidate #1 is defined in an impl of the trait `A` for the type `T` + --> $DIR/disambiguate-multiple-blanket-impl.rs:18:5 + | +LL | const CONST: usize = 1; + | ^^^^^^^^^^^^^^^^^^ +note: candidate #2 is defined in an impl of the trait `B` for the type `T` + --> $DIR/disambiguate-multiple-blanket-impl.rs:24:5 + | +LL | const CONST: usize = 2; + | ^^^^^^^^^^^^^^^^^^ +help: disambiguate the associated constant for candidate #1 + | +LL | ::CONST; + | ~~~~~~~~~~ +help: disambiguate the associated constant for candidate #2 + | +LL | ::CONST; + | ~~~~~~~~~~ + +error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0034`. +Some errors have detailed explanations: E0034, E0223. +For more information about an error, try `rustc --explain E0034`. diff --git a/tests/ui/methods/disambiguate-multiple-impl.rs b/tests/ui/methods/disambiguate-multiple-impl.rs index fa9942c745ade..9562bb865da95 100644 --- a/tests/ui/methods/disambiguate-multiple-impl.rs +++ b/tests/ui/methods/disambiguate-multiple-impl.rs @@ -1,18 +1,26 @@ trait A { + type Type; + const CONST: usize; fn foo(&self); } trait B { + type Type; + const CONST: usize; fn foo(&self); } struct S; impl A for S { + type Type = (); + const CONST: usize = 1; //~ NOTE candidate #1 fn foo(&self) {} //~ NOTE candidate #1 } impl B for S { + type Type = (); + const CONST: usize = 2; //~ NOTE candidate #2 fn foo(&self) {} //~ NOTE candidate #2 } @@ -22,5 +30,10 @@ fn main() { //~^ NOTE multiple `foo` found //~| HELP disambiguate //~| HELP disambiguate + let _: S::Type = (); //~ ERROR ambiguous associated type + //~| HELP use the fully-qualified path + let _ = S::CONST; //~ ERROR multiple applicable items in scope + //~^ NOTE multiple `CONST` found + //~| HELP disambiguate + //~| HELP disambiguate } - diff --git a/tests/ui/methods/disambiguate-multiple-impl.stderr b/tests/ui/methods/disambiguate-multiple-impl.stderr index b9fd10dba8d79..60cb086a57344 100644 --- a/tests/ui/methods/disambiguate-multiple-impl.stderr +++ b/tests/ui/methods/disambiguate-multiple-impl.stderr @@ -1,16 +1,29 @@ +error[E0223]: ambiguous associated type + --> $DIR/disambiguate-multiple-impl.rs:33:12 + | +LL | let _: S::Type = (); + | ^^^^^^^ + | +help: use the fully-qualified path + | +LL | let _: ::Type = (); + | ~~~~~~~~~~~~~~ +LL | let _: ::Type = (); + | ~~~~~~~~~~~~~~ + error[E0034]: multiple applicable items in scope - --> $DIR/disambiguate-multiple-impl.rs:21:8 + --> $DIR/disambiguate-multiple-impl.rs:29: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 + --> $DIR/disambiguate-multiple-impl.rs:18: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 + --> $DIR/disambiguate-multiple-impl.rs:24:5 | LL | fn foo(&self) {} | ^^^^^^^^^^^^^ @@ -23,6 +36,32 @@ help: disambiguate the method for candidate #2 LL | ::foo(&s); | ~~~~~~~~~~ -error: aborting due to previous error +error[E0034]: multiple applicable items in scope + --> $DIR/disambiguate-multiple-impl.rs:35:16 + | +LL | let _ = S::CONST; + | ^^^^^ multiple `CONST` found + | +note: candidate #1 is defined in an impl of the trait `A` for the type `S` + --> $DIR/disambiguate-multiple-impl.rs:17:5 + | +LL | const CONST: usize = 1; + | ^^^^^^^^^^^^^^^^^^ +note: candidate #2 is defined in an impl of the trait `B` for the type `S` + --> $DIR/disambiguate-multiple-impl.rs:23:5 + | +LL | const CONST: usize = 2; + | ^^^^^^^^^^^^^^^^^^ +help: disambiguate the associated constant for candidate #1 + | +LL | let _ = ::CONST; + | ~~~~~~~~~~ +help: disambiguate the associated constant for candidate #2 + | +LL | let _ = ::CONST; + | ~~~~~~~~~~ + +error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0034`. +Some errors have detailed explanations: E0034, E0223. +For more information about an error, try `rustc --explain E0034`. diff --git a/tests/ui/methods/disambiguate-multiple-trait-2.rs b/tests/ui/methods/disambiguate-multiple-trait-2.rs new file mode 100644 index 0000000000000..72ed3413b4ad6 --- /dev/null +++ b/tests/ui/methods/disambiguate-multiple-trait-2.rs @@ -0,0 +1,57 @@ +trait A { + type Type; //~ NOTE ambiguous `Type` from `A` + const CONST: usize = 1; //~ NOTE candidate #1 + fn foo(&self); //~ NOTE candidate #1 +} + +trait B { + type Type; //~ NOTE ambiguous `Type` from `B` + const CONST: usize; //~ NOTE candidate #2 + fn foo(&self); //~ NOTE candidate #2 +} + +trait C: A + B {} + +fn a(t: T) { + t.foo(); //~ ERROR multiple applicable items in scope + //~^ NOTE multiple `foo` found + //~| HELP disambiguate the method + //~| HELP disambiguate the method + let _ = T::CONST; //~ ERROR multiple applicable items in scope + //~^ NOTE multiple `CONST` found + //~| HELP disambiguate + //~| HELP disambiguate + let _: T::Type; //~ ERROR ambiguous associated type + //~^ NOTE ambiguous associated type `Type` + //~| HELP use fully qualified syntax + //~| HELP use fully qualified syntax +} + +#[derive(Debug)] +struct S; + +impl A for T { + type Type = (); + const CONST: usize = 1; //~ NOTE candidate #1 + fn foo(&self) {} //~ NOTE candidate #1 +} + +impl B for T { + type Type = (); + const CONST: usize = 1; //~ NOTE candidate #2 + 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 + let _ = S::CONST; //~ ERROR multiple applicable items in scope + //~^ NOTE multiple `CONST` found + //~| HELP disambiguate + //~| HELP disambiguate + let _: S::Type; //~ ERROR ambiguous associated type + //~^ HELP use the fully-qualified path +} diff --git a/tests/ui/methods/disambiguate-multiple-trait-2.stderr b/tests/ui/methods/disambiguate-multiple-trait-2.stderr new file mode 100644 index 0000000000000..76a240448e655 --- /dev/null +++ b/tests/ui/methods/disambiguate-multiple-trait-2.stderr @@ -0,0 +1,138 @@ +error[E0221]: ambiguous associated type `Type` in bounds of `T` + --> $DIR/disambiguate-multiple-trait-2.rs:24:12 + | +LL | type Type; + | --------- ambiguous `Type` from `A` +... +LL | type Type; + | --------- ambiguous `Type` from `B` +... +LL | let _: T::Type; + | ^^^^^^^ ambiguous associated type `Type` + | +help: use fully qualified syntax to disambiguate + | +LL | let _: ::Type; + | ~~~~~~~~~~ +help: use fully qualified syntax to disambiguate + | +LL | let _: ::Type; + | ~~~~~~~~~~ + +error[E0034]: multiple applicable items in scope + --> $DIR/disambiguate-multiple-trait-2.rs:16:7 + | +LL | t.foo(); + | ^^^ multiple `foo` found + | +note: candidate #1 is defined in the trait `A` + --> $DIR/disambiguate-multiple-trait-2.rs:4:5 + | +LL | fn foo(&self); + | ^^^^^^^^^^^^^^ +note: candidate #2 is defined in the trait `B` + --> $DIR/disambiguate-multiple-trait-2.rs:10:5 + | +LL | fn foo(&self); + | ^^^^^^^^^^^^^^ +help: disambiguate the method for candidate #1 + | +LL | A::foo(t); + | ~~~~~~~~~ +help: disambiguate the method for candidate #2 + | +LL | B::foo(t); + | ~~~~~~~~~ + +error[E0034]: multiple applicable items in scope + --> $DIR/disambiguate-multiple-trait-2.rs:20:16 + | +LL | let _ = T::CONST; + | ^^^^^ multiple `CONST` found + | +note: candidate #1 is defined in the trait `A` + --> $DIR/disambiguate-multiple-trait-2.rs:3:5 + | +LL | const CONST: usize = 1; + | ^^^^^^^^^^^^^^^^^^ +note: candidate #2 is defined in the trait `B` + --> $DIR/disambiguate-multiple-trait-2.rs:9:5 + | +LL | const CONST: usize; + | ^^^^^^^^^^^^^^^^^^ +help: disambiguate the associated constant for candidate #1 + | +LL | let _ = A::CONST; + | ~~~ +help: disambiguate the associated constant for candidate #2 + | +LL | let _ = B::CONST; + | ~~~ + +error[E0223]: ambiguous associated type + --> $DIR/disambiguate-multiple-trait-2.rs:55:12 + | +LL | let _: S::Type; + | ^^^^^^^ + | +help: use the fully-qualified path + | +LL | let _: ::Type; + | ~~~~~~~~~~~~~~ +LL | let _: ::Type; + | ~~~~~~~~~~~~~~ + +error[E0034]: multiple applicable items in scope + --> $DIR/disambiguate-multiple-trait-2.rs:47: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-trait-2.rs:36:5 + | +LL | fn foo(&self) {} + | ^^^^^^^^^^^^^ +note: candidate #2 is defined in an impl of the trait `B` for the type `T` + --> $DIR/disambiguate-multiple-trait-2.rs:42: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[E0034]: multiple applicable items in scope + --> $DIR/disambiguate-multiple-trait-2.rs:51:16 + | +LL | let _ = S::CONST; + | ^^^^^ multiple `CONST` found + | +note: candidate #1 is defined in an impl of the trait `A` for the type `T` + --> $DIR/disambiguate-multiple-trait-2.rs:35:5 + | +LL | const CONST: usize = 1; + | ^^^^^^^^^^^^^^^^^^ +note: candidate #2 is defined in an impl of the trait `B` for the type `T` + --> $DIR/disambiguate-multiple-trait-2.rs:41:5 + | +LL | const CONST: usize = 1; + | ^^^^^^^^^^^^^^^^^^ +help: disambiguate the associated constant for candidate #1 + | +LL | let _ = ::CONST; + | ~~~~~~~~~~ +help: disambiguate the associated constant for candidate #2 + | +LL | let _ = ::CONST; + | ~~~~~~~~~~ + +error: aborting due to 6 previous errors + +Some errors have detailed explanations: E0034, E0221, E0223. +For more information about an error, try `rustc --explain E0034`. diff --git a/tests/ui/methods/disambiguate-multiple-trait.rs b/tests/ui/methods/disambiguate-multiple-trait.rs new file mode 100644 index 0000000000000..73dfc43dd5b45 --- /dev/null +++ b/tests/ui/methods/disambiguate-multiple-trait.rs @@ -0,0 +1,34 @@ +#![feature(associated_type_defaults)] + +trait A { + type Type = (); + const CONST: usize = 1; //~ NOTE candidate #1 + fn foo(&self) {} //~ NOTE candidate #1 +} + +trait B { + type Type = (); + const CONST: usize = 2; //~ NOTE candidate #2 + fn foo(&self) {} //~ NOTE candidate #2 +} + +#[derive(Debug)] +struct S; + +impl A for T {} + +impl B for T {} + +fn main() { + let s = S; + S::foo(&s); //~ ERROR multiple applicable items in scope + //~^ NOTE multiple `foo` found + //~| HELP disambiguate + //~| HELP disambiguate + let _ = S::CONST; //~ ERROR multiple applicable items in scope + //~^ NOTE multiple `CONST` found + //~| HELP disambiguate + //~| HELP disambiguate + let _: S::Type; //~ ERROR ambiguous associated type + //~^ HELP use the fully-qualified path +} diff --git a/tests/ui/methods/disambiguate-multiple-trait.stderr b/tests/ui/methods/disambiguate-multiple-trait.stderr new file mode 100644 index 0000000000000..f88c280dfa3b2 --- /dev/null +++ b/tests/ui/methods/disambiguate-multiple-trait.stderr @@ -0,0 +1,67 @@ +error[E0223]: ambiguous associated type + --> $DIR/disambiguate-multiple-trait.rs:32:12 + | +LL | let _: S::Type; + | ^^^^^^^ + | +help: use the fully-qualified path + | +LL | let _: ::Type; + | ~~~~~~~~~~~~~~ +LL | let _: ::Type; + | ~~~~~~~~~~~~~~ + +error[E0034]: multiple applicable items in scope + --> $DIR/disambiguate-multiple-trait.rs:24: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-trait.rs:6:5 + | +LL | fn foo(&self) {} + | ^^^^^^^^^^^^^ +note: candidate #2 is defined in an impl of the trait `B` for the type `T` + --> $DIR/disambiguate-multiple-trait.rs:12: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[E0034]: multiple applicable items in scope + --> $DIR/disambiguate-multiple-trait.rs:28:16 + | +LL | let _ = S::CONST; + | ^^^^^ multiple `CONST` found + | +note: candidate #1 is defined in an impl of the trait `A` for the type `T` + --> $DIR/disambiguate-multiple-trait.rs:5:5 + | +LL | const CONST: usize = 1; + | ^^^^^^^^^^^^^^^^^^ +note: candidate #2 is defined in an impl of the trait `B` for the type `T` + --> $DIR/disambiguate-multiple-trait.rs:11:5 + | +LL | const CONST: usize = 2; + | ^^^^^^^^^^^^^^^^^^ +help: disambiguate the associated constant for candidate #1 + | +LL | let _ = ::CONST; + | ~~~~~~~~~~ +help: disambiguate the associated constant for candidate #2 + | +LL | let _ = ::CONST; + | ~~~~~~~~~~ + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0034, E0223. +For more information about an error, try `rustc --explain E0034`.