From 7c88bda1cb9a454ebce2f84ce188e950272a12c0 Mon Sep 17 00:00:00 2001
From: Ashton Hunt <ashkernel02@gmail.com>
Date: Tue, 9 Jul 2024 17:21:31 -0600
Subject: [PATCH] E0191 suggestion correction, inserts turbofish without dyn
 (#91997)

---
 .../src/hir_ty_lowering/errors.rs             | 14 ++++++++++-
 .../dynless-turbofish-e0191-issue-91997.rs    |  8 +++++++
 ...dynless-turbofish-e0191-issue-91997.stderr | 23 +++++++++++++++++++
 tests/ui/issues/issue-23024.stderr            |  2 +-
 tests/ui/issues/issue-28344.stderr            |  4 ++--
 5 files changed, 47 insertions(+), 4 deletions(-)
 create mode 100644 tests/ui/errors/dynless-turbofish-e0191-issue-91997.rs
 create mode 100644 tests/ui/errors/dynless-turbofish-e0191-issue-91997.stderr

diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs
index 2d240699105d6..21613a98e219a 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs
@@ -12,9 +12,9 @@ use rustc_errors::MultiSpan;
 use rustc_errors::{
     codes::*, pluralize, struct_span_code_err, Applicability, Diag, ErrorGuaranteed,
 };
-use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::{DefId, LocalDefId};
+use rustc_hir::{self as hir, Node};
 use rustc_middle::bug;
 use rustc_middle::query::Key;
 use rustc_middle::ty::print::{PrintPolyTraitRefExt as _, PrintTraitRefExt as _};
@@ -745,7 +745,15 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
         if object_safety_violations {
             return;
         }
+
+        // related to issue #91997, turbofishes added only when in an expr or pat
+        let mut in_expr_or_pat = false;
         if let ([], [bound]) = (&potential_assoc_types[..], &trait_bounds) {
+            let grandparent = tcx.parent_hir_node(tcx.parent_hir_id(bound.trait_ref.hir_ref_id));
+            in_expr_or_pat = match grandparent {
+                Node::Expr(_) | Node::Pat(_) => true,
+                _ => false,
+            };
             match bound.trait_ref.path.segments {
                 // FIXME: `trait_ref.path.span` can point to a full path with multiple
                 // segments, even though `trait_ref.path.segments` is of length `1`. Work
@@ -901,6 +909,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                     // `Trait<'a, Item = Type>` while accounting for the `<'a>` in the
                     // suggestion.
                     format!("{}, {}>", &snippet[..snippet.len() - 1], types.join(", "))
+                } else if in_expr_or_pat {
+                    // The user wrote `Iterator`, so we don't have a type we can suggest, but at
+                    // least we can clue them to the correct syntax `Iterator::<Item = Type>`.
+                    format!("{}::<{}>", snippet, types.join(", "))
                 } else {
                     // The user wrote `Iterator`, so we don't have a type we can suggest, but at
                     // least we can clue them to the correct syntax `Iterator<Item = Type>`.
diff --git a/tests/ui/errors/dynless-turbofish-e0191-issue-91997.rs b/tests/ui/errors/dynless-turbofish-e0191-issue-91997.rs
new file mode 100644
index 0000000000000..69a4c13530bd3
--- /dev/null
+++ b/tests/ui/errors/dynless-turbofish-e0191-issue-91997.rs
@@ -0,0 +1,8 @@
+trait MyIterator : Iterator {}
+
+fn main() {
+    let _ = MyIterator::next;
+}
+//~^^ ERROR the value of the associated type `Item` in `Iterator` must be specified [E0191]
+//~| WARN trait objects without an explicit `dyn` are deprecated [bare_trait_objects]
+//~| WARN this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
diff --git a/tests/ui/errors/dynless-turbofish-e0191-issue-91997.stderr b/tests/ui/errors/dynless-turbofish-e0191-issue-91997.stderr
new file mode 100644
index 0000000000000..68d8adc5a4013
--- /dev/null
+++ b/tests/ui/errors/dynless-turbofish-e0191-issue-91997.stderr
@@ -0,0 +1,23 @@
+warning: trait objects without an explicit `dyn` are deprecated
+  --> $DIR/dynless-turbofish-e0191-issue-91997.rs:4:13
+   |
+LL |     let _ = MyIterator::next;
+   |             ^^^^^^^^^^
+   |
+   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
+   = note: `#[warn(bare_trait_objects)]` on by default
+help: if this is an object-safe trait, use `dyn`
+   |
+LL |     let _ = <dyn MyIterator>::next;
+   |             ++++           +
+
+error[E0191]: the value of the associated type `Item` in `Iterator` must be specified
+  --> $DIR/dynless-turbofish-e0191-issue-91997.rs:4:13
+   |
+LL |     let _ = MyIterator::next;
+   |             ^^^^^^^^^^ help: specify the associated type: `MyIterator::<Item = Type>`
+
+error: aborting due to 1 previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0191`.
diff --git a/tests/ui/issues/issue-23024.stderr b/tests/ui/issues/issue-23024.stderr
index 1672622d8b723..62278a51be635 100644
--- a/tests/ui/issues/issue-23024.stderr
+++ b/tests/ui/issues/issue-23024.stderr
@@ -23,7 +23,7 @@ error[E0191]: the value of the associated type `Output` in `FnOnce` must be spec
   --> $DIR/issue-23024.rs:8:39
    |
 LL |     println!("{:?}",(vfnfer[0] as dyn Fn)(3));
-   |                                       ^^ help: specify the associated type: `Fn<Output = Type>`
+   |                                       ^^ help: specify the associated type: `Fn::<Output = Type>`
 
 error: aborting due to 3 previous errors
 
diff --git a/tests/ui/issues/issue-28344.stderr b/tests/ui/issues/issue-28344.stderr
index d30fb3cfe58ab..b7e0790f67964 100644
--- a/tests/ui/issues/issue-28344.stderr
+++ b/tests/ui/issues/issue-28344.stderr
@@ -16,7 +16,7 @@ error[E0191]: the value of the associated type `Output` in `BitXor` must be spec
   --> $DIR/issue-28344.rs:4:17
    |
 LL |     let x: u8 = BitXor::bitor(0 as u8, 0 as u8);
-   |                 ^^^^^^ help: specify the associated type: `BitXor<Output = Type>`
+   |                 ^^^^^^ help: specify the associated type: `BitXor::<Output = Type>`
 
 error[E0599]: no function or associated item named `bitor` found for trait object `dyn BitXor<_>` in the current scope
   --> $DIR/issue-28344.rs:4:25
@@ -44,7 +44,7 @@ error[E0191]: the value of the associated type `Output` in `BitXor` must be spec
   --> $DIR/issue-28344.rs:10:13
    |
 LL |     let g = BitXor::bitor;
-   |             ^^^^^^ help: specify the associated type: `BitXor<Output = Type>`
+   |             ^^^^^^ help: specify the associated type: `BitXor::<Output = Type>`
 
 error[E0599]: no function or associated item named `bitor` found for trait object `dyn BitXor<_>` in the current scope
   --> $DIR/issue-28344.rs:10:21