about summary refs log tree commit diff
diff options
context:
space:
mode:
authorCameron Steffen <cam.steffen94@gmail.com>2021-10-25 23:33:12 -0500
committerCameron Steffen <cam.steffen94@gmail.com>2021-11-21 08:15:21 -0600
commit9c83f8c4d1e562cd73a29a00828d68e2b520a086 (patch)
treea7b824c188a775e1de44c0e9c44dffe2d039c78f
parent3bfde2f1f4fc9409ecb63dfe1370df66171cf861 (diff)
downloadrust-9c83f8c4d1e562cd73a29a00828d68e2b520a086.tar.gz
rust-9c83f8c4d1e562cd73a29a00828d68e2b520a086.zip
Simplify for loop desugar
-rw-r--r--compiler/rustc_ast_lowering/src/expr.rs137
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs13
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/mod.rs12
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs24
-rw-r--r--compiler/rustc_hir/src/hir.rs2
-rw-r--r--compiler/rustc_hir/src/pat_util.rs11
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs24
-rw-r--r--compiler/rustc_middle/src/lint.rs2
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/check_match.rs21
-rw-r--r--compiler/rustc_span/src/hygiene.rs11
-rw-r--r--compiler/rustc_span/src/lib.rs2
-rw-r--r--compiler/rustc_span/src/symbol.rs1
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs7
-rw-r--r--library/std/src/keyword_docs.rs5
-rw-r--r--src/test/incremental/hashes/for_loops.rs2
-rw-r--r--src/test/mir-opt/remove_storage_markers.main.RemoveStorageMarkers.diff115
-rw-r--r--src/test/ui/borrowck/return-local-binding-from-desugaring.rs2
-rw-r--r--src/test/ui/borrowck/return-local-binding-from-desugaring.stderr4
-rw-r--r--src/test/ui/for/for-loop-unconstrained-element-type.stderr6
-rw-r--r--src/test/ui/issues/issue-20261.stderr4
-rw-r--r--src/test/ui/issues/issue-33941.rs1
-rw-r--r--src/test/ui/issues/issue-33941.stderr12
-rw-r--r--src/test/ui/nll/dont-print-desugared.stderr2
-rw-r--r--src/test/ui/nll/issue-53773.stderr4
-rw-r--r--src/test/ui/reachable/unreachable-loop-patterns.rs1
-rw-r--r--src/test/ui/reachable/unreachable-loop-patterns.stderr8
26 files changed, 179 insertions, 254 deletions
diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs
index 405e9035c4c..a0a63620c08 100644
--- a/compiler/rustc_ast_lowering/src/expr.rs
+++ b/compiler/rustc_ast_lowering/src/expr.rs
@@ -13,7 +13,7 @@ use rustc_session::parse::feature_err;
 use rustc_span::hygiene::ExpnId;
 use rustc_span::source_map::{respan, DesugaringKind, Span, Spanned};
 use rustc_span::symbol::{sym, Ident, Symbol};
-use rustc_span::{hygiene::ForLoopLoc, DUMMY_SP};
+use rustc_span::DUMMY_SP;
 
 impl<'hir> LoweringContext<'_, 'hir> {
     fn lower_exprs(&mut self, exprs: &[AstP<Expr>]) -> &'hir [hir::Expr<'hir>] {
@@ -1308,16 +1308,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
     /// Desugar `ExprForLoop` from: `[opt_ident]: for <pat> in <head> <body>` into:
     /// ```rust
     /// {
-    ///     let result = match ::std::iter::IntoIterator::into_iter(<head>) {
+    ///     let result = match IntoIterator::into_iter(<head>) {
     ///         mut iter => {
     ///             [opt_ident]: loop {
-    ///                 let mut __next;
-    ///                 match ::std::iter::Iterator::next(&mut iter) {
-    ///                     ::std::option::Option::Some(val) => __next = val,
-    ///                     ::std::option::Option::None => break
+    ///                 match Iterator::next(&mut iter) {
+    ///                     None => break,
+    ///                     Some(<pat>) => <body>,
     ///                 };
-    ///                 let <pat> = __next;
-    ///                 StmtKind::Expr(<body>);
     ///             }
     ///         }
     ///     };
@@ -1332,133 +1329,75 @@ impl<'hir> LoweringContext<'_, 'hir> {
         body: &Block,
         opt_label: Option<Label>,
     ) -> hir::Expr<'hir> {
-        // expand <head>
         let head = self.lower_expr_mut(head);
-        let desugared_span =
-            self.mark_span_with_reason(DesugaringKind::ForLoop(ForLoopLoc::Head), head.span, None);
-        let e_span = self.lower_span(e.span);
-
-        let iter = Ident::with_dummy_span(sym::iter);
-
-        let next_ident = Ident::with_dummy_span(sym::__next);
-        let (next_pat, next_pat_hid) = self.pat_ident_binding_mode(
-            desugared_span,
-            next_ident,
-            hir::BindingAnnotation::Mutable,
-        );
-
-        // `::std::option::Option::Some(val) => __next = val`
-        let pat_arm = {
-            let val_ident = Ident::with_dummy_span(sym::val);
-            let pat_span = self.lower_span(pat.span);
-            let (val_pat, val_pat_hid) = self.pat_ident(pat_span, val_ident);
-            let val_expr = self.expr_ident(pat_span, val_ident, val_pat_hid);
-            let next_expr = self.expr_ident(pat_span, next_ident, next_pat_hid);
-            let assign = self.arena.alloc(self.expr(
-                pat_span,
-                hir::ExprKind::Assign(next_expr, val_expr, self.lower_span(pat_span)),
-                ThinVec::new(),
-            ));
-            let some_pat = self.pat_some(pat_span, val_pat);
-            self.arm(some_pat, assign)
-        };
+        let pat = self.lower_pat(pat);
+        let for_span =
+            self.mark_span_with_reason(DesugaringKind::ForLoop, self.lower_span(e.span), None);
+        let head_span = self.mark_span_with_reason(DesugaringKind::ForLoop, head.span, None);
+        let pat_span = self.mark_span_with_reason(DesugaringKind::ForLoop, pat.span, None);
 
-        // `::std::option::Option::None => break`
-        let break_arm = {
+        // `None => break`
+        let none_arm = {
             let break_expr =
-                self.with_loop_scope(e.id, |this| this.expr_break_alloc(e_span, ThinVec::new()));
-            let pat = self.pat_none(e_span);
+                self.with_loop_scope(e.id, |this| this.expr_break_alloc(for_span, ThinVec::new()));
+            let pat = self.pat_none(for_span);
             self.arm(pat, break_expr)
         };
 
+        // Some(<pat>) => <body>,
+        let some_arm = {
+            let some_pat = self.pat_some(pat_span, pat);
+            let body_block = self.with_loop_scope(e.id, |this| this.lower_block(body, false));
+            let body_expr = self.arena.alloc(self.expr_block(body_block, ThinVec::new()));
+            self.arm(some_pat, body_expr)
+        };
+
         // `mut iter`
+        let iter = Ident::with_dummy_span(sym::iter);
         let (iter_pat, iter_pat_nid) =
-            self.pat_ident_binding_mode(desugared_span, iter, hir::BindingAnnotation::Mutable);
+            self.pat_ident_binding_mode(head_span, iter, hir::BindingAnnotation::Mutable);
 
-        // `match ::std::iter::Iterator::next(&mut iter) { ... }`
+        // `match Iterator::next(&mut iter) { ... }`
         let match_expr = {
-            let iter = self.expr_ident(desugared_span, iter, iter_pat_nid);
-            let ref_mut_iter = self.expr_mut_addr_of(desugared_span, iter);
+            let iter = self.expr_ident(head_span, iter, iter_pat_nid);
+            let ref_mut_iter = self.expr_mut_addr_of(head_span, iter);
             let next_expr = self.expr_call_lang_item_fn(
-                desugared_span,
+                head_span,
                 hir::LangItem::IteratorNext,
                 arena_vec![self; ref_mut_iter],
             );
-            let arms = arena_vec![self; pat_arm, break_arm];
+            let arms = arena_vec![self; none_arm, some_arm];
 
-            self.expr_match(desugared_span, next_expr, arms, hir::MatchSource::ForLoopDesugar)
+            self.expr_match(head_span, next_expr, arms, hir::MatchSource::ForLoopDesugar)
         };
-        let match_stmt = self.stmt_expr(desugared_span, match_expr);
-
-        let next_expr = self.expr_ident(desugared_span, next_ident, next_pat_hid);
-
-        // `let mut __next`
-        let next_let = self.stmt_let_pat(
-            None,
-            desugared_span,
-            None,
-            next_pat,
-            hir::LocalSource::ForLoopDesugar,
-        );
+        let match_stmt = self.stmt_expr(for_span, match_expr);
 
-        // `let <pat> = __next`
-        let pat = self.lower_pat(pat);
-        let pat_let = self.stmt_let_pat(
-            None,
-            desugared_span,
-            Some(next_expr),
-            pat,
-            hir::LocalSource::ForLoopDesugar,
-        );
-
-        let body_block = self.with_loop_scope(e.id, |this| this.lower_block(body, false));
-        let body_expr = self.expr_block(body_block, ThinVec::new());
-        let body_stmt = self.stmt_expr(body_block.span, body_expr);
-
-        let loop_block = self.block_all(
-            e_span,
-            arena_vec![self; next_let, match_stmt, pat_let, body_stmt],
-            None,
-        );
+        let loop_block = self.block_all(for_span, arena_vec![self; match_stmt], None);
 
         // `[opt_ident]: loop { ... }`
         let kind = hir::ExprKind::Loop(
             loop_block,
             self.lower_label(opt_label),
             hir::LoopSource::ForLoop,
-            self.lower_span(e_span.with_hi(head.span.hi())),
+            self.lower_span(for_span.with_hi(head.span.hi())),
         );
-        let loop_expr = self.arena.alloc(hir::Expr {
-            hir_id: self.lower_node_id(e.id),
-            kind,
-            span: self.lower_span(e.span),
-        });
+        let loop_expr =
+            self.arena.alloc(hir::Expr { hir_id: self.lower_node_id(e.id), kind, span: for_span });
 
         // `mut iter => { ... }`
         let iter_arm = self.arm(iter_pat, loop_expr);
 
-        let into_iter_span = self.mark_span_with_reason(
-            DesugaringKind::ForLoop(ForLoopLoc::IntoIter),
-            head.span,
-            None,
-        );
-
         // `match ::std::iter::IntoIterator::into_iter(<head>) { ... }`
         let into_iter_expr = {
             self.expr_call_lang_item_fn(
-                into_iter_span,
+                head_span,
                 hir::LangItem::IntoIterIntoIter,
                 arena_vec![self; head],
             )
         };
 
-        // #82462: to correctly diagnose borrow errors, the block that contains
-        // the iter expr needs to have a span that covers the loop body.
-        let desugared_full_span =
-            self.mark_span_with_reason(DesugaringKind::ForLoop(ForLoopLoc::Head), e_span, None);
-
         let match_expr = self.arena.alloc(self.expr_match(
-            desugared_full_span,
+            for_span,
             into_iter_expr,
             arena_vec![self; iter_arm],
             hir::MatchSource::ForLoopDesugar,
@@ -1472,7 +1411,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
         // surrounding scope of the `match` since the `match` is not a terminating scope.
         //
         // Also, add the attributes to the outer returned expr node.
-        self.expr_drop_temps_mut(desugared_full_span, match_expr, attrs.into())
+        self.expr_drop_temps_mut(for_span, match_expr, attrs.into())
     }
 
     /// Desugar `ExprKind::Try` from: `<expr>?` into:
diff --git a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
index 79973ab170c..db8268c8e2e 100644
--- a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
@@ -13,7 +13,7 @@ use rustc_middle::mir::{
 use rustc_middle::ty::adjustment::PointerCast;
 use rustc_middle::ty::{self, RegionVid, TyCtxt};
 use rustc_span::symbol::Symbol;
-use rustc_span::Span;
+use rustc_span::{sym, DesugaringKind, Span};
 
 use crate::region_infer::BlameConstraint;
 use crate::{
@@ -135,7 +135,16 @@ impl BorrowExplanation {
                 should_note_order,
             } => {
                 let local_decl = &body.local_decls[dropped_local];
-                let (dtor_desc, type_desc) = match local_decl.ty.kind() {
+                let mut ty = local_decl.ty;
+                if local_decl.source_info.span.desugaring_kind() == Some(DesugaringKind::ForLoop) {
+                    if let ty::Adt(adt, substs) = local_decl.ty.kind() {
+                        if tcx.is_diagnostic_item(sym::Option, adt.did) {
+                            // in for loop desugaring, only look at the `Some(..)` inner type
+                            ty = substs.type_at(0);
+                        }
+                    }
+                }
+                let (dtor_desc, type_desc) = match ty.kind() {
                     // If type is an ADT that implements Drop, then
                     // simplify output by reporting just the ADT name.
                     ty::Adt(adt, _substs) if adt.has_dtor(tcx) && !adt.is_box() => {
diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs
index a4df277a7b0..79623e26eb7 100644
--- a/compiler/rustc_borrowck/src/diagnostics/mod.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs
@@ -13,11 +13,7 @@ use rustc_middle::mir::{
 use rustc_middle::ty::print::Print;
 use rustc_middle::ty::{self, DefIdTree, Instance, Ty, TyCtxt};
 use rustc_mir_dataflow::move_paths::{InitLocation, LookupResult};
-use rustc_span::{
-    hygiene::{DesugaringKind, ForLoopLoc},
-    symbol::sym,
-    Span,
-};
+use rustc_span::{hygiene::DesugaringKind, symbol::sym, Span};
 use rustc_target::abi::VariantIdx;
 
 use super::borrow_set::BorrowData;
@@ -955,10 +951,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
             let kind = kind.unwrap_or_else(|| {
                 // This isn't a 'special' use of `self`
                 debug!("move_spans: method_did={:?}, fn_call_span={:?}", method_did, fn_call_span);
-                let implicit_into_iter = matches!(
-                    fn_call_span.desugaring_kind(),
-                    Some(DesugaringKind::ForLoop(ForLoopLoc::IntoIter))
-                );
+                let implicit_into_iter = Some(method_did) == tcx.lang_items().into_iter_fn()
+                    && fn_call_span.desugaring_kind() == Some(DesugaringKind::ForLoop);
                 let parent_self_ty = parent
                     .filter(|did| tcx.def_kind(*did) == rustc_hir::def::DefKind::Impl)
                     .and_then(|did| match tcx.type_of(did).kind() {
diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
index d5ff4c6766f..46e2a99a0d0 100644
--- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
@@ -445,15 +445,23 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
                                 },
                             ))) => {
                                 // check if the RHS is from desugaring
-                                let locations = self.body.find_assignments(local);
-                                let opt_assignment_rhs_span = locations
-                                    .first()
-                                    .map(|&location| self.body.source_info(location).span);
-                                let opt_desugaring_kind =
-                                    opt_assignment_rhs_span.and_then(|span| span.desugaring_kind());
-                                match opt_desugaring_kind {
+                                let opt_assignment_rhs_span =
+                                    self.body.find_assignments(local).first().map(|&location| {
+                                        let stmt = &self.body[location.block].statements
+                                            [location.statement_index];
+                                        match stmt.kind {
+                                            mir::StatementKind::Assign(box (
+                                                _,
+                                                mir::Rvalue::Use(mir::Operand::Copy(place)),
+                                            )) => {
+                                                self.body.local_decls[place.local].source_info.span
+                                            }
+                                            _ => self.body.source_info(location).span,
+                                        }
+                                    });
+                                match opt_assignment_rhs_span.and_then(|s| s.desugaring_kind()) {
                                     // on for loops, RHS points to the iterator part
-                                    Some(DesugaringKind::ForLoop(_)) => {
+                                    Some(DesugaringKind::ForLoop) => {
                                         self.suggest_similar_mut_method_for_for_loop(&mut err);
                                         Some((
                                             false,
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index a4db57bfc11..c67d3df3ded 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -1821,8 +1821,6 @@ impl<'hir> QPath<'hir> {
 pub enum LocalSource {
     /// A `match _ { .. }`.
     Normal,
-    /// A desugared `for _ in _ { .. }` loop.
-    ForLoopDesugar,
     /// When lowering async functions, we create locals within the `async move` so that
     /// all parameters are dropped after the future is polled.
     ///
diff --git a/compiler/rustc_hir/src/pat_util.rs b/compiler/rustc_hir/src/pat_util.rs
index b1f78a83e74..b30076100bb 100644
--- a/compiler/rustc_hir/src/pat_util.rs
+++ b/compiler/rustc_hir/src/pat_util.rs
@@ -2,6 +2,7 @@ use crate::def::{CtorOf, DefKind, Res};
 use crate::def_id::DefId;
 use crate::hir::{self, HirId, PatKind};
 use rustc_data_structures::stable_set::FxHashSet;
+use rustc_span::hygiene::DesugaringKind;
 use rustc_span::symbol::Ident;
 use rustc_span::Span;
 
@@ -143,4 +144,14 @@ impl hir::Pat<'_> {
         });
         result
     }
+
+    /// If the pattern is `Some(<pat>)` from a desugared for loop, returns the inner pattern
+    pub fn for_loop_some(&self) -> Option<&Self> {
+        if self.span.desugaring_kind() == Some(DesugaringKind::ForLoop) {
+            if let hir::PatKind::Struct(_, [pat_field], _) = self.kind {
+                return Some(pat_field.pat);
+            }
+        }
+        None
+    }
 }
diff --git a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs
index e00003face9..a7e019a53ee 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs
@@ -5,13 +5,12 @@ use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Namespace};
 use rustc_hir::def_id::DefId;
 use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
-use rustc_hir::{Body, Expr, ExprKind, FnRetTy, HirId, Local, Pat};
+use rustc_hir::{Body, Expr, ExprKind, FnRetTy, HirId, Local, MatchSource, Pat};
 use rustc_middle::hir::map::Map;
 use rustc_middle::infer::unify_key::ConstVariableOriginKind;
 use rustc_middle::ty::print::Print;
 use rustc_middle::ty::subst::{GenericArg, GenericArgKind};
 use rustc_middle::ty::{self, DefIdTree, InferConst, Ty, TyCtxt};
-use rustc_span::source_map::DesugaringKind;
 use rustc_span::symbol::kw;
 use rustc_span::Span;
 use std::borrow::Cow;
@@ -26,6 +25,7 @@ struct FindHirNodeVisitor<'a, 'tcx> {
     found_closure: Option<&'tcx Expr<'tcx>>,
     found_method_call: Option<&'tcx Expr<'tcx>>,
     found_exact_method_call: Option<&'tcx Expr<'tcx>>,
+    found_for_loop_iter: Option<&'tcx Expr<'tcx>>,
     found_use_diagnostic: Option<UseDiagnostic<'tcx>>,
 }
 
@@ -41,6 +41,7 @@ impl<'a, 'tcx> FindHirNodeVisitor<'a, 'tcx> {
             found_closure: None,
             found_method_call: None,
             found_exact_method_call: None,
+            found_for_loop_iter: None,
             found_use_diagnostic: None,
         }
     }
@@ -111,6 +112,15 @@ impl<'a, 'tcx> Visitor<'tcx> for FindHirNodeVisitor<'a, 'tcx> {
     }
 
     fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) {
+        if let ExprKind::Match(scrutinee, [_, arm], MatchSource::ForLoopDesugar) = expr.kind {
+            if let Some(pat) = arm.pat.for_loop_some() {
+                if let Some(ty) = self.node_ty_contains_target(pat.hir_id) {
+                    self.found_for_loop_iter = Some(scrutinee);
+                    self.found_node_ty = Some(ty);
+                    return;
+                }
+            }
+        }
         if let ExprKind::MethodCall(_, call_span, exprs, _) = expr.kind {
             if call_span == self.target_span
                 && Some(self.target)
@@ -643,10 +653,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
             let msg = if let Some(simple_ident) = pattern.simple_ident() {
                 match pattern.span.desugaring_kind() {
                     None => format!("consider giving `{}` {}", simple_ident, suffix),
-                    Some(DesugaringKind::ForLoop(_)) => {
-                        "the element type for this iterator is not specified".to_string()
-                    }
-                    _ => format!("this needs {}", suffix),
+                    Some(_) => format!("this needs {}", suffix),
                 }
             } else {
                 format!("consider giving this pattern {}", suffix)
@@ -719,6 +726,11 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
                 //    = note: type must be known at this point
                 self.annotate_method_call(segment, e, &mut err);
             }
+        } else if let Some(scrutinee) = local_visitor.found_for_loop_iter {
+            err.span_label(
+                scrutinee.span,
+                "the element type for this iterator is not specified".to_string(),
+            );
         }
         // Instead of the following:
         // error[E0282]: type annotations needed
diff --git a/compiler/rustc_middle/src/lint.rs b/compiler/rustc_middle/src/lint.rs
index 0e70d49ef49..881b14278e9 100644
--- a/compiler/rustc_middle/src/lint.rs
+++ b/compiler/rustc_middle/src/lint.rs
@@ -395,7 +395,7 @@ pub fn in_external_macro(sess: &Session, span: Span) -> bool {
     match expn_data.kind {
         ExpnKind::Inlined
         | ExpnKind::Root
-        | ExpnKind::Desugaring(DesugaringKind::ForLoop(_) | DesugaringKind::WhileLoop) => false,
+        | ExpnKind::Desugaring(DesugaringKind::ForLoop | DesugaringKind::WhileLoop) => false,
         ExpnKind::AstPass(_) | ExpnKind::Desugaring(_) => true, // well, it's "external"
         ExpnKind::Macro(MacroKind::Bang, _) => {
             // Dummy span for the `def_site` means it's an external macro.
diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
index e28fd2c5081..d74c53fae53 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
@@ -74,19 +74,16 @@ impl<'tcx> Visitor<'tcx> for MatchVisitor<'_, '_, 'tcx> {
 
         let (msg, sp) = match loc.source {
             hir::LocalSource::Normal => ("local binding", Some(loc.span)),
-            hir::LocalSource::ForLoopDesugar => ("`for` loop binding", None),
             hir::LocalSource::AsyncFn => ("async fn binding", None),
             hir::LocalSource::AwaitDesugar => ("`await` future binding", None),
             hir::LocalSource::AssignDesugar(_) => ("destructuring assignment binding", None),
         };
         self.check_irrefutable(&loc.pat, msg, sp);
-        self.check_patterns(&loc.pat, Irrefutable);
     }
 
     fn visit_param(&mut self, param: &'tcx hir::Param<'tcx>) {
         intravisit::walk_param(self, param);
         self.check_irrefutable(&param.pat, "function argument", None);
-        self.check_patterns(&param.pat, Irrefutable);
     }
 }
 
@@ -161,12 +158,12 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> {
     fn check_match(
         &mut self,
         scrut: &hir::Expr<'_>,
-        arms: &'tcx [hir::Arm<'tcx>],
+        hir_arms: &'tcx [hir::Arm<'tcx>],
         source: hir::MatchSource,
     ) {
         let mut cx = self.new_cx(scrut.hir_id);
 
-        for arm in arms {
+        for arm in hir_arms {
             // Check the arm for some things unrelated to exhaustiveness.
             self.check_patterns(&arm.pat, Refutable);
             if let Some(hir::Guard::IfLet(ref pat, _)) = arm.guard {
@@ -178,7 +175,7 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> {
 
         let mut have_errors = false;
 
-        let arms: Vec<_> = arms
+        let arms: Vec<_> = hir_arms
             .iter()
             .map(|hir::Arm { pat, guard, .. }| MatchArm {
                 pat: self.lower_pattern(&mut cx, pat, &mut have_errors),
@@ -196,6 +193,9 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> {
         let report = compute_match_usefulness(&cx, &arms, scrut.hir_id, scrut_ty);
 
         match source {
+            // Don't report arm reachability of desugared `match $iter.into_iter() { iter => .. }`
+            // when the iterator is an uninhabited type. unreachable_code will trigger instead.
+            hir::MatchSource::ForLoopDesugar if arms.len() == 1 => {}
             hir::MatchSource::ForLoopDesugar | hir::MatchSource::Normal => {
                 report_arm_reachability(&cx, &report)
             }
@@ -208,7 +208,13 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> {
         let is_empty_match = arms.is_empty();
         let witnesses = report.non_exhaustiveness_witnesses;
         if !witnesses.is_empty() {
-            non_exhaustive_match(&cx, scrut_ty, scrut.span, witnesses, is_empty_match);
+            if source == hir::MatchSource::ForLoopDesugar && hir_arms.len() == 2 {
+                // the for loop pattern is not irrefutable
+                let pat = hir_arms[1].pat.for_loop_some().unwrap();
+                self.check_irrefutable(pat, "`for` loop binding", None);
+            } else {
+                non_exhaustive_match(&cx, scrut_ty, scrut.span, witnesses, is_empty_match);
+            }
         }
     }
 
@@ -225,6 +231,7 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> {
         let witnesses = report.non_exhaustiveness_witnesses;
         if witnesses.is_empty() {
             // The pattern is irrefutable.
+            self.check_patterns(pat, Irrefutable);
             return;
         }
 
diff --git a/compiler/rustc_span/src/hygiene.rs b/compiler/rustc_span/src/hygiene.rs
index 724d1904dc3..d590776676b 100644
--- a/compiler/rustc_span/src/hygiene.rs
+++ b/compiler/rustc_span/src/hygiene.rs
@@ -1099,18 +1099,11 @@ pub enum DesugaringKind {
     OpaqueTy,
     Async,
     Await,
-    ForLoop(ForLoopLoc),
+    ForLoop,
     LetElse,
     WhileLoop,
 }
 
-/// A location in the desugaring of a `for` loop
-#[derive(Clone, Copy, PartialEq, Debug, Encodable, Decodable, HashStable_Generic)]
-pub enum ForLoopLoc {
-    Head,
-    IntoIter,
-}
-
 impl DesugaringKind {
     /// The description wording should combine well with "desugaring of {}".
     pub fn descr(self) -> &'static str {
@@ -1121,7 +1114,7 @@ impl DesugaringKind {
             DesugaringKind::QuestionMark => "operator `?`",
             DesugaringKind::TryBlock => "`try` block",
             DesugaringKind::OpaqueTy => "`impl Trait`",
-            DesugaringKind::ForLoop(_) => "`for` loop",
+            DesugaringKind::ForLoop => "`for` loop",
             DesugaringKind::LetElse => "`let...else`",
             DesugaringKind::WhileLoop => "`while` loop",
         }
diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs
index 1445c59710c..66c01140abc 100644
--- a/compiler/rustc_span/src/lib.rs
+++ b/compiler/rustc_span/src/lib.rs
@@ -41,7 +41,7 @@ pub mod edition;
 use edition::Edition;
 pub mod hygiene;
 use hygiene::Transparency;
-pub use hygiene::{DesugaringKind, ExpnKind, ForLoopLoc, MacroKind};
+pub use hygiene::{DesugaringKind, ExpnKind, MacroKind};
 pub use hygiene::{ExpnData, ExpnHash, ExpnId, LocalExpnId, SyntaxContext};
 pub mod def_id;
 use def_id::{CrateNum, DefId, DefPathHash, LocalDefId, LOCAL_CRATE};
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 9992b1f31fe..0d556b5eda6 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -269,7 +269,6 @@ symbols! {
         __D,
         __H,
         __S,
-        __next,
         __try_var,
         _args,
         _d,
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
index d5c7cf71116..a90140a9b50 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
@@ -27,7 +27,7 @@ use rustc_middle::ty::{TypeAndMut, TypeckResults};
 use rustc_session::Limit;
 use rustc_span::def_id::LOCAL_CRATE;
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
-use rustc_span::{BytePos, DesugaringKind, ExpnKind, ForLoopLoc, MultiSpan, Span, DUMMY_SP};
+use rustc_span::{BytePos, DesugaringKind, ExpnKind, MultiSpan, Span, DUMMY_SP};
 use rustc_target::spec::abi;
 use std::fmt;
 
@@ -685,7 +685,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
             &obligation.cause.code
         {
             parent_code.clone()
-        } else if let ExpnKind::Desugaring(DesugaringKind::ForLoop(ForLoopLoc::IntoIter)) =
+        } else if let ExpnKind::Desugaring(DesugaringKind::ForLoop) =
             span.ctxt().outer_expn_data().kind
         {
             Lrc::new(obligation.cause.code.clone())
@@ -765,8 +765,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
                     // This if is to prevent a special edge-case
                     if matches!(
                         span.ctxt().outer_expn_data().kind,
-                        ExpnKind::Root
-                            | ExpnKind::Desugaring(DesugaringKind::ForLoop(ForLoopLoc::IntoIter))
+                        ExpnKind::Root | ExpnKind::Desugaring(DesugaringKind::ForLoop)
                     ) {
                         // We don't want a borrowing suggestion on the fields in structs,
                         // ```
diff --git a/library/std/src/keyword_docs.rs b/library/std/src/keyword_docs.rs
index a8365071d61..a370485102e 100644
--- a/library/std/src/keyword_docs.rs
+++ b/library/std/src/keyword_docs.rs
@@ -549,13 +549,10 @@ mod fn_keyword {}
 /// {
 ///     let result = match IntoIterator::into_iter(iterator) {
 ///         mut iter => loop {
-///             let next;
 ///             match iter.next() {
-///                 Some(val) => next = val,
 ///                 None => break,
+///                 Some(loop_variable) => { code(); },
 ///             };
-///             let loop_variable = next;
-///             let () = { code(); };
 ///         },
 ///     };
 ///     result
diff --git a/src/test/incremental/hashes/for_loops.rs b/src/test/incremental/hashes/for_loops.rs
index 1b96cd54c3e..d3687d5b908 100644
--- a/src/test/incremental/hashes/for_loops.rs
+++ b/src/test/incremental/hashes/for_loops.rs
@@ -183,7 +183,7 @@ pub fn add_loop_label_to_break() {
 #[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
 #[rustc_clean(cfg="cfail3")]
-#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")]
 #[rustc_clean(cfg="cfail6")]
 pub fn add_loop_label_to_break() {
     let mut _x = 0;
diff --git a/src/test/mir-opt/remove_storage_markers.main.RemoveStorageMarkers.diff b/src/test/mir-opt/remove_storage_markers.main.RemoveStorageMarkers.diff
index 02f6e55a9a8..2dfc94f2186 100644
--- a/src/test/mir-opt/remove_storage_markers.main.RemoveStorageMarkers.diff
+++ b/src/test/mir-opt/remove_storage_markers.main.RemoveStorageMarkers.diff
@@ -7,39 +7,29 @@
       let mut _2: std::ops::Range<i32>;    // in scope 0 at $DIR/remove_storage_markers.rs:8:14: 8:19
       let mut _3: std::ops::Range<i32>;    // in scope 0 at $DIR/remove_storage_markers.rs:8:14: 8:19
       let mut _5: ();                      // in scope 0 at $DIR/remove_storage_markers.rs:6:1: 11:2
-      let _7: ();                          // in scope 0 at $DIR/remove_storage_markers.rs:8:14: 8:19
-      let mut _8: std::option::Option<i32>; // in scope 0 at $DIR/remove_storage_markers.rs:8:14: 8:19
+      let _6: ();                          // in scope 0 at $DIR/remove_storage_markers.rs:8:14: 8:19
+      let mut _7: std::option::Option<i32>; // in scope 0 at $DIR/remove_storage_markers.rs:8:14: 8:19
+      let mut _8: &mut std::ops::Range<i32>; // in scope 0 at $DIR/remove_storage_markers.rs:8:14: 8:19
       let mut _9: &mut std::ops::Range<i32>; // in scope 0 at $DIR/remove_storage_markers.rs:8:14: 8:19
-      let mut _10: &mut std::ops::Range<i32>; // in scope 0 at $DIR/remove_storage_markers.rs:8:14: 8:19
-      let mut _11: isize;                  // in scope 0 at $DIR/remove_storage_markers.rs:8:9: 8:10
-      let mut _13: i32;                    // in scope 0 at $DIR/remove_storage_markers.rs:8:9: 8:10
-      let mut _14: !;                      // in scope 0 at $DIR/remove_storage_markers.rs:8:5: 10:6
-      let _16: ();                         // in scope 0 at $DIR/remove_storage_markers.rs:8:20: 10:6
-      let mut _17: i32;                    // in scope 0 at $DIR/remove_storage_markers.rs:9:16: 9:17
+      let mut _10: isize;                  // in scope 0 at $DIR/remove_storage_markers.rs:8:5: 10:6
+      let mut _11: !;                      // in scope 0 at $DIR/remove_storage_markers.rs:8:5: 10:6
+      let mut _13: i32;                    // in scope 0 at $DIR/remove_storage_markers.rs:9:16: 9:17
       scope 1 {
           debug sum => _1;                 // in scope 1 at $DIR/remove_storage_markers.rs:7:9: 7:16
           let mut _4: std::ops::Range<i32>; // in scope 1 at $DIR/remove_storage_markers.rs:8:14: 8:19
           scope 2 {
               debug iter => _4;            // in scope 2 at $DIR/remove_storage_markers.rs:8:14: 8:19
-              let mut _6: i32;             // in scope 2 at $DIR/remove_storage_markers.rs:8:14: 8:19
+              let _12: i32;                // in scope 2 at $DIR/remove_storage_markers.rs:8:9: 8:10
               scope 3 {
-                  debug __next => _6;      // in scope 3 at $DIR/remove_storage_markers.rs:8:14: 8:19
-                  let _12: i32;            // in scope 3 at $DIR/remove_storage_markers.rs:8:9: 8:10
-                  let _15: i32;            // in scope 3 at $DIR/remove_storage_markers.rs:8:9: 8:10
-                  scope 4 {
-                      debug val => _12;    // in scope 4 at $DIR/remove_storage_markers.rs:8:9: 8:10
-                  }
-                  scope 5 {
-                      debug i => _15;      // in scope 5 at $DIR/remove_storage_markers.rs:8:9: 8:10
-                  }
-                  scope 7 (inlined iter::range::<impl Iterator for std::ops::Range<i32>>::next) { // at $DIR/remove_storage_markers.rs:8:14: 8:19
-                      debug self => _9;    // in scope 7 at $DIR/remove_storage_markers.rs:8:14: 8:19
-                      let mut _18: &mut std::ops::Range<i32>; // in scope 7 at $DIR/remove_storage_markers.rs:8:14: 8:19
-                  }
+                  debug i => _12;          // in scope 3 at $DIR/remove_storage_markers.rs:8:9: 8:10
+              }
+              scope 5 (inlined iter::range::<impl Iterator for std::ops::Range<i32>>::next) { // at $DIR/remove_storage_markers.rs:8:14: 8:19
+                  debug self => _8;        // in scope 5 at $DIR/remove_storage_markers.rs:8:14: 8:19
+                  let mut _14: &mut std::ops::Range<i32>; // in scope 5 at $DIR/remove_storage_markers.rs:8:14: 8:19
               }
           }
-          scope 6 (inlined <std::ops::Range<i32> as IntoIterator>::into_iter) { // at $DIR/remove_storage_markers.rs:8:14: 8:19
-              debug self => _3;            // in scope 6 at $DIR/remove_storage_markers.rs:8:14: 8:19
+          scope 4 (inlined <std::ops::Range<i32> as IntoIterator>::into_iter) { // at $DIR/remove_storage_markers.rs:8:14: 8:19
+              debug self => _3;            // in scope 4 at $DIR/remove_storage_markers.rs:8:14: 8:19
           }
       }
   
@@ -50,7 +40,7 @@
 -         StorageLive(_3);                 // scope 1 at $DIR/remove_storage_markers.rs:8:14: 8:19
           (_3.0: i32) = const 0_i32;       // scope 1 at $DIR/remove_storage_markers.rs:8:14: 8:19
           (_3.1: i32) = const 10_i32;      // scope 1 at $DIR/remove_storage_markers.rs:8:14: 8:19
-          _2 = move _3;                    // scope 6 at $DIR/remove_storage_markers.rs:8:14: 8:19
+          _2 = move _3;                    // scope 4 at $DIR/remove_storage_markers.rs:8:14: 8:19
 -         StorageDead(_3);                 // scope 1 at $DIR/remove_storage_markers.rs:8:18: 8:19
 -         StorageLive(_4);                 // scope 1 at $DIR/remove_storage_markers.rs:8:14: 8:19
           _4 = move _2;                    // scope 1 at $DIR/remove_storage_markers.rs:8:14: 8:19
@@ -59,64 +49,51 @@
   
       bb1: {
 -         StorageLive(_6);                 // scope 2 at $DIR/remove_storage_markers.rs:8:14: 8:19
--         StorageLive(_7);                 // scope 3 at $DIR/remove_storage_markers.rs:8:14: 8:19
--         StorageLive(_8);                 // scope 3 at $DIR/remove_storage_markers.rs:8:14: 8:19
--         StorageLive(_9);                 // scope 3 at $DIR/remove_storage_markers.rs:8:14: 8:19
--         StorageLive(_10);                // scope 3 at $DIR/remove_storage_markers.rs:8:14: 8:19
-          _10 = &mut _4;                   // scope 3 at $DIR/remove_storage_markers.rs:8:14: 8:19
-          _9 = &mut (*_10);                // scope 3 at $DIR/remove_storage_markers.rs:8:14: 8:19
--         StorageLive(_18);                // scope 7 at $DIR/remove_storage_markers.rs:8:14: 8:19
-          _18 = &mut (*_9);                // scope 7 at $DIR/remove_storage_markers.rs:8:14: 8:19
-          _8 = <std::ops::Range<i32> as iter::range::RangeIteratorImpl>::spec_next(move _18) -> bb4; // scope 7 at $DIR/remove_storage_markers.rs:8:14: 8:19
+-         StorageLive(_7);                 // scope 2 at $DIR/remove_storage_markers.rs:8:14: 8:19
+-         StorageLive(_8);                 // scope 2 at $DIR/remove_storage_markers.rs:8:14: 8:19
+-         StorageLive(_9);                 // scope 2 at $DIR/remove_storage_markers.rs:8:14: 8:19
+          _9 = &mut _4;                    // scope 2 at $DIR/remove_storage_markers.rs:8:14: 8:19
+          _8 = &mut (*_9);                 // scope 2 at $DIR/remove_storage_markers.rs:8:14: 8:19
+-         StorageLive(_14);                // scope 5 at $DIR/remove_storage_markers.rs:8:14: 8:19
+          _14 = &mut (*_8);                // scope 5 at $DIR/remove_storage_markers.rs:8:14: 8:19
+          _7 = <std::ops::Range<i32> as iter::range::RangeIteratorImpl>::spec_next(move _14) -> bb4; // scope 5 at $DIR/remove_storage_markers.rs:8:14: 8:19
                                            // mir::Constant
                                            // + span: $DIR/remove_storage_markers.rs:8:14: 8:19
                                            // + literal: Const { ty: for<'r> fn(&'r mut std::ops::Range<i32>) -> std::option::Option<<std::ops::Range<i32> as std::iter::range::RangeIteratorImpl>::Item> {<std::ops::Range<i32> as std::iter::range::RangeIteratorImpl>::spec_next}, val: Value(Scalar(<ZST>)) }
       }
   
       bb2: {
-          _0 = const ();                   // scope 3 at $DIR/remove_storage_markers.rs:8:5: 10:6
--         StorageDead(_10);                // scope 3 at $DIR/remove_storage_markers.rs:8:18: 8:19
--         StorageDead(_8);                 // scope 3 at $DIR/remove_storage_markers.rs:8:18: 8:19
--         StorageDead(_7);                 // scope 3 at $DIR/remove_storage_markers.rs:8:18: 8:19
+-         StorageLive(_12);                // scope 2 at $DIR/remove_storage_markers.rs:8:9: 8:10
+          _12 = ((_7 as Some).0: i32);     // scope 2 at $DIR/remove_storage_markers.rs:8:9: 8:10
+-         StorageLive(_13);                // scope 3 at $DIR/remove_storage_markers.rs:9:16: 9:17
+          _13 = _12;                       // scope 3 at $DIR/remove_storage_markers.rs:9:16: 9:17
+          _1 = Add(_1, move _13);          // scope 3 at $DIR/remove_storage_markers.rs:9:9: 9:17
+-         StorageDead(_13);                // scope 3 at $DIR/remove_storage_markers.rs:9:16: 9:17
+          _6 = const ();                   // scope 3 at $DIR/remove_storage_markers.rs:8:20: 10:6
+-         StorageDead(_12);                // scope 2 at $DIR/remove_storage_markers.rs:10:5: 10:6
+-         StorageDead(_9);                 // scope 2 at $DIR/remove_storage_markers.rs:10:5: 10:6
+-         StorageDead(_7);                 // scope 2 at $DIR/remove_storage_markers.rs:10:5: 10:6
 -         StorageDead(_6);                 // scope 2 at $DIR/remove_storage_markers.rs:10:5: 10:6
--         StorageDead(_4);                 // scope 1 at $DIR/remove_storage_markers.rs:10:5: 10:6
--         StorageDead(_2);                 // scope 1 at $DIR/remove_storage_markers.rs:10:5: 10:6
--         StorageDead(_1);                 // scope 0 at $DIR/remove_storage_markers.rs:11:1: 11:2
-          return;                          // scope 0 at $DIR/remove_storage_markers.rs:11:2: 11:2
+          _5 = const ();                   // scope 2 at $DIR/remove_storage_markers.rs:8:5: 10:6
+          goto -> bb1;                     // scope 2 at $DIR/remove_storage_markers.rs:8:5: 10:6
       }
   
       bb3: {
--         StorageLive(_12);                // scope 3 at $DIR/remove_storage_markers.rs:8:9: 8:10
-          _12 = ((_8 as Some).0: i32);     // scope 3 at $DIR/remove_storage_markers.rs:8:9: 8:10
--         StorageLive(_13);                // scope 4 at $DIR/remove_storage_markers.rs:8:9: 8:10
-          _13 = _12;                       // scope 4 at $DIR/remove_storage_markers.rs:8:9: 8:10
-          _6 = move _13;                   // scope 4 at $DIR/remove_storage_markers.rs:8:9: 8:10
-          _7 = const ();                   // scope 4 at $DIR/remove_storage_markers.rs:8:9: 8:10
--         StorageDead(_13);                // scope 4 at $DIR/remove_storage_markers.rs:8:9: 8:10
--         StorageDead(_12);                // scope 3 at $DIR/remove_storage_markers.rs:8:9: 8:10
--         StorageDead(_10);                // scope 3 at $DIR/remove_storage_markers.rs:8:18: 8:19
--         StorageDead(_8);                 // scope 3 at $DIR/remove_storage_markers.rs:8:18: 8:19
--         StorageDead(_7);                 // scope 3 at $DIR/remove_storage_markers.rs:8:18: 8:19
--         StorageLive(_15);                // scope 3 at $DIR/remove_storage_markers.rs:8:9: 8:10
-          _15 = _6;                        // scope 3 at $DIR/remove_storage_markers.rs:8:14: 8:19
--         StorageLive(_16);                // scope 5 at $DIR/remove_storage_markers.rs:8:20: 10:6
--         StorageLive(_17);                // scope 5 at $DIR/remove_storage_markers.rs:9:16: 9:17
-          _17 = _15;                       // scope 5 at $DIR/remove_storage_markers.rs:9:16: 9:17
-          _1 = Add(_1, move _17);          // scope 5 at $DIR/remove_storage_markers.rs:9:9: 9:17
--         StorageDead(_17);                // scope 5 at $DIR/remove_storage_markers.rs:9:16: 9:17
-          _16 = const ();                  // scope 5 at $DIR/remove_storage_markers.rs:8:20: 10:6
--         StorageDead(_16);                // scope 5 at $DIR/remove_storage_markers.rs:10:5: 10:6
-          _5 = const ();                   // scope 2 at $DIR/remove_storage_markers.rs:8:5: 10:6
--         StorageDead(_15);                // scope 3 at $DIR/remove_storage_markers.rs:10:5: 10:6
+          _0 = const ();                   // scope 2 at $DIR/remove_storage_markers.rs:8:5: 10:6
+-         StorageDead(_9);                 // scope 2 at $DIR/remove_storage_markers.rs:10:5: 10:6
+-         StorageDead(_7);                 // scope 2 at $DIR/remove_storage_markers.rs:10:5: 10:6
 -         StorageDead(_6);                 // scope 2 at $DIR/remove_storage_markers.rs:10:5: 10:6
-          goto -> bb1;                     // scope 2 at $DIR/remove_storage_markers.rs:8:5: 10:6
+-         StorageDead(_4);                 // scope 1 at $DIR/remove_storage_markers.rs:10:5: 10:6
+-         StorageDead(_2);                 // scope 1 at $DIR/remove_storage_markers.rs:10:5: 10:6
+-         StorageDead(_1);                 // scope 0 at $DIR/remove_storage_markers.rs:11:1: 11:2
+          return;                          // scope 0 at $DIR/remove_storage_markers.rs:11:2: 11:2
       }
   
       bb4: {
--         StorageDead(_18);                // scope 7 at $DIR/remove_storage_markers.rs:8:14: 8:19
--         StorageDead(_9);                 // scope 3 at $DIR/remove_storage_markers.rs:8:18: 8:19
-          _11 = discriminant(_8);          // scope 3 at $DIR/remove_storage_markers.rs:8:14: 8:19
-          switchInt(move _11) -> [0_isize: bb2, otherwise: bb3]; // scope 3 at $DIR/remove_storage_markers.rs:8:14: 8:19
+-         StorageDead(_14);                // scope 5 at $DIR/remove_storage_markers.rs:8:14: 8:19
+-         StorageDead(_8);                 // scope 2 at $DIR/remove_storage_markers.rs:8:18: 8:19
+          _10 = discriminant(_7);          // scope 2 at $DIR/remove_storage_markers.rs:8:14: 8:19
+          switchInt(move _10) -> [0_isize: bb3, otherwise: bb2]; // scope 2 at $DIR/remove_storage_markers.rs:8:14: 8:19
       }
   }
   
diff --git a/src/test/ui/borrowck/return-local-binding-from-desugaring.rs b/src/test/ui/borrowck/return-local-binding-from-desugaring.rs
index b2dcd54ec2e..c6643edf5a9 100644
--- a/src/test/ui/borrowck/return-local-binding-from-desugaring.rs
+++ b/src/test/ui/borrowck/return-local-binding-from-desugaring.rs
@@ -27,7 +27,7 @@ where
         let key = f(x);
         result.entry(key).or_insert(Vec::new()).push(x);
     }
-    result //~ ERROR cannot return value referencing local binding
+    result //~ ERROR cannot return value referencing temporary value
 }
 
 fn main() {}
diff --git a/src/test/ui/borrowck/return-local-binding-from-desugaring.stderr b/src/test/ui/borrowck/return-local-binding-from-desugaring.stderr
index 293dbe62813..9f952542e18 100644
--- a/src/test/ui/borrowck/return-local-binding-from-desugaring.stderr
+++ b/src/test/ui/borrowck/return-local-binding-from-desugaring.stderr
@@ -1,8 +1,8 @@
-error[E0515]: cannot return value referencing local binding
+error[E0515]: cannot return value referencing temporary value
   --> $DIR/return-local-binding-from-desugaring.rs:30:5
    |
 LL |     for ref x in xs {
-   |                  -- local binding introduced here
+   |                  -- temporary value created here
 ...
 LL |     result
    |     ^^^^^^ returns a value referencing data owned by the current function
diff --git a/src/test/ui/for/for-loop-unconstrained-element-type.stderr b/src/test/ui/for/for-loop-unconstrained-element-type.stderr
index 0672014a929..580b135ac2d 100644
--- a/src/test/ui/for/for-loop-unconstrained-element-type.stderr
+++ b/src/test/ui/for/for-loop-unconstrained-element-type.stderr
@@ -1,8 +1,10 @@
 error[E0282]: type annotations needed
-  --> $DIR/for-loop-unconstrained-element-type.rs:8:14
+  --> $DIR/for-loop-unconstrained-element-type.rs:8:9
    |
 LL |     for i in Vec::new() { }
-   |              ^^^^^^^^^^ the element type for this iterator is not specified
+   |         ^    ---------- the element type for this iterator is not specified
+   |         |
+   |         cannot infer type
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-20261.stderr b/src/test/ui/issues/issue-20261.stderr
index c6c3f32dfe7..6330364c92b 100644
--- a/src/test/ui/issues/issue-20261.stderr
+++ b/src/test/ui/issues/issue-20261.stderr
@@ -1,8 +1,8 @@
-error[E0282]: type annotations needed for `&(_,)`
+error[E0282]: type annotations needed for `(_,)`
   --> $DIR/issue-20261.rs:4:11
    |
 LL |     for (ref i,) in [].iter() {
-   |                     --------- the element type for this iterator is not specified
+   |                     --------- this method call resolves to `std::slice::Iter<'_, T>`
 LL |         i.clone();
    |           ^^^^^ cannot infer type
    |
diff --git a/src/test/ui/issues/issue-33941.rs b/src/test/ui/issues/issue-33941.rs
index 4fb805b37e0..ccaa6334856 100644
--- a/src/test/ui/issues/issue-33941.rs
+++ b/src/test/ui/issues/issue-33941.rs
@@ -3,5 +3,4 @@ use std::collections::HashMap;
 fn main() {
     for _ in HashMap::new().iter().cloned() {} //~ ERROR type mismatch
     //~^ ERROR type mismatch
-    //~| ERROR type mismatch
 }
diff --git a/src/test/ui/issues/issue-33941.stderr b/src/test/ui/issues/issue-33941.stderr
index e7263148205..eb98a3a29a6 100644
--- a/src/test/ui/issues/issue-33941.stderr
+++ b/src/test/ui/issues/issue-33941.stderr
@@ -23,16 +23,6 @@ LL |     for _ in HashMap::new().iter().cloned() {}
    = note: required because of the requirements on the impl of `Iterator` for `Cloned<std::collections::hash_map::Iter<'_, _, _>>`
    = note: required because of the requirements on the impl of `IntoIterator` for `Cloned<std::collections::hash_map::Iter<'_, _, _>>`
 
-error[E0271]: type mismatch resolving `<std::collections::hash_map::Iter<'_, _, _> as Iterator>::Item == &_`
-  --> $DIR/issue-33941.rs:4:14
-   |
-LL |     for _ in HashMap::new().iter().cloned() {}
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected reference, found tuple
-   |
-   = note: expected reference `&_`
-                  found tuple `(&_, &_)`
-   = note: required because of the requirements on the impl of `Iterator` for `Cloned<std::collections::hash_map::Iter<'_, _, _>>`
-
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0271`.
diff --git a/src/test/ui/nll/dont-print-desugared.stderr b/src/test/ui/nll/dont-print-desugared.stderr
index 88773def8b7..fad6121cbca 100644
--- a/src/test/ui/nll/dont-print-desugared.stderr
+++ b/src/test/ui/nll/dont-print-desugared.stderr
@@ -2,7 +2,7 @@ error[E0596]: cannot borrow data in a `&` reference as mutable
   --> $DIR/dont-print-desugared.rs:4:10
    |
 LL |     for &ref mut x in s {}
-   |          ^^^^^^^^^ cannot borrow as mutable through `&` reference
+   |          ^^^^^^^^^ cannot borrow as mutable
 
 error[E0597]: `y` does not live long enough
   --> $DIR/dont-print-desugared.rs:17:16
diff --git a/src/test/ui/nll/issue-53773.stderr b/src/test/ui/nll/issue-53773.stderr
index 11cd423295a..90cba2a145f 100644
--- a/src/test/ui/nll/issue-53773.stderr
+++ b/src/test/ui/nll/issue-53773.stderr
@@ -2,12 +2,10 @@ error[E0713]: borrow may still be in use when destructor runs
   --> $DIR/issue-53773.rs:41:22
    |
 LL |         members.push(child.raw);
-   |                      ^^^^^^^^^
+   |         -------------^^^^^^^^^- borrow later used here
 LL |
 LL |     }
    |     - here, drop of `child` needs exclusive access to `*child.raw`, because the type `C<'_>` implements the `Drop` trait
-LL |     members.len();
-   |     ------------- borrow later used here
    |
    = note: consider using a `let` binding to create a longer lived value
 
diff --git a/src/test/ui/reachable/unreachable-loop-patterns.rs b/src/test/ui/reachable/unreachable-loop-patterns.rs
index 4de29c3c3d7..e9cef5f47d4 100644
--- a/src/test/ui/reachable/unreachable-loop-patterns.rs
+++ b/src/test/ui/reachable/unreachable-loop-patterns.rs
@@ -17,5 +17,4 @@ impl Iterator for Void {
 fn main() {
     for _ in unimplemented!() as Void {}
     //~^ ERROR unreachable pattern
-    //~^^ ERROR unreachable pattern
 }
diff --git a/src/test/ui/reachable/unreachable-loop-patterns.stderr b/src/test/ui/reachable/unreachable-loop-patterns.stderr
index 680d22862d7..80ffa5d73f0 100644
--- a/src/test/ui/reachable/unreachable-loop-patterns.stderr
+++ b/src/test/ui/reachable/unreachable-loop-patterns.stderr
@@ -10,11 +10,5 @@ note: the lint level is defined here
 LL | #![deny(unreachable_patterns)]
    |         ^^^^^^^^^^^^^^^^^^^^
 
-error: unreachable pattern
-  --> $DIR/unreachable-loop-patterns.rs:18:14
-   |
-LL |     for _ in unimplemented!() as Void {}
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error