From 5cc9216ff3552ac1f6b545860bc25f25cf6551df Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Esteban=20K=C3=BCber?= <esteban@kuber.com.ar>
Date: Fri, 13 Oct 2023 23:31:35 +0000
Subject: [PATCH 1/3] 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<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
+}
+
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 |     <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`.
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 |     <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`.

From 6cf01fcf1ec24142919d92035b8531c4ff1deaca Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Esteban=20K=C3=BCber?= <esteban@kuber.com.ar>
Date: Mon, 16 Oct 2023 01:22:25 +0000
Subject: [PATCH 2/3] 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<Ty<'_>>,
     kind: ty::AssocKind,
     def_kind_descr: &'static str,
     span: Span,
@@ -3174,20 +3174,21 @@ fn print_disambiguation_help<'tcx>(
                 .collect::<Vec<_>>()
                 .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<T: std::fmt::Debug> A for T {
+    type Type = ();
+    const CONST: usize = 1; //~ NOTE candidate #1
     fn foo(&self) {} //~ NOTE candidate #1
 }
 
 impl<T: std::fmt::Debug> 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 _: <S as A>::Type;
+   |            ~~~~~~~~~~~~~~
+LL |     let _: <S as B>::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 |     <T as B>::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 |     <T as A>::CONST;
+   |     ~~~~~~~~~~
+help: disambiguate the associated constant for candidate #2
+   |
+LL |     <T as B>::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 _: <S as A>::Type = ();
+   |            ~~~~~~~~~~~~~~
+LL |     let _: <S as B>::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 |     <S as B>::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 _ = <S as A>::CONST;
+   |             ~~~~~~~~~~
+help: disambiguate the associated constant for candidate #2
+   |
+LL |     let _ = <S as B>::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: C>(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<T: std::fmt::Debug> A for T {
+    type Type = ();
+    const CONST: usize = 1; //~ NOTE candidate #1
+    fn foo(&self) {} //~ NOTE candidate #1
+}
+
+impl<T: std::fmt::Debug> 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 _: <T as A>::Type;
+   |            ~~~~~~~~~~
+help: use fully qualified syntax to disambiguate
+   |
+LL |     let _: <T as B>::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 _: <S as A>::Type;
+   |            ~~~~~~~~~~~~~~
+LL |     let _: <S as B>::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 |     <T as A>::foo(&s);
+   |     ~~~~~~~~~~
+help: disambiguate the method for candidate #2
+   |
+LL |     <T as B>::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 _ = <T as A>::CONST;
+   |             ~~~~~~~~~~
+help: disambiguate the associated constant for candidate #2
+   |
+LL |     let _ = <T as B>::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<T: std::fmt::Debug> A for T {}
+
+impl<T: std::fmt::Debug> 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 _: <S as A>::Type;
+   |            ~~~~~~~~~~~~~~
+LL |     let _: <S as B>::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 |     <T as A>::foo(&s);
+   |     ~~~~~~~~~~
+help: disambiguate the method for candidate #2
+   |
+LL |     <T as B>::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 _ = <T as A>::CONST;
+   |             ~~~~~~~~~~
+help: disambiguate the associated constant for candidate #2
+   |
+LL |     let _ = <T as B>::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`.

From 890e92feedcfe942cea8ffda2929d9d4ecf8ab5f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Esteban=20K=C3=BCber?= <esteban@kuber.com.ar>
Date: Mon, 16 Oct 2023 18:25:11 +0000
Subject: [PATCH 3/3] Unify suggestion wording

---
 .../rustc_hir_analysis/src/astconv/mod.rs     |  4 +-
 .../rustc_hir_typeck/src/method/suggest.rs    | 96 ++++++++++---------
 .../associated-const-ambiguity-report.stderr  |  8 +-
 .../issue-109071.no_gate.stderr               |  2 +-
 ...fers-shadowing-trait-item.uncovered.stderr |  2 +-
 ...guous-associated-type-with-generics.stderr |  2 +-
 .../associated-item-duplicate-names-3.stderr  |  2 +-
 ...mbig-between-bound-and-where-clause.stderr | 24 ++---
 ...rojection-from-multiple-supertraits.stderr |  8 +-
 ...sociated-types-in-ambiguous-context.stderr |  6 +-
 .../associated-types-path-1.stderr            |  4 +-
 tests/ui/did_you_mean/bad-assoc-ty.stderr     |  2 +-
 tests/ui/error-codes/E0034.stderr             |  4 +-
 tests/ui/error-codes/E0221.stderr             |  6 +-
 tests/ui/error-codes/E0223.stderr             |  2 +-
 tests/ui/lint/bare-trait-objects-path.stderr  |  2 +-
 .../disambiguate-multiple-blanket-impl.rs     |  8 +-
 .../disambiguate-multiple-blanket-impl.stderr | 14 +--
 .../ui/methods/disambiguate-multiple-impl.rs  |  8 +-
 .../methods/disambiguate-multiple-impl.stderr | 14 +--
 .../methods/disambiguate-multiple-trait-2.rs  | 15 ++-
 .../disambiguate-multiple-trait-2.stderr      | 34 +++----
 .../ui/methods/disambiguate-multiple-trait.rs |  8 +-
 .../disambiguate-multiple-trait.stderr        | 14 +--
 ...method-ambig-two-traits-from-impls2.stderr |  4 +-
 tests/ui/self/self-impl.stderr                |  4 +-
 .../struct-path-associated-type.stderr        |  6 +-
 .../suggest-trait-in-ufcs-in-hrtb.stderr      |  2 +-
 tests/ui/traits/item-privacy.stderr           |  4 +-
 tests/ui/typeck/issue-107087.stderr           |  2 +-
 tests/ui/typeck/issue-110052.stderr           |  2 +-
 31 files changed, 145 insertions(+), 168 deletions(-)

diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs
index 960a1bfdd2d57..6b4980deae405 100644
--- a/compiler/rustc_hir_analysis/src/astconv/mod.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs
@@ -1018,7 +1018,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                     }
                     err.span_suggestions(
                         span,
-                        "use the fully-qualified path",
+                        "use fully-qualified syntax",
                         suggestions,
                         Applicability::MachineApplicable,
                     );
@@ -1190,7 +1190,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                     } else {
                         err.span_suggestion_verbose(
                             span.with_hi(assoc_name.span.lo()),
-                            "use fully qualified syntax to disambiguate",
+                            "use fully-qualified syntax to disambiguate",
                             format!("<{ty_param_name} as {}>::", bound.print_only_trait_path()),
                             Applicability::MaybeIncorrect,
                         );
diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs
index f3441b313cb59..29e5f39daf7ea 100644
--- a/compiler/rustc_hir_typeck/src/method/suggest.rs
+++ b/compiler/rustc_hir_typeck/src/method/suggest.rs
@@ -1260,6 +1260,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         // Dynamic limit to avoid hiding just one candidate, which is silly.
         let limit = if sources.len() == 5 { 5 } else { 4 };
 
+        let mut suggs = vec![];
         for (idx, source) in sources.iter().take(limit).enumerate() {
             match *source {
                 CandidateSource::Impl(impl_did) => {
@@ -1334,7 +1335,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                                 .copied()
                                 .unwrap_or(rcvr_ty),
                         };
-                        print_disambiguation_help(
+                        if let Some(sugg) = print_disambiguation_help(
                             item_name,
                             args,
                             err,
@@ -1347,7 +1348,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                             idx,
                             self.tcx.sess.source_map(),
                             item.fn_has_self_parameter,
-                        );
+                        ) {
+                            suggs.push(sugg);
+                        }
                     }
                 }
                 CandidateSource::Trait(trait_did) => {
@@ -1371,7 +1374,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     };
                     if let Some(sugg_span) = sugg_span {
                         let path = self.tcx.def_path_str(trait_did);
-                        print_disambiguation_help(
+                        if let Some(sugg) = print_disambiguation_help(
                             item_name,
                             args,
                             err,
@@ -1384,11 +1387,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                             idx,
                             self.tcx.sess.source_map(),
                             item.fn_has_self_parameter,
-                        );
+                        ) {
+                            suggs.push(sugg);
+                        }
                     }
                 }
             }
         }
+        if !suggs.is_empty() && let Some(span) = sugg_span {
+            err.span_suggestions(
+                span.with_hi(item_name.span.lo()),
+                "use fully-qualified syntax to disambiguate",
+                suggs,
+                Applicability::MachineApplicable,
+            );
+        }
         if sources.len() > limit {
             err.note(format!("and {} others", sources.len() - limit));
         }
@@ -3155,47 +3168,44 @@ fn print_disambiguation_help<'tcx>(
     candidate: Option<usize>,
     source_map: &source_map::SourceMap,
     fn_has_self_parameter: bool,
-) {
-    let mut applicability = Applicability::MachineApplicable;
-    let (span, sugg) = if let (
-        ty::AssocKind::Fn,
-        Some(MethodCallComponents { receiver, args, .. }),
-    ) = (kind, args)
-    {
-        let args = format!(
-            "({}{})",
-            rcvr_ty.ref_mutability().map_or("", |mutbl| mutbl.ref_prefix_str()),
-            std::iter::once(receiver)
-                .chain(args.iter())
-                .map(|arg| source_map.span_to_snippet(arg.span).unwrap_or_else(|_| {
-                    applicability = Applicability::HasPlaceholders;
-                    "_".to_owned()
-                }))
-                .collect::<Vec<_>>()
-                .join(", "),
-        );
-        let trait_name = if !fn_has_self_parameter && let Some(impl_self_ty) = impl_self_ty {
+) -> Option<String> {
+    Some(
+        if let (ty::AssocKind::Fn, Some(MethodCallComponents { receiver, args, .. })) = (kind, args)
+        {
+            let args = format!(
+                "({}{})",
+                rcvr_ty.ref_mutability().map_or("", |mutbl| mutbl.ref_prefix_str()),
+                std::iter::once(receiver)
+                    .chain(args.iter())
+                    .map(|arg| source_map
+                        .span_to_snippet(arg.span)
+                        .unwrap_or_else(|_| { "_".to_owned() }))
+                    .collect::<Vec<_>>()
+                    .join(", "),
+            );
+            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!("{trait_name}::"))
-    };
-    err.span_suggestion_verbose(
-        span,
-        format!(
-            "disambiguate the {def_kind_descr} for {}",
-            if let Some(candidate) = candidate {
-                format!("candidate #{candidate}")
-            } else {
-                "the candidate".to_string()
-            },
-        ),
-        sugg,
-        applicability,
-    );
+            err.span_suggestion_verbose(
+                span,
+                format!(
+                    "disambiguate the {def_kind_descr} for {}",
+                    if let Some(candidate) = candidate {
+                        format!("candidate #{candidate}")
+                    } else {
+                        "the candidate".to_string()
+                    },
+                ),
+                format!("{trait_name}::{item_name}{args}"),
+                Applicability::HasPlaceholders,
+            );
+            return None;
+        } else if let Some(impl_self_ty) = impl_self_ty {
+            format!("<{impl_self_ty} as {trait_name}>::")
+        } else {
+            format!("{trait_name}::")
+        },
+    )
 }
diff --git a/tests/ui/associated-consts/associated-const-ambiguity-report.stderr b/tests/ui/associated-consts/associated-const-ambiguity-report.stderr
index 5435f22321c92..e39224f2c1646 100644
--- a/tests/ui/associated-consts/associated-const-ambiguity-report.stderr
+++ b/tests/ui/associated-consts/associated-const-ambiguity-report.stderr
@@ -14,14 +14,12 @@ note: candidate #2 is defined in an impl of the trait `Bar` for the type `i32`
    |
 LL |     const ID: i32 = 3;
    |     ^^^^^^^^^^^^^
-help: disambiguate the associated constant for candidate #1
-   |
-LL | const X: i32 = <i32 as Foo>::ID;
-   |                ~~~~~~~~~~~~~~
-help: disambiguate the associated constant for candidate #2
+help: use fully-qualified syntax to disambiguate
    |
 LL | const X: i32 = <i32 as Bar>::ID;
    |                ~~~~~~~~~~~~~~
+LL | const X: i32 = <i32 as Foo>::ID;
+   |                ~~~~~~~~~~~~~~
 
 error: aborting due to previous error
 
diff --git a/tests/ui/associated-inherent-types/issue-109071.no_gate.stderr b/tests/ui/associated-inherent-types/issue-109071.no_gate.stderr
index 6f206f2b89c79..866a53f57fc23 100644
--- a/tests/ui/associated-inherent-types/issue-109071.no_gate.stderr
+++ b/tests/ui/associated-inherent-types/issue-109071.no_gate.stderr
@@ -33,7 +33,7 @@ error[E0223]: ambiguous associated type
   --> $DIR/issue-109071.rs:15:22
    |
 LL |     fn T() -> Option<Self::Item> {}
-   |                      ^^^^^^^^^^ help: use the fully-qualified path: `<Windows<T> as IntoIterator>::Item`
+   |                      ^^^^^^^^^^ help: use fully-qualified syntax: `<Windows<T> as IntoIterator>::Item`
 
 error: aborting due to 4 previous errors
 
diff --git a/tests/ui/associated-inherent-types/not-found-self-type-differs-shadowing-trait-item.uncovered.stderr b/tests/ui/associated-inherent-types/not-found-self-type-differs-shadowing-trait-item.uncovered.stderr
index 88c72042ce2d0..9206b4f6db7e5 100644
--- a/tests/ui/associated-inherent-types/not-found-self-type-differs-shadowing-trait-item.uncovered.stderr
+++ b/tests/ui/associated-inherent-types/not-found-self-type-differs-shadowing-trait-item.uncovered.stderr
@@ -2,7 +2,7 @@ error[E0223]: ambiguous associated type
   --> $DIR/not-found-self-type-differs-shadowing-trait-item.rs:28:12
    |
 LL |     let _: S::<bool>::Pr = ();
-   |            ^^^^^^^^^^^^^ help: use the fully-qualified path: `<S<bool> as Tr>::Pr`
+   |            ^^^^^^^^^^^^^ help: use fully-qualified syntax: `<S<bool> as Tr>::Pr`
 
 error: aborting due to previous error
 
diff --git a/tests/ui/associated-item/ambiguous-associated-type-with-generics.stderr b/tests/ui/associated-item/ambiguous-associated-type-with-generics.stderr
index 97088b79fd671..f7a47be8dc39a 100644
--- a/tests/ui/associated-item/ambiguous-associated-type-with-generics.stderr
+++ b/tests/ui/associated-item/ambiguous-associated-type-with-generics.stderr
@@ -2,7 +2,7 @@ error[E0223]: ambiguous associated type
   --> $DIR/ambiguous-associated-type-with-generics.rs:13:13
    |
 LL |     let _x: <dyn Trait<i32>>::Ty;
-   |             ^^^^^^^^^^^^^^^^^^^^ help: use the fully-qualified path: `<dyn Trait<i32> as Assoc>::Ty`
+   |             ^^^^^^^^^^^^^^^^^^^^ help: use fully-qualified syntax: `<dyn Trait<i32> as Assoc>::Ty`
 
 error: aborting due to previous error
 
diff --git a/tests/ui/associated-item/associated-item-duplicate-names-3.stderr b/tests/ui/associated-item/associated-item-duplicate-names-3.stderr
index d0c170620766c..a2346e292ac40 100644
--- a/tests/ui/associated-item/associated-item-duplicate-names-3.stderr
+++ b/tests/ui/associated-item/associated-item-duplicate-names-3.stderr
@@ -13,7 +13,7 @@ error[E0223]: ambiguous associated type
   --> $DIR/associated-item-duplicate-names-3.rs:18:12
    |
 LL |     let x: Baz::Bar = 5;
-   |            ^^^^^^^^ help: use the fully-qualified path: `<Baz as Foo>::Bar`
+   |            ^^^^^^^^ help: use fully-qualified syntax: `<Baz as Foo>::Bar`
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/associated-types/associated-type-projection-ambig-between-bound-and-where-clause.stderr b/tests/ui/associated-types/associated-type-projection-ambig-between-bound-and-where-clause.stderr
index 236552baf9287..df01e1e376869 100644
--- a/tests/ui/associated-types/associated-type-projection-ambig-between-bound-and-where-clause.stderr
+++ b/tests/ui/associated-types/associated-type-projection-ambig-between-bound-and-where-clause.stderr
@@ -10,11 +10,11 @@ LL |     type Color;
 LL | fn a<C:Vehicle+Box>(_: C::Color) {
    |                        ^^^^^^^^ ambiguous associated type `Color`
    |
-help: use fully qualified syntax to disambiguate
+help: use fully-qualified syntax to disambiguate
    |
 LL | fn a<C:Vehicle+Box>(_: <C as Box>::Color) {
    |                        ~~~~~~~~~~~~
-help: use fully qualified syntax to disambiguate
+help: use fully-qualified syntax to disambiguate
    |
 LL | fn a<C:Vehicle+Box>(_: <C as Vehicle>::Color) {
    |                        ~~~~~~~~~~~~~~~~
@@ -31,11 +31,11 @@ LL |     type Color;
 LL | fn b<C>(_: C::Color) where C : Vehicle+Box {
    |            ^^^^^^^^ ambiguous associated type `Color`
    |
-help: use fully qualified syntax to disambiguate
+help: use fully-qualified syntax to disambiguate
    |
 LL | fn b<C>(_: <C as Box>::Color) where C : Vehicle+Box {
    |            ~~~~~~~~~~~~
-help: use fully qualified syntax to disambiguate
+help: use fully-qualified syntax to disambiguate
    |
 LL | fn b<C>(_: <C as Vehicle>::Color) where C : Vehicle+Box {
    |            ~~~~~~~~~~~~~~~~
@@ -52,11 +52,11 @@ LL |     type Color;
 LL | fn c<C>(_: C::Color) where C : Vehicle, C : Box {
    |            ^^^^^^^^ ambiguous associated type `Color`
    |
-help: use fully qualified syntax to disambiguate
+help: use fully-qualified syntax to disambiguate
    |
 LL | fn c<C>(_: <C as Box>::Color) where C : Vehicle, C : Box {
    |            ~~~~~~~~~~~~
-help: use fully qualified syntax to disambiguate
+help: use fully-qualified syntax to disambiguate
    |
 LL | fn c<C>(_: <C as Vehicle>::Color) where C : Vehicle, C : Box {
    |            ~~~~~~~~~~~~~~~~
@@ -73,11 +73,11 @@ LL |     type Color;
 LL |     fn e(&self, _: X::Color) where X : Box;
    |                    ^^^^^^^^ ambiguous associated type `Color`
    |
-help: use fully qualified syntax to disambiguate
+help: use fully-qualified syntax to disambiguate
    |
 LL |     fn e(&self, _: <X as Box>::Color) where X : Box;
    |                    ~~~~~~~~~~~~
-help: use fully qualified syntax to disambiguate
+help: use fully-qualified syntax to disambiguate
    |
 LL |     fn e(&self, _: <X as Vehicle>::Color) where X : Box;
    |                    ~~~~~~~~~~~~~~~~
@@ -94,11 +94,11 @@ LL |     type Color;
 LL |     fn f(&self, _: X::Color) where X : Box { }
    |                    ^^^^^^^^ ambiguous associated type `Color`
    |
-help: use fully qualified syntax to disambiguate
+help: use fully-qualified syntax to disambiguate
    |
 LL |     fn f(&self, _: <X as Box>::Color) where X : Box { }
    |                    ~~~~~~~~~~~~
-help: use fully qualified syntax to disambiguate
+help: use fully-qualified syntax to disambiguate
    |
 LL |     fn f(&self, _: <X as Vehicle>::Color) where X : Box { }
    |                    ~~~~~~~~~~~~~~~~
@@ -115,11 +115,11 @@ LL |     type Color;
 LL |     fn d(&self, _: X::Color) where X : Box { }
    |                    ^^^^^^^^ ambiguous associated type `Color`
    |
-help: use fully qualified syntax to disambiguate
+help: use fully-qualified syntax to disambiguate
    |
 LL |     fn d(&self, _: <X as Box>::Color) where X : Box { }
    |                    ~~~~~~~~~~~~
-help: use fully qualified syntax to disambiguate
+help: use fully-qualified syntax to disambiguate
    |
 LL |     fn d(&self, _: <X as Vehicle>::Color) where X : Box { }
    |                    ~~~~~~~~~~~~~~~~
diff --git a/tests/ui/associated-types/associated-type-projection-from-multiple-supertraits.stderr b/tests/ui/associated-types/associated-type-projection-from-multiple-supertraits.stderr
index e765f93239841..4f8954b80bc71 100644
--- a/tests/ui/associated-types/associated-type-projection-from-multiple-supertraits.stderr
+++ b/tests/ui/associated-types/associated-type-projection-from-multiple-supertraits.stderr
@@ -18,11 +18,11 @@ LL |     type Color;
 LL | fn dent<C:BoxCar>(c: C, color: C::Color) {
    |                                ^^^^^^^^ ambiguous associated type `Color`
    |
-help: use fully qualified syntax to disambiguate
+help: use fully-qualified syntax to disambiguate
    |
 LL | fn dent<C:BoxCar>(c: C, color: <C as Vehicle>::Color) {
    |                                ~~~~~~~~~~~~~~~~
-help: use fully qualified syntax to disambiguate
+help: use fully-qualified syntax to disambiguate
    |
 LL | fn dent<C:BoxCar>(c: C, color: <C as Box>::Color) {
    |                                ~~~~~~~~~~~~
@@ -71,11 +71,11 @@ LL |     type Color;
 LL | fn paint<C:BoxCar>(c: C, d: C::Color) {
    |                             ^^^^^^^^ ambiguous associated type `Color`
    |
-help: use fully qualified syntax to disambiguate
+help: use fully-qualified syntax to disambiguate
    |
 LL | fn paint<C:BoxCar>(c: C, d: <C as Vehicle>::Color) {
    |                             ~~~~~~~~~~~~~~~~
-help: use fully qualified syntax to disambiguate
+help: use fully-qualified syntax to disambiguate
    |
 LL | fn paint<C:BoxCar>(c: C, d: <C as Box>::Color) {
    |                             ~~~~~~~~~~~~
diff --git a/tests/ui/associated-types/associated-types-in-ambiguous-context.stderr b/tests/ui/associated-types/associated-types-in-ambiguous-context.stderr
index 1ff6fd4b821e3..d361643f024d1 100644
--- a/tests/ui/associated-types/associated-types-in-ambiguous-context.stderr
+++ b/tests/ui/associated-types/associated-types-in-ambiguous-context.stderr
@@ -13,7 +13,7 @@ error[E0223]: ambiguous associated type
   --> $DIR/associated-types-in-ambiguous-context.rs:22:17
    |
 LL | trait Foo where Foo::Assoc: Bar {
-   |                 ^^^^^^^^^^ help: use the fully-qualified path: `<Self as Foo>::Assoc`
+   |                 ^^^^^^^^^^ help: use fully-qualified syntax: `<Self as Foo>::Assoc`
 
 error[E0223]: ambiguous associated type
   --> $DIR/associated-types-in-ambiguous-context.rs:27:10
@@ -21,7 +21,7 @@ error[E0223]: ambiguous associated type
 LL | type X = std::ops::Deref::Target;
    |          ^^^^^^^^^^^^^^^^^^^^^^^
    |
-help: use the fully-qualified path
+help: use fully-qualified syntax
    |
 LL | type X = <CString as Deref>::Target;
    |          ~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -37,7 +37,7 @@ error[E0223]: ambiguous associated type
   --> $DIR/associated-types-in-ambiguous-context.rs:13:23
    |
 LL |     fn grab(&self) -> Grab::Value;
-   |                       ^^^^^^^^^^^ help: use the fully-qualified path: `<Self as Grab>::Value`
+   |                       ^^^^^^^^^^^ help: use fully-qualified syntax: `<Self as Grab>::Value`
 
 error[E0223]: ambiguous associated type
   --> $DIR/associated-types-in-ambiguous-context.rs:16:22
diff --git a/tests/ui/associated-types/associated-types-path-1.stderr b/tests/ui/associated-types/associated-types-path-1.stderr
index a67f77e37c707..cab9dcec0b6b7 100644
--- a/tests/ui/associated-types/associated-types-path-1.stderr
+++ b/tests/ui/associated-types/associated-types-path-1.stderr
@@ -16,11 +16,11 @@ LL |     type A;
 LL | pub fn f2<T: Foo + Bar>(a: T, x: T::A) {}
    |                                  ^^^^ ambiguous associated type `A`
    |
-help: use fully qualified syntax to disambiguate
+help: use fully-qualified syntax to disambiguate
    |
 LL | pub fn f2<T: Foo + Bar>(a: T, x: <T as Bar>::A) {}
    |                                  ~~~~~~~~~~~~
-help: use fully qualified syntax to disambiguate
+help: use fully-qualified syntax to disambiguate
    |
 LL | pub fn f2<T: Foo + Bar>(a: T, x: <T as Foo>::A) {}
    |                                  ~~~~~~~~~~~~
diff --git a/tests/ui/did_you_mean/bad-assoc-ty.stderr b/tests/ui/did_you_mean/bad-assoc-ty.stderr
index efa6bb6682407..5c0c7a0b94ffe 100644
--- a/tests/ui/did_you_mean/bad-assoc-ty.stderr
+++ b/tests/ui/did_you_mean/bad-assoc-ty.stderr
@@ -191,7 +191,7 @@ error[E0223]: ambiguous associated type
   --> $DIR/bad-assoc-ty.rs:33:10
    |
 LL | type H = Fn(u8) -> (u8)::Output;
-   |          ^^^^^^^^^^^^^^^^^^^^^^ help: use the fully-qualified path: `<(dyn Fn(u8) -> u8 + 'static) as IntoFuture>::Output`
+   |          ^^^^^^^^^^^^^^^^^^^^^^ help: use fully-qualified syntax: `<(dyn Fn(u8) -> u8 + 'static) as IntoFuture>::Output`
 
 error[E0223]: ambiguous associated type
   --> $DIR/bad-assoc-ty.rs:39:19
diff --git a/tests/ui/error-codes/E0034.stderr b/tests/ui/error-codes/E0034.stderr
index e296217026570..da6f221881cec 100644
--- a/tests/ui/error-codes/E0034.stderr
+++ b/tests/ui/error-codes/E0034.stderr
@@ -14,12 +14,10 @@ note: candidate #2 is defined in an impl of the trait `Trait2` for the type `Tes
    |
 LL |     fn foo() {}
    |     ^^^^^^^^
-help: disambiguate the associated function for candidate #1
+help: use fully-qualified syntax to disambiguate
    |
 LL |     <Test as Trait1>::foo()
    |     ~~~~~~~~~~~~~~~~~~
-help: disambiguate the associated function for candidate #2
-   |
 LL |     <Test as Trait2>::foo()
    |     ~~~~~~~~~~~~~~~~~~
 
diff --git a/tests/ui/error-codes/E0221.stderr b/tests/ui/error-codes/E0221.stderr
index 5414d77ad7c51..e600acf783446 100644
--- a/tests/ui/error-codes/E0221.stderr
+++ b/tests/ui/error-codes/E0221.stderr
@@ -10,11 +10,11 @@ LL |     fn do_something() {
 LL |         let _: Self::A;
    |                ^^^^^^^ ambiguous associated type `A`
    |
-help: use fully qualified syntax to disambiguate
+help: use fully-qualified syntax to disambiguate
    |
 LL |         let _: <Self as Foo>::A;
    |                ~~~~~~~~~~~~~~~
-help: use fully qualified syntax to disambiguate
+help: use fully-qualified syntax to disambiguate
    |
 LL |         let _: <Self as Bar>::A;
    |                ~~~~~~~~~~~~~~~
@@ -29,7 +29,7 @@ LL |         let _: Self::Err;
    |                ^^^^^^^^^ ambiguous associated type `Err`
    |
    = note: associated type `Self` could derive from `FromStr`
-help: use fully qualified syntax to disambiguate
+help: use fully-qualified syntax to disambiguate
    |
 LL |         let _: <Self as My>::Err;
    |                ~~~~~~~~~~~~~~
diff --git a/tests/ui/error-codes/E0223.stderr b/tests/ui/error-codes/E0223.stderr
index 42945e42f6ea1..1299ba5f50c15 100644
--- a/tests/ui/error-codes/E0223.stderr
+++ b/tests/ui/error-codes/E0223.stderr
@@ -2,7 +2,7 @@ error[E0223]: ambiguous associated type
   --> $DIR/E0223.rs:8:14
    |
 LL |     let foo: MyTrait::X;
-   |              ^^^^^^^^^^ help: use the fully-qualified path: `<MyStruct as MyTrait>::X`
+   |              ^^^^^^^^^^ help: use fully-qualified syntax: `<MyStruct as MyTrait>::X`
 
 error: aborting due to previous error
 
diff --git a/tests/ui/lint/bare-trait-objects-path.stderr b/tests/ui/lint/bare-trait-objects-path.stderr
index a19f4963c239b..01ca08a6f19be 100644
--- a/tests/ui/lint/bare-trait-objects-path.stderr
+++ b/tests/ui/lint/bare-trait-objects-path.stderr
@@ -16,7 +16,7 @@ error[E0223]: ambiguous associated type
   --> $DIR/bare-trait-objects-path.rs:23:12
    |
 LL |     let _: Dyn::Ty;
-   |            ^^^^^^^ help: use the fully-qualified path: `<dyn Dyn as Assoc>::Ty`
+   |            ^^^^^^^ help: use fully-qualified syntax: `<dyn Dyn as Assoc>::Ty`
 
 warning: trait objects without an explicit `dyn` are deprecated
   --> $DIR/bare-trait-objects-path.rs:14:5
diff --git a/tests/ui/methods/disambiguate-multiple-blanket-impl.rs b/tests/ui/methods/disambiguate-multiple-blanket-impl.rs
index f8fb8439ddc50..6a17f6a2172a8 100644
--- a/tests/ui/methods/disambiguate-multiple-blanket-impl.rs
+++ b/tests/ui/methods/disambiguate-multiple-blanket-impl.rs
@@ -29,12 +29,10 @@ fn main() {
     let s = S;
     S::foo(&s); //~ ERROR multiple applicable items in scope
     //~^ NOTE multiple `foo` found
-    //~| HELP disambiguate
-    //~| HELP disambiguate
+    //~| HELP use fully-qualified syntax to disambiguate
     S::CONST; //~ ERROR multiple applicable items in scope
     //~^ NOTE multiple `CONST` found
-    //~| HELP disambiguate
-    //~| HELP disambiguate
+    //~| HELP use fully-qualified syntax to disambiguate
     let _: S::Type; //~ ERROR ambiguous associated type
-    //~^ HELP use the fully-qualified path
+    //~^ HELP use fully-qualified syntax
 }
diff --git a/tests/ui/methods/disambiguate-multiple-blanket-impl.stderr b/tests/ui/methods/disambiguate-multiple-blanket-impl.stderr
index 5138e7fa2cb05..a9e9c679fdb67 100644
--- a/tests/ui/methods/disambiguate-multiple-blanket-impl.stderr
+++ b/tests/ui/methods/disambiguate-multiple-blanket-impl.stderr
@@ -1,10 +1,10 @@
 error[E0223]: ambiguous associated type
-  --> $DIR/disambiguate-multiple-blanket-impl.rs:38:12
+  --> $DIR/disambiguate-multiple-blanket-impl.rs:36:12
    |
 LL |     let _: S::Type;
    |            ^^^^^^^
    |
-help: use the fully-qualified path
+help: use fully-qualified syntax
    |
 LL |     let _: <S as A>::Type;
    |            ~~~~~~~~~~~~~~
@@ -27,17 +27,15 @@ note: candidate #2 is defined in an impl of the trait `B` for the type `T`
    |
 LL |     fn foo(&self) {}
    |     ^^^^^^^^^^^^^
-help: disambiguate the method for candidate #1
+help: use fully-qualified syntax to disambiguate
    |
 LL |     <T as A>::foo(&s);
    |     ~~~~~~~~~~
-help: disambiguate the method for candidate #2
-   |
 LL |     <T as B>::foo(&s);
    |     ~~~~~~~~~~
 
 error[E0034]: multiple applicable items in scope
-  --> $DIR/disambiguate-multiple-blanket-impl.rs:34:8
+  --> $DIR/disambiguate-multiple-blanket-impl.rs:33:8
    |
 LL |     S::CONST;
    |        ^^^^^ multiple `CONST` found
@@ -52,12 +50,10 @@ note: candidate #2 is defined in an impl of the trait `B` for the type `T`
    |
 LL |     const CONST: usize = 2;
    |     ^^^^^^^^^^^^^^^^^^
-help: disambiguate the associated constant for candidate #1
+help: use fully-qualified syntax to disambiguate
    |
 LL |     <T as A>::CONST;
    |     ~~~~~~~~~~
-help: disambiguate the associated constant for candidate #2
-   |
 LL |     <T as B>::CONST;
    |     ~~~~~~~~~~
 
diff --git a/tests/ui/methods/disambiguate-multiple-impl.rs b/tests/ui/methods/disambiguate-multiple-impl.rs
index 9562bb865da95..9a82ff01574a5 100644
--- a/tests/ui/methods/disambiguate-multiple-impl.rs
+++ b/tests/ui/methods/disambiguate-multiple-impl.rs
@@ -28,12 +28,10 @@ fn main() {
     let s = S;
     S::foo(&s); //~ ERROR multiple applicable items in scope
     //~^ NOTE multiple `foo` found
-    //~| HELP disambiguate
-    //~| HELP disambiguate
+    //~| HELP use fully-qualified syntax
     let _: S::Type = (); //~ ERROR ambiguous associated type
-    //~| HELP use the fully-qualified path
+    //~| HELP use fully-qualified syntax
     let _ = S::CONST; //~ ERROR multiple applicable items in scope
     //~^ NOTE multiple `CONST` found
-    //~| HELP disambiguate
-    //~| HELP disambiguate
+    //~| HELP use fully-qualified syntax
 }
diff --git a/tests/ui/methods/disambiguate-multiple-impl.stderr b/tests/ui/methods/disambiguate-multiple-impl.stderr
index 60cb086a57344..901bfc30a3f23 100644
--- a/tests/ui/methods/disambiguate-multiple-impl.stderr
+++ b/tests/ui/methods/disambiguate-multiple-impl.stderr
@@ -1,10 +1,10 @@
 error[E0223]: ambiguous associated type
-  --> $DIR/disambiguate-multiple-impl.rs:33:12
+  --> $DIR/disambiguate-multiple-impl.rs:32:12
    |
 LL |     let _: S::Type = ();
    |            ^^^^^^^
    |
-help: use the fully-qualified path
+help: use fully-qualified syntax
    |
 LL |     let _: <S as A>::Type = ();
    |            ~~~~~~~~~~~~~~
@@ -27,17 +27,15 @@ note: candidate #2 is defined in an impl of the trait `B` for the type `S`
    |
 LL |     fn foo(&self) {}
    |     ^^^^^^^^^^^^^
-help: disambiguate the method for candidate #1
+help: use fully-qualified syntax to disambiguate
    |
 LL |     <S as A>::foo(&s);
    |     ~~~~~~~~~~
-help: disambiguate the method for candidate #2
-   |
 LL |     <S as B>::foo(&s);
    |     ~~~~~~~~~~
 
 error[E0034]: multiple applicable items in scope
-  --> $DIR/disambiguate-multiple-impl.rs:35:16
+  --> $DIR/disambiguate-multiple-impl.rs:34:16
    |
 LL |     let _ = S::CONST;
    |                ^^^^^ multiple `CONST` found
@@ -52,12 +50,10 @@ note: candidate #2 is defined in an impl of the trait `B` for the type `S`
    |
 LL |     const CONST: usize = 2;
    |     ^^^^^^^^^^^^^^^^^^
-help: disambiguate the associated constant for candidate #1
+help: use fully-qualified syntax to disambiguate
    |
 LL |     let _ = <S as A>::CONST;
    |             ~~~~~~~~~~
-help: disambiguate the associated constant for candidate #2
-   |
 LL |     let _ = <S as B>::CONST;
    |             ~~~~~~~~~~
 
diff --git a/tests/ui/methods/disambiguate-multiple-trait-2.rs b/tests/ui/methods/disambiguate-multiple-trait-2.rs
index 72ed3413b4ad6..829491d824d78 100644
--- a/tests/ui/methods/disambiguate-multiple-trait-2.rs
+++ b/tests/ui/methods/disambiguate-multiple-trait-2.rs
@@ -19,12 +19,11 @@ fn a<T: C>(t: T) {
     //~| HELP disambiguate the method
     let _ = T::CONST; //~ ERROR multiple applicable items in scope
     //~^ NOTE multiple `CONST` found
-    //~| HELP disambiguate
-    //~| HELP disambiguate
+    //~| HELP use fully-qualified syntax
     let _: T::Type; //~ ERROR ambiguous associated type
     //~^ NOTE ambiguous associated type `Type`
-    //~| HELP use fully qualified syntax
-    //~| HELP use fully qualified syntax
+    //~| HELP use fully-qualified syntax
+    //~| HELP use fully-qualified syntax
 }
 
 #[derive(Debug)]
@@ -46,12 +45,10 @@ fn main() {
     let s = S;
     S::foo(&s); //~ ERROR multiple applicable items in scope
     //~^ NOTE multiple `foo` found
-    //~| HELP disambiguate
-    //~| HELP disambiguate
+    //~| HELP use fully-qualified syntax
     let _ = S::CONST; //~ ERROR multiple applicable items in scope
     //~^ NOTE multiple `CONST` found
-    //~| HELP disambiguate
-    //~| HELP disambiguate
+    //~| HELP use fully-qualified syntax
     let _: S::Type; //~ ERROR ambiguous associated type
-    //~^ HELP use the fully-qualified path
+    //~^ HELP use fully-qualified syntax
 }
diff --git a/tests/ui/methods/disambiguate-multiple-trait-2.stderr b/tests/ui/methods/disambiguate-multiple-trait-2.stderr
index 76a240448e655..0f9c60ce243df 100644
--- a/tests/ui/methods/disambiguate-multiple-trait-2.stderr
+++ b/tests/ui/methods/disambiguate-multiple-trait-2.stderr
@@ -1,5 +1,5 @@
 error[E0221]: ambiguous associated type `Type` in bounds of `T`
-  --> $DIR/disambiguate-multiple-trait-2.rs:24:12
+  --> $DIR/disambiguate-multiple-trait-2.rs:23:12
    |
 LL |     type Type;
    |     --------- ambiguous `Type` from `A`
@@ -10,11 +10,11 @@ LL |     type Type;
 LL |     let _: T::Type;
    |            ^^^^^^^ ambiguous associated type `Type`
    |
-help: use fully qualified syntax to disambiguate
+help: use fully-qualified syntax to disambiguate
    |
 LL |     let _: <T as A>::Type;
    |            ~~~~~~~~~~
-help: use fully qualified syntax to disambiguate
+help: use fully-qualified syntax to disambiguate
    |
 LL |     let _: <T as B>::Type;
    |            ~~~~~~~~~~
@@ -60,22 +60,20 @@ note: candidate #2 is defined in the trait `B`
    |
 LL |     const CONST: usize;
    |     ^^^^^^^^^^^^^^^^^^
-help: disambiguate the associated constant for candidate #1
+help: use fully-qualified syntax to disambiguate
    |
 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
+  --> $DIR/disambiguate-multiple-trait-2.rs:52:12
    |
 LL |     let _: S::Type;
    |            ^^^^^^^
    |
-help: use the fully-qualified path
+help: use fully-qualified syntax
    |
 LL |     let _: <S as A>::Type;
    |            ~~~~~~~~~~~~~~
@@ -83,52 +81,48 @@ LL |     let _: <S as B>::Type;
    |            ~~~~~~~~~~~~~~
 
 error[E0034]: multiple applicable items in scope
-  --> $DIR/disambiguate-multiple-trait-2.rs:47:8
+  --> $DIR/disambiguate-multiple-trait-2.rs:46: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
+  --> $DIR/disambiguate-multiple-trait-2.rs:35: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
+  --> $DIR/disambiguate-multiple-trait-2.rs:41:5
    |
 LL |     fn foo(&self) {}
    |     ^^^^^^^^^^^^^
-help: disambiguate the method for candidate #1
+help: use fully-qualified syntax to disambiguate
    |
 LL |     <T as A>::foo(&s);
    |     ~~~~~~~~~~
-help: disambiguate the method for candidate #2
-   |
 LL |     <T as B>::foo(&s);
    |     ~~~~~~~~~~
 
 error[E0034]: multiple applicable items in scope
-  --> $DIR/disambiguate-multiple-trait-2.rs:51:16
+  --> $DIR/disambiguate-multiple-trait-2.rs:49: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
+  --> $DIR/disambiguate-multiple-trait-2.rs:34: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
+  --> $DIR/disambiguate-multiple-trait-2.rs:40:5
    |
 LL |     const CONST: usize = 1;
    |     ^^^^^^^^^^^^^^^^^^
-help: disambiguate the associated constant for candidate #1
+help: use fully-qualified syntax to disambiguate
    |
 LL |     let _ = <T as A>::CONST;
    |             ~~~~~~~~~~
-help: disambiguate the associated constant for candidate #2
-   |
 LL |     let _ = <T as B>::CONST;
    |             ~~~~~~~~~~
 
diff --git a/tests/ui/methods/disambiguate-multiple-trait.rs b/tests/ui/methods/disambiguate-multiple-trait.rs
index 73dfc43dd5b45..c990d047576b9 100644
--- a/tests/ui/methods/disambiguate-multiple-trait.rs
+++ b/tests/ui/methods/disambiguate-multiple-trait.rs
@@ -23,12 +23,10 @@ fn main() {
     let s = S;
     S::foo(&s); //~ ERROR multiple applicable items in scope
     //~^ NOTE multiple `foo` found
-    //~| HELP disambiguate
-    //~| HELP disambiguate
+    //~| HELP use fully-qualified syntax
     let _ = S::CONST; //~ ERROR multiple applicable items in scope
     //~^ NOTE multiple `CONST` found
-    //~| HELP disambiguate
-    //~| HELP disambiguate
+    //~| HELP use fully-qualified syntax
     let _: S::Type; //~ ERROR ambiguous associated type
-    //~^ HELP use the fully-qualified path
+    //~^ HELP use fully-qualified syntax
 }
diff --git a/tests/ui/methods/disambiguate-multiple-trait.stderr b/tests/ui/methods/disambiguate-multiple-trait.stderr
index f88c280dfa3b2..9a50d51245ba9 100644
--- a/tests/ui/methods/disambiguate-multiple-trait.stderr
+++ b/tests/ui/methods/disambiguate-multiple-trait.stderr
@@ -1,10 +1,10 @@
 error[E0223]: ambiguous associated type
-  --> $DIR/disambiguate-multiple-trait.rs:32:12
+  --> $DIR/disambiguate-multiple-trait.rs:30:12
    |
 LL |     let _: S::Type;
    |            ^^^^^^^
    |
-help: use the fully-qualified path
+help: use fully-qualified syntax
    |
 LL |     let _: <S as A>::Type;
    |            ~~~~~~~~~~~~~~
@@ -27,17 +27,15 @@ note: candidate #2 is defined in an impl of the trait `B` for the type `T`
    |
 LL |     fn foo(&self) {}
    |     ^^^^^^^^^^^^^
-help: disambiguate the method for candidate #1
+help: use fully-qualified syntax to disambiguate
    |
 LL |     <T as A>::foo(&s);
    |     ~~~~~~~~~~
-help: disambiguate the method for candidate #2
-   |
 LL |     <T as B>::foo(&s);
    |     ~~~~~~~~~~
 
 error[E0034]: multiple applicable items in scope
-  --> $DIR/disambiguate-multiple-trait.rs:28:16
+  --> $DIR/disambiguate-multiple-trait.rs:27:16
    |
 LL |     let _ = S::CONST;
    |                ^^^^^ multiple `CONST` found
@@ -52,12 +50,10 @@ note: candidate #2 is defined in an impl of the trait `B` for the type `T`
    |
 LL |     const CONST: usize = 2;
    |     ^^^^^^^^^^^^^^^^^^
-help: disambiguate the associated constant for candidate #1
+help: use fully-qualified syntax to disambiguate
    |
 LL |     let _ = <T as A>::CONST;
    |             ~~~~~~~~~~
-help: disambiguate the associated constant for candidate #2
-   |
 LL |     let _ = <T as B>::CONST;
    |             ~~~~~~~~~~
 
diff --git a/tests/ui/methods/method-ambig-two-traits-from-impls2.stderr b/tests/ui/methods/method-ambig-two-traits-from-impls2.stderr
index 4ba778e0ef725..5bb887b4503a9 100644
--- a/tests/ui/methods/method-ambig-two-traits-from-impls2.stderr
+++ b/tests/ui/methods/method-ambig-two-traits-from-impls2.stderr
@@ -14,12 +14,10 @@ note: candidate #2 is defined in an impl of the trait `B` for the type `AB`
    |
 LL |     fn foo() {}
    |     ^^^^^^^^
-help: disambiguate the associated function for candidate #1
+help: use fully-qualified syntax to disambiguate
    |
 LL |     <AB as A>::foo();
    |     ~~~~~~~~~~~
-help: disambiguate the associated function for candidate #2
-   |
 LL |     <AB as B>::foo();
    |     ~~~~~~~~~~~
 
diff --git a/tests/ui/self/self-impl.stderr b/tests/ui/self/self-impl.stderr
index 36372b644d6e1..18ffd15427f81 100644
--- a/tests/ui/self/self-impl.stderr
+++ b/tests/ui/self/self-impl.stderr
@@ -2,13 +2,13 @@ error[E0223]: ambiguous associated type
   --> $DIR/self-impl.rs:23:16
    |
 LL |         let _: <Self>::Baz = true;
-   |                ^^^^^^^^^^^ help: use the fully-qualified path: `<Bar as Foo>::Baz`
+   |                ^^^^^^^^^^^ help: use fully-qualified syntax: `<Bar as Foo>::Baz`
 
 error[E0223]: ambiguous associated type
   --> $DIR/self-impl.rs:25:16
    |
 LL |         let _: Self::Baz = true;
-   |                ^^^^^^^^^ help: use the fully-qualified path: `<Bar as Foo>::Baz`
+   |                ^^^^^^^^^ help: use fully-qualified syntax: `<Bar as Foo>::Baz`
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/structs/struct-path-associated-type.stderr b/tests/ui/structs/struct-path-associated-type.stderr
index acfddaf37607d..0c9d2aad5d827 100644
--- a/tests/ui/structs/struct-path-associated-type.stderr
+++ b/tests/ui/structs/struct-path-associated-type.stderr
@@ -48,19 +48,19 @@ error[E0223]: ambiguous associated type
   --> $DIR/struct-path-associated-type.rs:32:13
    |
 LL |     let s = S::A {};
-   |             ^^^^ help: use the fully-qualified path: `<S as Tr>::A`
+   |             ^^^^ help: use fully-qualified syntax: `<S as Tr>::A`
 
 error[E0223]: ambiguous associated type
   --> $DIR/struct-path-associated-type.rs:33:13
    |
 LL |     let z = S::A::<u8> {};
-   |             ^^^^ help: use the fully-qualified path: `<S as Tr>::A`
+   |             ^^^^ help: use fully-qualified syntax: `<S as Tr>::A`
 
 error[E0223]: ambiguous associated type
   --> $DIR/struct-path-associated-type.rs:35:9
    |
 LL |         S::A {} => {}
-   |         ^^^^ help: use the fully-qualified path: `<S as Tr>::A`
+   |         ^^^^ help: use fully-qualified syntax: `<S as Tr>::A`
 
 error: aborting due to 8 previous errors
 
diff --git a/tests/ui/suggestions/suggest-trait-in-ufcs-in-hrtb.stderr b/tests/ui/suggestions/suggest-trait-in-ufcs-in-hrtb.stderr
index 0ca5b9b920790..0d1eed67c55e0 100644
--- a/tests/ui/suggestions/suggest-trait-in-ufcs-in-hrtb.stderr
+++ b/tests/ui/suggestions/suggest-trait-in-ufcs-in-hrtb.stderr
@@ -2,7 +2,7 @@ error[E0223]: ambiguous associated type
   --> $DIR/suggest-trait-in-ufcs-in-hrtb.rs:5:38
    |
 LL | impl<S> Foo for Bar<S> where for<'a> <&'a S>::Item: Foo {}
-   |                                      ^^^^^^^^^^^^^ help: use the fully-qualified path: `<&'a S as IntoIterator>::Item`
+   |                                      ^^^^^^^^^^^^^ help: use fully-qualified syntax: `<&'a S as IntoIterator>::Item`
 
 error: aborting due to previous error
 
diff --git a/tests/ui/traits/item-privacy.stderr b/tests/ui/traits/item-privacy.stderr
index f538131892546..af2e076321219 100644
--- a/tests/ui/traits/item-privacy.stderr
+++ b/tests/ui/traits/item-privacy.stderr
@@ -159,13 +159,13 @@ error[E0223]: ambiguous associated type
   --> $DIR/item-privacy.rs:116:12
    |
 LL |     let _: S::B;
-   |            ^^^^ help: use the fully-qualified path: `<S as assoc_ty::B>::B`
+   |            ^^^^ help: use fully-qualified syntax: `<S as assoc_ty::B>::B`
 
 error[E0223]: ambiguous associated type
   --> $DIR/item-privacy.rs:117:12
    |
 LL |     let _: S::C;
-   |            ^^^^ help: use the fully-qualified path: `<S as assoc_ty::C>::C`
+   |            ^^^^ help: use fully-qualified syntax: `<S as assoc_ty::C>::C`
 
 error[E0624]: associated type `A` is private
   --> $DIR/item-privacy.rs:119:12
diff --git a/tests/ui/typeck/issue-107087.stderr b/tests/ui/typeck/issue-107087.stderr
index 70f19320802b9..8921e3f7694d4 100644
--- a/tests/ui/typeck/issue-107087.stderr
+++ b/tests/ui/typeck/issue-107087.stderr
@@ -2,7 +2,7 @@ error[E0223]: ambiguous associated type
   --> $DIR/issue-107087.rs:16:5
    |
 LL |     A::B::<>::C
-   |     ^^^^^^^^ help: use the fully-qualified path: `<A<_> as Foo>::B`
+   |     ^^^^^^^^ help: use fully-qualified syntax: `<A<_> as Foo>::B`
 
 error: aborting due to previous error
 
diff --git a/tests/ui/typeck/issue-110052.stderr b/tests/ui/typeck/issue-110052.stderr
index 0c15c03a7408d..75374fa6121e6 100644
--- a/tests/ui/typeck/issue-110052.stderr
+++ b/tests/ui/typeck/issue-110052.stderr
@@ -2,7 +2,7 @@ error[E0223]: ambiguous associated type
   --> $DIR/issue-110052.rs:6:30
    |
 LL |     for<'iter> dyn Validator<<&'iter I>::Item>:,
-   |                              ^^^^^^^^^^^^^^^^ help: use the fully-qualified path: `<&'iter I as IntoIterator>::Item`
+   |                              ^^^^^^^^^^^^^^^^ help: use fully-qualified syntax: `<&'iter I as IntoIterator>::Item`
 
 error: aborting due to previous error