diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
index 11c893a7cb6..e156930cc89 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
@@ -609,7 +609,14 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
                 if !matches!(ty.kind(), ty::Infer(ty::InferTy::TyVar(_) | ty::InferTy::FreshTy(_)))
                 {
                     // don't show type `_`
-                    err.span_label(span, format!("this expression has type `{}`", ty));
+                    if span.desugaring_kind() == Some(DesugaringKind::ForLoop)
+                    && let ty::Adt(def, substs) = ty.kind()
+                    && Some(def.did()) == self.tcx.get_diagnostic_item(sym::Option)
+                    {
+                        err.span_label(span, format!("this is an iterator with items of type `{}`", substs.type_at(0)));
+                    } else {
+                        err.span_label(span, format!("this expression has type `{}`", ty));
+                    }
                 }
                 if let Some(ty::error::ExpectedFound { found, .. }) = exp_found
                     && ty.is_box() && ty.boxed_ty() == found
diff --git a/src/test/ui/pattern/for-loop-bad-item.rs b/src/test/ui/pattern/for-loop-bad-item.rs
new file mode 100644
index 00000000000..9a56a399b9b
--- /dev/null
+++ b/src/test/ui/pattern/for-loop-bad-item.rs
@@ -0,0 +1,20 @@
+struct Qux(i32);
+
+fn bad() {
+    let mut map = std::collections::HashMap::new();
+    map.insert(('a', 'b'), ('c', 'd'));
+
+    for ((_, _), (&mut c, _)) in &mut map {
+    //~^ ERROR mismatched types
+        if c == 'e' {}
+    }
+}
+
+fn bad2() {
+    for Some(Qux(_)) | None in [Some(""), None] {
+    //~^ ERROR mismatched types
+        todo!();
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/pattern/for-loop-bad-item.stderr b/src/test/ui/pattern/for-loop-bad-item.stderr
new file mode 100644
index 00000000000..9410e4da8d2
--- /dev/null
+++ b/src/test/ui/pattern/for-loop-bad-item.stderr
@@ -0,0 +1,23 @@
+error[E0308]: mismatched types
+  --> $DIR/for-loop-bad-item.rs:7:19
+   |
+LL |     for ((_, _), (&mut c, _)) in &mut map {
+   |                   ^^^^^^         -------- this is an iterator with items of type `(&(char, char), &mut (char, char))`
+   |                   |
+   |                   expected `char`, found `&mut _`
+   |                   help: you can probably remove the explicit borrow: `c`
+   |
+   = note:           expected type `char`
+           found mutable reference `&mut _`
+
+error[E0308]: mismatched types
+  --> $DIR/for-loop-bad-item.rs:14:14
+   |
+LL |     for Some(Qux(_)) | None in [Some(""), None] {
+   |              ^^^^^^            ---------------- this is an iterator with items of type `Option<&str>`
+   |              |
+   |              expected `str`, found struct `Qux`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.