Importing rustc-1.53.0

Bug: 194400612
Change-Id: Id2f38eeabc8325fff960e46b89b1cc7216f5227c
diff --git a/compiler/rustc_mir/src/borrow_check/diagnostics/conflict_errors.rs b/compiler/rustc_mir/src/borrow_check/diagnostics/conflict_errors.rs
index eb942b1..9f19a47 100644
--- a/compiler/rustc_mir/src/borrow_check/diagnostics/conflict_errors.rs
+++ b/compiler/rustc_mir/src/borrow_check/diagnostics/conflict_errors.rs
@@ -197,7 +197,11 @@
                                 );
                             }
                         }
-                        FnSelfUseKind::Normal { self_arg, implicit_into_iter } => {
+                        FnSelfUseKind::Normal {
+                            self_arg,
+                            implicit_into_iter,
+                            is_option_or_result,
+                        } => {
                             if implicit_into_iter {
                                 err.span_label(
                                     fn_call_span,
@@ -215,6 +219,14 @@
                                     ),
                                 );
                             }
+                            if is_option_or_result {
+                                err.span_suggestion_verbose(
+                                    fn_call_span.shrink_to_lo(),
+                                    "consider calling `.as_ref()` to borrow the type's contents",
+                                    "as_ref().".to_string(),
+                                    Applicability::MachineApplicable,
+                                );
+                            }
                             // Avoid pointing to the same function in multiple different
                             // error messages.
                             if span != DUMMY_SP && self.fn_self_span_reported.insert(self_arg.span)
@@ -264,7 +276,24 @@
 
                 if let Some(DesugaringKind::ForLoop(_)) = move_span.desugaring_kind() {
                     let sess = self.infcx.tcx.sess;
-                    if let Ok(snippet) = sess.source_map().span_to_snippet(move_span) {
+                    let ty = used_place.ty(self.body, self.infcx.tcx).ty;
+                    // If we have a `&mut` ref, we need to reborrow.
+                    if let ty::Ref(_, _, hir::Mutability::Mut) = ty.kind() {
+                        // If we are in a loop this will be suggested later.
+                        if !is_loop_move {
+                            err.span_suggestion_verbose(
+                                move_span.shrink_to_lo(),
+                                &format!(
+                                    "consider creating a fresh reborrow of {} here",
+                                    self.describe_place(moved_place.as_ref())
+                                        .map(|n| format!("`{}`", n))
+                                        .unwrap_or_else(|| "the mutable reference".to_string()),
+                                ),
+                                format!("&mut *"),
+                                Applicability::MachineApplicable,
+                            );
+                        }
+                    } else if let Ok(snippet) = sess.source_map().span_to_snippet(move_span) {
                         err.span_suggestion(
                             move_span,
                             "consider borrowing to avoid moving into the for loop",
@@ -1664,7 +1693,7 @@
                 if decl.can_be_made_mutable() {
                     err.span_suggestion(
                         decl.source_info.span,
-                        "make this binding mutable",
+                        "consider making this binding mutable",
                         format!("mut {}", name),
                         Applicability::MachineApplicable,
                     );
@@ -1728,7 +1757,7 @@
         impl<'tcx> Visitor<'tcx> for FakeReadCauseFinder<'tcx> {
             fn visit_statement(&mut self, statement: &Statement<'tcx>, _: Location) {
                 match statement {
-                    Statement { kind: StatementKind::FakeRead(cause, box place), .. }
+                    Statement { kind: StatementKind::FakeRead(box (cause, place)), .. }
                         if *place == self.place =>
                     {
                         self.cause = Some(*cause);
diff --git a/compiler/rustc_mir/src/borrow_check/diagnostics/explain_borrow.rs b/compiler/rustc_mir/src/borrow_check/diagnostics/explain_borrow.rs
index 06e3f4b..2a388b8 100644
--- a/compiler/rustc_mir/src/borrow_check/diagnostics/explain_borrow.rs
+++ b/compiler/rustc_mir/src/borrow_check/diagnostics/explain_borrow.rs
@@ -515,7 +515,7 @@
                 let block = &self.body.basic_blocks()[location.block];
 
                 let kind = if let Some(&Statement {
-                    kind: StatementKind::FakeRead(FakeReadCause::ForLet, _),
+                    kind: StatementKind::FakeRead(box (FakeReadCause::ForLet(_), _)),
                     ..
                 }) = block.statements.get(location.statement_index)
                 {
diff --git a/compiler/rustc_mir/src/borrow_check/diagnostics/mod.rs b/compiler/rustc_mir/src/borrow_check/diagnostics/mod.rs
index ec561fa..aa9f18d 100644
--- a/compiler/rustc_mir/src/borrow_check/diagnostics/mod.rs
+++ b/compiler/rustc_mir/src/borrow_check/diagnostics/mod.rs
@@ -7,8 +7,8 @@
 use rustc_hir::lang_items::LangItemGroup;
 use rustc_hir::GeneratorKind;
 use rustc_middle::mir::{
-    AggregateKind, Constant, Field, Local, LocalInfo, LocalKind, Location, Operand, Place,
-    PlaceRef, ProjectionElem, Rvalue, Statement, StatementKind, Terminator, TerminatorKind,
+    AggregateKind, Constant, FakeReadCause, Field, Local, LocalInfo, LocalKind, Location, Operand,
+    Place, PlaceRef, ProjectionElem, Rvalue, Statement, StatementKind, Terminator, TerminatorKind,
 };
 use rustc_middle::ty::print::Print;
 use rustc_middle::ty::{self, DefIdTree, Instance, Ty, TyCtxt};
@@ -18,6 +18,7 @@
     Span,
 };
 use rustc_target::abi::VariantIdx;
+use std::iter;
 
 use super::borrow_set::BorrowData;
 use super::MirBorrowckCtxt;
@@ -501,7 +502,7 @@
         // lifetimes without names with the value `'0`.
         match ty.kind() {
             ty::Ref(
-                ty::RegionKind::ReLateBound(_, ty::BoundRegion { kind: br })
+                ty::RegionKind::ReLateBound(_, ty::BoundRegion { kind: br, .. })
                 | ty::RegionKind::RePlaceholder(ty::PlaceholderRegion { name: br, .. }),
                 _,
                 _,
@@ -522,7 +523,7 @@
         let region = match ty.kind() {
             ty::Ref(region, _, _) => {
                 match region {
-                    ty::RegionKind::ReLateBound(_, ty::BoundRegion { kind: br })
+                    ty::RegionKind::ReLateBound(_, ty::BoundRegion { kind: br, .. })
                     | ty::RegionKind::RePlaceholder(ty::PlaceholderRegion { name: br, .. }) => {
                         printer.region_highlight_mode.highlighting_bound_region(*br, counter)
                     }
@@ -572,7 +573,13 @@
 #[derive(Copy, Clone, PartialEq, Eq, Debug)]
 pub(super) enum FnSelfUseKind<'tcx> {
     /// A normal method call of the form `receiver.foo(a, b, c)`
-    Normal { self_arg: Ident, implicit_into_iter: bool },
+    Normal {
+        self_arg: Ident,
+        implicit_into_iter: bool,
+        /// Whether the self type of the method call has an `.as_ref()` method.
+        /// Used for better diagnostics.
+        is_option_or_result: bool,
+    },
     /// A call to `FnOnce::call_once`, desugared from `my_closure(a, b, c)`
     FnOnceCall,
     /// A call to an operator trait, desuraged from operator syntax (e.g. `a << b`)
@@ -794,6 +801,24 @@
             }
         }
 
+        // StatementKind::FakeRead only contains a def_id if they are introduced as a result
+        // of pattern matching within a closure.
+        if let StatementKind::FakeRead(box (cause, ref place)) = stmt.kind {
+            match cause {
+                FakeReadCause::ForMatchedPlace(Some(closure_def_id))
+                | FakeReadCause::ForLet(Some(closure_def_id)) => {
+                    debug!("move_spans: def_id={:?} place={:?}", closure_def_id, place);
+                    let places = &[Operand::Move(*place)];
+                    if let Some((args_span, generator_kind, var_span)) =
+                        self.closure_span(closure_def_id, moved_place, places)
+                    {
+                        return ClosureUse { generator_kind, args_span, var_span };
+                    }
+                }
+                _ => {}
+            }
+        }
+
         let normal_ret =
             if moved_place.projection.iter().any(|p| matches!(p, ProjectionElem::Downcast(..))) {
                 PatUse(stmt.source_info.span)
@@ -881,7 +906,17 @@
                     fn_call_span.desugaring_kind(),
                     Some(DesugaringKind::ForLoop(ForLoopLoc::IntoIter))
                 );
-                FnSelfUseKind::Normal { self_arg, implicit_into_iter }
+                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() {
+                        ty::Adt(def, ..) => Some(def.did),
+                        _ => None,
+                    });
+                let is_option_or_result = parent_self_ty.map_or(false, |def_id| {
+                    tcx.is_diagnostic_item(sym::option_type, def_id)
+                        || tcx.is_diagnostic_item(sym::result_type, def_id)
+                });
+                FnSelfUseKind::Normal { self_arg, implicit_into_iter, is_option_or_result }
             });
 
             return FnSelfUse {
@@ -970,13 +1005,10 @@
         let expr = &self.infcx.tcx.hir().expect_expr(hir_id).kind;
         debug!("closure_span: hir_id={:?} expr={:?}", hir_id, expr);
         if let hir::ExprKind::Closure(.., body_id, args_span, _) = expr {
-            for (captured_place, place) in self
-                .infcx
-                .tcx
-                .typeck(def_id.expect_local())
-                .closure_min_captures_flattened(def_id)
-                .zip(places)
-            {
+            for (captured_place, place) in iter::zip(
+                self.infcx.tcx.typeck(def_id.expect_local()).closure_min_captures_flattened(def_id),
+                places,
+            ) {
                 let upvar_hir_id = captured_place.get_root_variable();
                 //FIXME(project-rfc-2229#8): Use better span from captured_place
                 let span = self.infcx.tcx.upvars_mentioned(local_did)?[&upvar_hir_id].span;
diff --git a/compiler/rustc_mir/src/borrow_check/diagnostics/outlives_suggestion.rs b/compiler/rustc_mir/src/borrow_check/diagnostics/outlives_suggestion.rs
index 7505e6e..7dc3434 100644
--- a/compiler/rustc_mir/src/borrow_check/diagnostics/outlives_suggestion.rs
+++ b/compiler/rustc_mir/src/borrow_check/diagnostics/outlives_suggestion.rs
@@ -1,4 +1,4 @@
-//! Contains utilities for generating suggestions for borrowck errors related to unsatisified
+//! Contains utilities for generating suggestions for borrowck errors related to unsatisfied
 //! outlives constraints.
 
 use std::collections::BTreeMap;
@@ -157,7 +157,7 @@
         debug!("Collected {:?}: {:?}", fr, outlived_fr);
 
         // Add to set of constraints for final help note.
-        self.constraints_to_add.entry(fr).or_insert(Vec::new()).push(outlived_fr);
+        self.constraints_to_add.entry(fr).or_default().push(outlived_fr);
     }
 
     /// Emit an intermediate note on the given `Diagnostic` if the involved regions are
diff --git a/compiler/rustc_mir/src/borrow_check/diagnostics/region_name.rs b/compiler/rustc_mir/src/borrow_check/diagnostics/region_name.rs
index 03738f1..1f168c6 100644
--- a/compiler/rustc_mir/src/borrow_check/diagnostics/region_name.rs
+++ b/compiler/rustc_mir/src/borrow_check/diagnostics/region_name.rs
@@ -1,4 +1,5 @@
 use std::fmt::{self, Display};
+use std::iter;
 
 use rustc_errors::DiagnosticBuilder;
 use rustc_hir as hir;
@@ -536,7 +537,8 @@
                 // just worry about trying to match up the rustc type
                 // with the HIR types:
                 (ty::Tuple(elem_tys), hir::TyKind::Tup(elem_hir_tys)) => {
-                    search_stack.extend(elem_tys.iter().map(|k| k.expect_ty()).zip(*elem_hir_tys));
+                    search_stack
+                        .extend(iter::zip(elem_tys.iter().map(|k| k.expect_ty()), *elem_hir_tys));
                 }
 
                 (ty::Slice(elem_ty), hir::TyKind::Slice(elem_hir_ty))
@@ -611,7 +613,7 @@
         args: &'hir hir::GenericArgs<'hir>,
         search_stack: &mut Vec<(Ty<'tcx>, &'hir hir::Ty<'hir>)>,
     ) -> Option<&'hir hir::Lifetime> {
-        for (kind, hir_arg) in substs.iter().zip(args.args) {
+        for (kind, hir_arg) in iter::zip(substs, args.args) {
             match (kind.unpack(), hir_arg) {
                 (GenericArgKind::Lifetime(r), hir::GenericArg::Lifetime(lt)) => {
                     if r.to_region_vid() == needle_fr {
diff --git a/compiler/rustc_mir/src/borrow_check/invalidation.rs b/compiler/rustc_mir/src/borrow_check/invalidation.rs
index 17c4f3c..e621baf 100644
--- a/compiler/rustc_mir/src/borrow_check/invalidation.rs
+++ b/compiler/rustc_mir/src/borrow_check/invalidation.rs
@@ -5,6 +5,7 @@
 use rustc_middle::mir::{InlineAsmOperand, Terminator, TerminatorKind};
 use rustc_middle::mir::{Statement, StatementKind};
 use rustc_middle::ty::TyCtxt;
+use std::iter;
 
 use crate::dataflow::indexes::BorrowIndex;
 
@@ -62,14 +63,14 @@
 
                 self.mutate_place(location, *lhs, Shallow(None), JustWrite);
             }
-            StatementKind::FakeRead(_, _) => {
+            StatementKind::FakeRead(box (_, _)) => {
                 // Only relevant for initialized/liveness/safety checks.
             }
             StatementKind::SetDiscriminant { place, variant_index: _ } => {
                 self.mutate_place(location, **place, Shallow(None), JustWrite);
             }
             StatementKind::LlvmInlineAsm(asm) => {
-                for (o, output) in asm.asm.outputs.iter().zip(asm.outputs.iter()) {
+                for (o, output) in iter::zip(&asm.asm.outputs, &*asm.outputs) {
                     if o.is_indirect {
                         // FIXME(eddyb) indirect inline asm outputs should
                         // be encoded through MIR place derefs instead.
@@ -203,8 +204,7 @@
             } => {
                 for op in operands {
                     match *op {
-                        InlineAsmOperand::In { reg: _, ref value }
-                        | InlineAsmOperand::Const { ref value } => {
+                        InlineAsmOperand::In { reg: _, ref value } => {
                             self.consume_operand(location, value);
                         }
                         InlineAsmOperand::Out { reg: _, late: _, place, .. } => {
@@ -218,7 +218,8 @@
                                 self.mutate_place(location, out_place, Shallow(None), JustWrite);
                             }
                         }
-                        InlineAsmOperand::SymFn { value: _ }
+                        InlineAsmOperand::Const { value: _ }
+                        | InlineAsmOperand::SymFn { value: _ }
                         | InlineAsmOperand::SymStatic { def_id: _ } => {}
                     }
                 }
diff --git a/compiler/rustc_mir/src/borrow_check/mod.rs b/compiler/rustc_mir/src/borrow_check/mod.rs
index 5b8bb72..2d1d83b 100644
--- a/compiler/rustc_mir/src/borrow_check/mod.rs
+++ b/compiler/rustc_mir/src/borrow_check/mod.rs
@@ -25,6 +25,7 @@
 use smallvec::SmallVec;
 use std::cell::RefCell;
 use std::collections::BTreeMap;
+use std::iter;
 use std::mem;
 use std::rc::Rc;
 
@@ -573,7 +574,7 @@
 
                 self.mutate_place(location, (*lhs, span), Shallow(None), JustWrite, flow_state);
             }
-            StatementKind::FakeRead(_, box ref place) => {
+            StatementKind::FakeRead(box (_, ref place)) => {
                 // Read for match doesn't access any memory and is used to
                 // assert that a place is safe and live. So we don't have to
                 // do any checks here.
@@ -595,7 +596,7 @@
                 self.mutate_place(location, (**place, span), Shallow(None), JustWrite, flow_state);
             }
             StatementKind::LlvmInlineAsm(ref asm) => {
-                for (o, output) in asm.asm.outputs.iter().zip(asm.outputs.iter()) {
+                for (o, output) in iter::zip(&asm.asm.outputs, &*asm.outputs) {
                     if o.is_indirect {
                         // FIXME(eddyb) indirect inline asm outputs should
                         // be encoded through MIR place derefs instead.
@@ -733,8 +734,7 @@
             } => {
                 for op in operands {
                     match *op {
-                        InlineAsmOperand::In { reg: _, ref value }
-                        | InlineAsmOperand::Const { ref value } => {
+                        InlineAsmOperand::In { reg: _, ref value } => {
                             self.consume_operand(loc, (value, span), flow_state);
                         }
                         InlineAsmOperand::Out { reg: _, late: _, place, .. } => {
@@ -760,7 +760,8 @@
                                 );
                             }
                         }
-                        InlineAsmOperand::SymFn { value: _ }
+                        InlineAsmOperand::Const { value: _ }
+                        | InlineAsmOperand::SymFn { value: _ }
                         | InlineAsmOperand::SymStatic { def_id: _ } => {}
                     }
                 }
diff --git a/compiler/rustc_mir/src/borrow_check/places_conflict.rs b/compiler/rustc_mir/src/borrow_check/places_conflict.rs
index 02c7b7d..3654b51 100644
--- a/compiler/rustc_mir/src/borrow_check/places_conflict.rs
+++ b/compiler/rustc_mir/src/borrow_check/places_conflict.rs
@@ -5,6 +5,7 @@
 use rustc_middle::mir::{Body, BorrowKind, Local, Place, PlaceElem, PlaceRef, ProjectionElem};
 use rustc_middle::ty::{self, TyCtxt};
 use std::cmp::max;
+use std::iter;
 
 /// When checking if a place conflicts with another place, this enum is used to influence decisions
 /// where a place might be equal or disjoint with another place, such as if `a[i] == a[j]`.
@@ -139,7 +140,7 @@
 
     // loop invariant: borrow_c is always either equal to access_c or disjoint from it.
     for (i, (borrow_c, &access_c)) in
-        borrow_place.projection.iter().zip(access_place.projection.iter()).enumerate()
+        iter::zip(borrow_place.projection, access_place.projection).enumerate()
     {
         debug!("borrow_conflicts_with_place: borrow_c = {:?}", borrow_c);
         let borrow_proj_base = &borrow_place.projection[..i];
diff --git a/compiler/rustc_mir/src/borrow_check/region_infer/graphviz.rs b/compiler/rustc_mir/src/borrow_check/region_infer/graphviz.rs
index a272e92..7156612 100644
--- a/compiler/rustc_mir/src/borrow_check/region_infer/graphviz.rs
+++ b/compiler/rustc_mir/src/borrow_check/region_infer/graphviz.rs
@@ -1,5 +1,5 @@
 //! This module provides linkage between RegionInferenceContext and
-//! librustc_graphviz traits, specialized to attaching borrowck analysis
+//! `rustc_graphviz` traits, specialized to attaching borrowck analysis
 //! data to rendered labels.
 
 use std::borrow::Cow;
diff --git a/compiler/rustc_mir/src/borrow_check/type_check/input_output.rs b/compiler/rustc_mir/src/borrow_check/type_check/input_output.rs
index 77d9136..1bb447d 100644
--- a/compiler/rustc_mir/src/borrow_check/type_check/input_output.rs
+++ b/compiler/rustc_mir/src/borrow_check/type_check/input_output.rs
@@ -70,6 +70,12 @@
 
         // Equate expected input tys with those in the MIR.
         for (argument_index, &normalized_input_ty) in normalized_input_tys.iter().enumerate() {
+            if argument_index + 1 >= body.local_decls.len() {
+                self.tcx()
+                    .sess
+                    .delay_span_bug(body.span, "found more normalized_input_ty than local_decls");
+                break;
+            }
             // In MIR, argument N is stored in local N+1.
             let local = Local::new(argument_index + 1);
 
diff --git a/compiler/rustc_mir/src/borrow_check/type_check/mod.rs b/compiler/rustc_mir/src/borrow_check/type_check/mod.rs
index cce1549..d27fcb2 100644
--- a/compiler/rustc_mir/src/borrow_check/type_check/mod.rs
+++ b/compiler/rustc_mir/src/borrow_check/type_check/mod.rs
@@ -97,7 +97,7 @@
 
 /// Type checks the given `mir` in the context of the inference
 /// context `infcx`. Returns any region constraints that have yet to
-/// be proven. This result is includes liveness constraints that
+/// be proven. This result includes liveness constraints that
 /// ensure that regions appearing in the types of all local variables
 /// are live at all points where that local variable may later be
 /// used.
@@ -316,14 +316,12 @@
             let tcx = self.tcx();
             let maybe_uneval = match constant.literal {
                 ConstantKind::Ty(ct) => match ct.val {
-                    ty::ConstKind::Unevaluated(def, substs, promoted) => {
-                        Some((def, substs, promoted))
-                    }
+                    ty::ConstKind::Unevaluated(uv) => Some(uv),
                     _ => None,
                 },
                 _ => None,
             };
-            if let Some((def, substs, promoted)) = maybe_uneval {
+            if let Some(ty::Unevaluated { def, substs, promoted }) = maybe_uneval {
                 if let Some(promoted) = promoted {
                     let check_err = |verifier: &mut TypeVerifier<'a, 'b, 'tcx>,
                                      promoted: &Body<'tcx>,
@@ -1772,7 +1770,7 @@
         if args.len() < sig.inputs().len() || (args.len() > sig.inputs().len() && !sig.c_variadic) {
             span_mirbug!(self, term, "call to {:?} with wrong # of args", sig);
         }
-        for (n, (fn_arg, op_arg)) in sig.inputs().iter().zip(args).enumerate() {
+        for (n, (fn_arg, op_arg)) in iter::zip(sig.inputs(), args).enumerate() {
             let op_arg_ty = op_arg.ty(body, self.tcx());
             let op_arg_ty = self.normalize(op_arg_ty, term_location);
             let category = if from_hir_call {
@@ -2030,7 +2028,7 @@
                                             traits::ObligationCauseCode::RepeatVec(is_const_fn),
                                         ),
                                         self.param_env,
-                                        ty::Binder::bind(ty::TraitRef::new(
+                                        ty::Binder::dummy(ty::TraitRef::new(
                                             self.tcx().require_lang_item(
                                                 LangItem::Copy,
                                                 Some(self.last_span),
diff --git a/compiler/rustc_mir/src/borrow_check/universal_regions.rs b/compiler/rustc_mir/src/borrow_check/universal_regions.rs
index 4b1acc1..c2ac1e2 100644
--- a/compiler/rustc_mir/src/borrow_check/universal_regions.rs
+++ b/compiler/rustc_mir/src/borrow_check/universal_regions.rs
@@ -580,7 +580,7 @@
 
         let global_mapping = iter::once((tcx.lifetimes.re_static, fr_static));
         let subst_mapping =
-            identity_substs.regions().zip(fr_substs.regions().map(|r| r.to_region_vid()));
+            iter::zip(identity_substs.regions(), fr_substs.regions().map(|r| r.to_region_vid()));
 
         UniversalRegionIndices { indices: global_mapping.chain(subst_mapping).collect() }
     }
@@ -589,31 +589,45 @@
         &self,
         indices: &UniversalRegionIndices<'tcx>,
         defining_ty: DefiningTy<'tcx>,
-    ) -> ty::Binder<&'tcx ty::List<Ty<'tcx>>> {
+    ) -> ty::Binder<'tcx, &'tcx ty::List<Ty<'tcx>>> {
         let tcx = self.infcx.tcx;
         match defining_ty {
             DefiningTy::Closure(def_id, substs) => {
                 assert_eq!(self.mir_def.did.to_def_id(), def_id);
                 let closure_sig = substs.as_closure().sig();
                 let inputs_and_output = closure_sig.inputs_and_output();
-                let closure_ty = tcx.closure_env_ty(def_id, substs).unwrap();
-                ty::Binder::fuse(closure_ty, inputs_and_output, |closure_ty, inputs_and_output| {
-                    // The "inputs" of the closure in the
-                    // signature appear as a tuple.  The MIR side
-                    // flattens this tuple.
-                    let (&output, tuplized_inputs) = inputs_and_output.split_last().unwrap();
-                    assert_eq!(tuplized_inputs.len(), 1, "multiple closure inputs");
-                    let inputs = match tuplized_inputs[0].kind() {
-                        ty::Tuple(inputs) => inputs,
-                        _ => bug!("closure inputs not a tuple: {:?}", tuplized_inputs[0]),
-                    };
+                let bound_vars = tcx.mk_bound_variable_kinds(
+                    inputs_and_output
+                        .bound_vars()
+                        .iter()
+                        .chain(iter::once(ty::BoundVariableKind::Region(ty::BrEnv))),
+                );
+                let br = ty::BoundRegion {
+                    var: ty::BoundVar::from_usize(bound_vars.len() - 1),
+                    kind: ty::BrEnv,
+                };
+                let env_region = ty::ReLateBound(ty::INNERMOST, br);
+                let closure_ty = tcx.closure_env_ty(def_id, substs, env_region).unwrap();
 
+                // The "inputs" of the closure in the
+                // signature appear as a tuple.  The MIR side
+                // flattens this tuple.
+                let (&output, tuplized_inputs) =
+                    inputs_and_output.skip_binder().split_last().unwrap();
+                assert_eq!(tuplized_inputs.len(), 1, "multiple closure inputs");
+                let inputs = match tuplized_inputs[0].kind() {
+                    ty::Tuple(inputs) => inputs,
+                    _ => bug!("closure inputs not a tuple: {:?}", tuplized_inputs[0]),
+                };
+
+                ty::Binder::bind_with_vars(
                     tcx.mk_type_list(
                         iter::once(closure_ty)
                             .chain(inputs.iter().map(|k| k.expect_ty()))
                             .chain(iter::once(output)),
-                    )
-                })
+                    ),
+                    bound_vars,
+                )
             }
 
             DefiningTy::Generator(def_id, substs, movability) => {
@@ -657,7 +671,7 @@
         &self,
         origin: NllRegionVariableOrigin,
         all_outlive_scope: LocalDefId,
-        value: ty::Binder<T>,
+        value: ty::Binder<'tcx, T>,
         indices: &mut UniversalRegionIndices<'tcx>,
     ) -> T
     where
@@ -686,7 +700,7 @@
         &self,
         origin: NllRegionVariableOrigin,
         all_outlive_scope: LocalDefId,
-        value: ty::Binder<T>,
+        value: ty::Binder<'tcx, T>,
         indices: &mut UniversalRegionIndices<'tcx>,
     ) -> T
     where
diff --git a/compiler/rustc_mir/src/const_eval/eval_queries.rs b/compiler/rustc_mir/src/const_eval/eval_queries.rs
index fa234ff..d51adc8 100644
--- a/compiler/rustc_mir/src/const_eval/eval_queries.rs
+++ b/compiler/rustc_mir/src/const_eval/eval_queries.rs
@@ -5,6 +5,7 @@
     Immediate, InternKind, InterpCx, InterpResult, MPlaceTy, MemoryKind, OpTy, RefTracking, Scalar,
     ScalarMaybeUninit, StackPopCleanup,
 };
+use crate::util::pretty::display_allocation;
 
 use rustc_errors::ErrorReported;
 use rustc_hir::def::DefKind;
@@ -360,6 +361,15 @@
                     "it is undefined behavior to use this value",
                     |mut diag| {
                         diag.note(note_on_undefined_behavior_error());
+                        diag.note(&format!(
+                            "the raw bytes of the constant ({}",
+                            display_allocation(
+                                *ecx.tcx,
+                                ecx.tcx
+                                    .global_alloc(mplace.ptr.assert_ptr().alloc_id)
+                                    .unwrap_memory()
+                            )
+                        ));
                         diag.emit();
                     },
                 ))
diff --git a/compiler/rustc_mir/src/const_eval/fn_queries.rs b/compiler/rustc_mir/src/const_eval/fn_queries.rs
index 8c18dfc..40419a4 100644
--- a/compiler/rustc_mir/src/const_eval/fn_queries.rs
+++ b/compiler/rustc_mir/src/const_eval/fn_queries.rs
@@ -1,4 +1,3 @@
-use rustc_attr as attr;
 use rustc_hir as hir;
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_middle::hir::map::blocks::FnLikeNode;
@@ -34,54 +33,6 @@
     }
 }
 
-/// Returns `true` if this function must conform to `min_const_fn`
-pub fn is_min_const_fn(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
-    // Bail out if the signature doesn't contain `const`
-    if !tcx.is_const_fn_raw(def_id) {
-        return false;
-    }
-
-    if tcx.features().staged_api {
-        // In order for a libstd function to be considered min_const_fn
-        // it needs to be stable and have no `rustc_const_unstable` attribute.
-        match tcx.lookup_const_stability(def_id) {
-            // `rustc_const_unstable` functions don't need to conform.
-            Some(&attr::ConstStability { ref level, .. }) if level.is_unstable() => false,
-            None => {
-                if let Some(stab) = tcx.lookup_stability(def_id) {
-                    if stab.level.is_stable() {
-                        tcx.sess.delay_span_bug(
-                            tcx.def_span(def_id),
-                            "stable const functions must have either `rustc_const_stable` or \
-                             `rustc_const_unstable` attribute",
-                        );
-                        // While we errored above, because we don't know if we need to conform, we
-                        // err on the "safe" side and require min_const_fn.
-                        true
-                    } else {
-                        // Unstable functions need not conform to min_const_fn.
-                        false
-                    }
-                } else {
-                    // Internal functions are forced to conform to min_const_fn.
-                    // Annotate the internal function with a const stability attribute if
-                    // you need to use unstable features.
-                    // Note: this is an arbitrary choice that does not affect stability or const
-                    // safety or anything, it just changes whether we need to annotate some
-                    // internal functions with `rustc_const_stable` or with `rustc_const_unstable`
-                    true
-                }
-            }
-            // Everything else needs to conform, because it would be callable from
-            // other `min_const_fn` functions.
-            _ => true,
-        }
-    } else {
-        // users enabling the `const_fn` feature gate can do what they want
-        !tcx.features().const_fn
-    }
-}
-
 pub fn is_parent_const_impl_raw(tcx: TyCtxt<'_>, hir_id: hir::HirId) -> bool {
     let parent_id = tcx.hir().get_parent_did(hir_id);
     if !parent_id.is_top_level_module() { is_const_impl_raw(tcx, parent_id) } else { false }
diff --git a/compiler/rustc_mir/src/const_eval/machine.rs b/compiler/rustc_mir/src/const_eval/machine.rs
index 61785a5..8e9148f 100644
--- a/compiler/rustc_mir/src/const_eval/machine.rs
+++ b/compiler/rustc_mir/src/const_eval/machine.rs
@@ -53,7 +53,7 @@
 /// Extra machine state for CTFE, and the Machine instance
 pub struct CompileTimeInterpreter<'mir, 'tcx> {
     /// For now, the number of terminators that can be evaluated before we throw a resource
-    /// exhuastion error.
+    /// exhaustion error.
     ///
     /// Setting this to `0` disables the limit and allows the interpreter to run forever.
     pub steps_remaining: usize,
diff --git a/compiler/rustc_mir/src/const_eval/mod.rs b/compiler/rustc_mir/src/const_eval/mod.rs
index 77531ae..3f14efc 100644
--- a/compiler/rustc_mir/src/const_eval/mod.rs
+++ b/compiler/rustc_mir/src/const_eval/mod.rs
@@ -110,7 +110,7 @@
 
             let variant = ecx.read_discriminant(&place.into()).unwrap().1;
 
-            branches(def.variants[variant].fields.len(), Some(variant))
+            branches(def.variants[variant].fields.len(), def.is_enum().then_some(variant))
         }
 
         ty::Never
diff --git a/compiler/rustc_mir/src/dataflow/framework/cursor.rs b/compiler/rustc_mir/src/dataflow/framework/cursor.rs
index 4942bed..c000e49 100644
--- a/compiler/rustc_mir/src/dataflow/framework/cursor.rs
+++ b/compiler/rustc_mir/src/dataflow/framework/cursor.rs
@@ -64,10 +64,6 @@
         }
     }
 
-    pub fn body(&self) -> &'mir mir::Body<'tcx> {
-        self.body
-    }
-
     /// Returns the underlying `Results`.
     pub fn results(&self) -> &Results<'tcx, A> {
         &self.results.borrow()
diff --git a/compiler/rustc_mir/src/dataflow/framework/lattice.rs b/compiler/rustc_mir/src/dataflow/framework/lattice.rs
index e7ef926..f937b31 100644
--- a/compiler/rustc_mir/src/dataflow/framework/lattice.rs
+++ b/compiler/rustc_mir/src/dataflow/framework/lattice.rs
@@ -40,6 +40,7 @@
 
 use rustc_index::bit_set::BitSet;
 use rustc_index::vec::{Idx, IndexVec};
+use std::iter;
 
 /// A [partially ordered set][poset] that has a [least upper bound][lub] for any pair of elements
 /// in the set.
@@ -110,7 +111,7 @@
         assert_eq!(self.len(), other.len());
 
         let mut changed = false;
-        for (a, b) in self.iter_mut().zip(other.iter()) {
+        for (a, b) in iter::zip(self, other) {
             changed |= a.join(b);
         }
         changed
@@ -122,7 +123,7 @@
         assert_eq!(self.len(), other.len());
 
         let mut changed = false;
-        for (a, b) in self.iter_mut().zip(other.iter()) {
+        for (a, b) in iter::zip(self, other) {
             changed |= a.meet(b);
         }
         changed
diff --git a/compiler/rustc_mir/src/dataflow/framework/mod.rs b/compiler/rustc_mir/src/dataflow/framework/mod.rs
index 3f7808c..344d7b9 100644
--- a/compiler/rustc_mir/src/dataflow/framework/mod.rs
+++ b/compiler/rustc_mir/src/dataflow/framework/mod.rs
@@ -510,7 +510,7 @@
         }
     }
 
-    /// Returns `true` if the effect at `self` should be applied eariler than the effect at `other`
+    /// Returns `true` if the effect at `self` should be applied earlier than the effect at `other`
     /// in forward order.
     fn precedes_in_forward_order(self, other: Self) -> bool {
         let ord = self
diff --git a/compiler/rustc_mir/src/dataflow/impls/borrows.rs b/compiler/rustc_mir/src/dataflow/impls/borrows.rs
index f24d0f0..c92cff1 100644
--- a/compiler/rustc_mir/src/dataflow/impls/borrows.rs
+++ b/compiler/rustc_mir/src/dataflow/impls/borrows.rs
@@ -11,6 +11,7 @@
 use crate::dataflow::{self, fmt::DebugWithContext, GenKill};
 
 use std::fmt;
+use std::iter;
 
 rustc_index::newtype_index! {
     pub struct BorrowIndex {
@@ -292,7 +293,7 @@
             }
 
             mir::StatementKind::LlvmInlineAsm(ref asm) => {
-                for (output, kind) in asm.outputs.iter().zip(&asm.asm.outputs) {
+                for (output, kind) in iter::zip(&*asm.outputs, &asm.asm.outputs) {
                     if !kind.is_indirect && !kind.is_rw {
                         self.kill_borrows_on_place(trans, *output);
                     }
diff --git a/compiler/rustc_mir/src/dataflow/move_paths/builder.rs b/compiler/rustc_mir/src/dataflow/move_paths/builder.rs
index 1ddd81e..994b403 100644
--- a/compiler/rustc_mir/src/dataflow/move_paths/builder.rs
+++ b/compiler/rustc_mir/src/dataflow/move_paths/builder.rs
@@ -4,6 +4,7 @@
 use rustc_middle::ty::{self, TyCtxt};
 use smallvec::{smallvec, SmallVec};
 
+use std::iter;
 use std::mem;
 
 use super::abs_domain::Lift;
@@ -292,11 +293,11 @@
                 }
                 self.gather_rvalue(rval);
             }
-            StatementKind::FakeRead(_, place) => {
-                self.create_move_path(**place);
+            StatementKind::FakeRead(box (_, place)) => {
+                self.create_move_path(*place);
             }
             StatementKind::LlvmInlineAsm(ref asm) => {
-                for (output, kind) in asm.outputs.iter().zip(&asm.asm.outputs) {
+                for (output, kind) in iter::zip(&*asm.outputs, &asm.asm.outputs) {
                     if !kind.is_indirect {
                         self.gather_init(output.as_ref(), InitKind::Deep);
                     }
@@ -424,7 +425,7 @@
                 for op in operands {
                     match *op {
                         InlineAsmOperand::In { reg: _, ref value }
-                        | InlineAsmOperand::Const { ref value } => {
+                         => {
                             self.gather_operand(value);
                         }
                         InlineAsmOperand::Out { reg: _, late: _, place, .. } => {
@@ -440,7 +441,8 @@
                                 self.gather_init(out_place.as_ref(), InitKind::Deep);
                             }
                         }
-                        InlineAsmOperand::SymFn { value: _ }
+                        InlineAsmOperand::Const { value: _ }
+                        | InlineAsmOperand::SymFn { value: _ }
                         | InlineAsmOperand::SymStatic { def_id: _ } => {}
                     }
                 }
diff --git a/compiler/rustc_mir/src/interpret/eval_context.rs b/compiler/rustc_mir/src/interpret/eval_context.rs
index 149a9f8..2d83d6c 100644
--- a/compiler/rustc_mir/src/interpret/eval_context.rs
+++ b/compiler/rustc_mir/src/interpret/eval_context.rs
@@ -232,6 +232,8 @@
     /// this frame (can happen e.g. during frame initialization, and during unwinding on
     /// frames without cleanup code).
     /// We basically abuse `Result` as `Either`.
+    ///
+    /// Used by priroda.
     pub fn current_loc(&self) -> Result<mir::Location, Span> {
         self.loc
     }
@@ -460,11 +462,6 @@
     }
 
     #[inline]
-    pub fn type_is_sized(&self, ty: Ty<'tcx>) -> bool {
-        ty.is_sized(self.tcx, self.param_env)
-    }
-
-    #[inline]
     pub fn type_is_freeze(&self, ty: Ty<'tcx>) -> bool {
         ty.is_freeze(self.tcx, self.param_env)
     }
@@ -527,6 +524,7 @@
         }
     }
 
+    #[inline(always)]
     pub fn layout_of_local(
         &self,
         frame: &Frame<'mir, 'tcx, M::PointerTag, M::FrameExtra>,
diff --git a/compiler/rustc_mir/src/interpret/intrinsics.rs b/compiler/rustc_mir/src/interpret/intrinsics.rs
index 25c3c2c..d74ef66 100644
--- a/compiler/rustc_mir/src/interpret/intrinsics.rs
+++ b/compiler/rustc_mir/src/interpret/intrinsics.rs
@@ -171,8 +171,7 @@
                 };
                 let val =
                     self.tcx.const_eval_global_id(self.param_env, gid, Some(self.tcx.span))?;
-                let const_ = ty::Const { val: ty::ConstKind::Value(val), ty };
-                let val = self.const_to_op(&const_, None)?;
+                let val = self.const_val_to_op(val, ty, Some(dest.layout))?;
                 self.copy_op(&val, dest)?;
             }
 
diff --git a/compiler/rustc_mir/src/interpret/intrinsics/type_name.rs b/compiler/rustc_mir/src/interpret/intrinsics/type_name.rs
index e1ec4cc..ae5e78e 100644
--- a/compiler/rustc_mir/src/interpret/intrinsics/type_name.rs
+++ b/compiler/rustc_mir/src/interpret/intrinsics/type_name.rs
@@ -74,7 +74,7 @@
 
     fn print_dyn_existential(
         mut self,
-        predicates: &'tcx ty::List<ty::Binder<ty::ExistentialPredicate<'tcx>>>,
+        predicates: &'tcx ty::List<ty::Binder<'tcx, ty::ExistentialPredicate<'tcx>>>,
     ) -> Result<Self::DynExistential, Self::Error> {
         let mut first = true;
         for p in predicates {
diff --git a/compiler/rustc_mir/src/interpret/operand.rs b/compiler/rustc_mir/src/interpret/operand.rs
index 2893349..e5bc932 100644
--- a/compiler/rustc_mir/src/interpret/operand.rs
+++ b/compiler/rustc_mir/src/interpret/operand.rs
@@ -77,14 +77,6 @@
     pub fn to_scalar(self) -> InterpResult<'tcx, Scalar<Tag>> {
         self.to_scalar_or_uninit().check_init()
     }
-
-    #[inline]
-    pub fn to_scalar_pair(self) -> InterpResult<'tcx, (Scalar<Tag>, Scalar<Tag>)> {
-        match self {
-            Immediate::Scalar(..) => bug!("Got a thin pointer where a scalar pair was expected"),
-            Immediate::ScalarPair(a, b) => Ok((a.check_init()?, b.check_init()?)),
-        }
-    }
 }
 
 // ScalarPair needs a type to interpret, so we often have an immediate and a type together
@@ -233,7 +225,7 @@
 }
 
 impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
-    /// Normalice `place.ptr` to a `Pointer` if this is a place and not a ZST.
+    /// Normalize `place.ptr` to a `Pointer` if this is a place and not a ZST.
     /// Can be helpful to avoid lots of `force_ptr` calls later, if this place is used a lot.
     #[inline]
     pub fn force_op_ptr(
@@ -560,7 +552,7 @@
         match val.val {
             ty::ConstKind::Param(_) | ty::ConstKind::Bound(..) => throw_inval!(TooGeneric),
             ty::ConstKind::Error(_) => throw_inval!(AlreadyReported(ErrorReported)),
-            ty::ConstKind::Unevaluated(def, substs, promoted) => {
+            ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }) => {
                 let instance = self.resolve(def, substs)?;
                 Ok(self.eval_to_allocation(GlobalId { instance, promoted })?.into())
             }
@@ -578,7 +570,7 @@
     ) -> InterpResult<'tcx, OpTy<'tcx, M::PointerTag>> {
         match val {
             mir::ConstantKind::Ty(ct) => self.const_to_op(ct, layout),
-            mir::ConstantKind::Val(val, ty) => self.const_val_to_op(*val, ty, None),
+            mir::ConstantKind::Val(val, ty) => self.const_val_to_op(*val, ty, layout),
         }
     }
 
diff --git a/compiler/rustc_mir/src/lib.rs b/compiler/rustc_mir/src/lib.rs
index bf4eeb4..f9adc27 100644
--- a/compiler/rustc_mir/src/lib.rs
+++ b/compiler/rustc_mir/src/lib.rs
@@ -11,12 +11,12 @@
 #![feature(bool_to_option)]
 #![feature(box_patterns)]
 #![feature(box_syntax)]
-#![feature(const_fn)]
 #![feature(const_panic)]
 #![feature(crate_visibility_modifier)]
 #![feature(decl_macro)]
 #![feature(exact_size_is_empty)]
 #![feature(exhaustive_patterns)]
+#![feature(iter_zip)]
 #![feature(never_type)]
 #![feature(map_try_insert)]
 #![feature(min_specialization)]
@@ -26,7 +26,7 @@
 #![feature(stmt_expr_attributes)]
 #![feature(trait_alias)]
 #![feature(option_get_or_insert_default)]
-#![feature(or_patterns)]
+#![cfg_attr(bootstrap, feature(or_patterns))]
 #![feature(once_cell)]
 #![feature(control_flow_enum)]
 #![recursion_limit = "256"]
diff --git a/compiler/rustc_mir/src/monomorphize/collector.rs b/compiler/rustc_mir/src/monomorphize/collector.rs
index 911224d..fdefc89 100644
--- a/compiler/rustc_mir/src/monomorphize/collector.rs
+++ b/compiler/rustc_mir/src/monomorphize/collector.rs
@@ -59,11 +59,15 @@
 //!
 //! ### Discovering roots
 //!
-//! The roots of the mono item graph correspond to the non-generic
+//! The roots of the mono item graph correspond to the public non-generic
 //! syntactic items in the source code. We find them by walking the HIR of the
-//! crate, and whenever we hit upon a function, method, or static item, we
-//! create a mono item consisting of the items DefId and, since we only
-//! consider non-generic items, an empty type-substitution set.
+//! crate, and whenever we hit upon a public function, method, or static item,
+//! we create a mono item consisting of the items DefId and, since we only
+//! consider non-generic items, an empty type-substitution set. (In eager
+//! collection mode, during incremental compilation, all non-generic functions
+//! are considered as roots, as well as when the `-Clink-dead-code` option is
+//! specified. Functions marked `#[no_mangle]` and functions called by inlinable
+//! functions also always act as roots.)
 //!
 //! ### Finding neighbor nodes
 //! Given a mono item node, we can discover neighbors by inspecting its
@@ -184,7 +188,6 @@
 use rustc_hir::itemlikevisit::ItemLikeVisitor;
 use rustc_hir::lang_items::LangItem;
 use rustc_index::bit_set::GrowableBitSet;
-use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
 use rustc_middle::mir::interpret::{AllocId, ConstValue};
 use rustc_middle::mir::interpret::{ErrorHandled, GlobalAlloc, Scalar};
 use rustc_middle::mir::mono::{InstantiationMode, MonoItem};
@@ -193,8 +196,11 @@
 use rustc_middle::ty::adjustment::{CustomCoerceUnsized, PointerCast};
 use rustc_middle::ty::subst::{GenericArgKind, InternalSubsts};
 use rustc_middle::ty::{self, GenericParamDefKind, Instance, Ty, TyCtxt, TypeFoldable};
+use rustc_middle::{middle::codegen_fn_attrs::CodegenFnAttrFlags, mir::visit::TyContext};
 use rustc_session::config::EntryFnType;
+use rustc_session::lint::builtin::LARGE_ASSIGNMENTS;
 use rustc_span::source_map::{dummy_spanned, respan, Span, Spanned, DUMMY_SP};
+use rustc_target::abi::Size;
 use smallvec::SmallVec;
 use std::iter;
 use std::ops::Range;
@@ -638,6 +644,35 @@
         self.super_rvalue(rvalue, location);
     }
 
+    /// This does not walk the constant, as it has been handled entirely here and trying
+    /// to walk it would attempt to evaluate the `ty::Const` inside, which doesn't necessarily
+    /// work, as some constants cannot be represented in the type system.
+    fn visit_constant(&mut self, constant: &mir::Constant<'tcx>, location: Location) {
+        let literal = self.monomorphize(constant.literal);
+        let val = match literal {
+            mir::ConstantKind::Val(val, _) => val,
+            mir::ConstantKind::Ty(ct) => match ct.val {
+                ty::ConstKind::Value(val) => val,
+                ty::ConstKind::Unevaluated(ct) => {
+                    let param_env = ty::ParamEnv::reveal_all();
+                    match self.tcx.const_eval_resolve(param_env, ct, None) {
+                        // The `monomorphize` call should have evaluated that constant already.
+                        Ok(val) => val,
+                        Err(ErrorHandled::Reported(ErrorReported) | ErrorHandled::Linted) => return,
+                        Err(ErrorHandled::TooGeneric) => span_bug!(
+                            self.body.source_info(location).span,
+                            "collection encountered polymorphic constant: {:?}",
+                            literal
+                        ),
+                    }
+                }
+                _ => return,
+            },
+        };
+        collect_const_value(self.tcx, val, self.output);
+        self.visit_ty(literal.ty(), TyContext::Location(location));
+    }
+
     fn visit_const(&mut self, constant: &&'tcx ty::Const<'tcx>, location: Location) {
         debug!("visiting const {:?} @ {:?}", *constant, location);
 
@@ -646,9 +681,15 @@
 
         match substituted_constant.val {
             ty::ConstKind::Value(val) => collect_const_value(self.tcx, val, self.output),
-            ty::ConstKind::Unevaluated(def, substs, promoted) => {
-                match self.tcx.const_eval_resolve(param_env, def, substs, promoted, None) {
-                    Ok(val) => collect_const_value(self.tcx, val, self.output),
+            ty::ConstKind::Unevaluated(unevaluated) => {
+                match self.tcx.const_eval_resolve(param_env, unevaluated, None) {
+                    // The `monomorphize` call should have evaluated that constant already.
+                    Ok(val) => span_bug!(
+                        self.body.source_info(location).span,
+                        "collection encountered the unevaluated constant {} which evaluated to {:?}",
+                        substituted_constant,
+                        val
+                    ),
                     Err(ErrorHandled::Reported(ErrorReported) | ErrorHandled::Linted) => {}
                     Err(ErrorHandled::TooGeneric) => span_bug!(
                         self.body.source_info(location).span,
@@ -714,6 +755,46 @@
         self.super_terminator(terminator, location);
     }
 
+    fn visit_operand(&mut self, operand: &mir::Operand<'tcx>, location: Location) {
+        self.super_operand(operand, location);
+        let limit = self.tcx.sess.move_size_limit();
+        if limit == 0 {
+            return;
+        }
+        let limit = Size::from_bytes(limit);
+        let ty = operand.ty(self.body, self.tcx);
+        let ty = self.monomorphize(ty);
+        let layout = self.tcx.layout_of(ty::ParamEnv::reveal_all().and(ty));
+        if let Ok(layout) = layout {
+            if layout.size > limit {
+                debug!(?layout);
+                let source_info = self.body.source_info(location);
+                debug!(?source_info);
+                let lint_root = source_info.scope.lint_root(&self.body.source_scopes);
+                debug!(?lint_root);
+                let lint_root = match lint_root {
+                    Some(lint_root) => lint_root,
+                    // This happens when the issue is in a function from a foreign crate that
+                    // we monomorphized in the current crate. We can't get a `HirId` for things
+                    // in other crates.
+                    // FIXME: Find out where to report the lint on. Maybe simply crate-level lint root
+                    // but correct span? This would make the lint at least accept crate-level lint attributes.
+                    None => return,
+                };
+                self.tcx.struct_span_lint_hir(
+                    LARGE_ASSIGNMENTS,
+                    lint_root,
+                    source_info.span,
+                    |lint| {
+                        let mut err = lint.build(&format!("moving {} bytes", layout.size.bytes()));
+                        err.span_label(source_info.span, "value moved from here");
+                        err.emit()
+                    },
+                );
+            }
+        }
+    }
+
     fn visit_local(
         &mut self,
         _place_local: &Local,
@@ -985,7 +1066,7 @@
     tcx: TyCtxt<'tcx>,
     mode: MonoItemCollectionMode,
     output: &'a mut Vec<Spanned<MonoItem<'tcx>>>,
-    entry_fn: Option<(LocalDefId, EntryFnType)>,
+    entry_fn: Option<(DefId, EntryFnType)>,
 }
 
 impl ItemLikeVisitor<'v> for RootCollector<'_, 'v> {
@@ -1073,7 +1154,7 @@
             && match self.mode {
                 MonoItemCollectionMode::Eager => true,
                 MonoItemCollectionMode::Lazy => {
-                    self.entry_fn.map(|(id, _)| id) == Some(def_id)
+                    self.entry_fn.and_then(|(id, _)| id.as_local()) == Some(def_id)
                         || self.tcx.is_reachable_non_generic(def_id)
                         || self
                             .tcx
@@ -1175,7 +1256,8 @@
                     let substs =
                         InternalSubsts::for_item(tcx, method.def_id, |param, _| match param.kind {
                             GenericParamDefKind::Lifetime => tcx.lifetimes.re_erased.into(),
-                            GenericParamDefKind::Type { .. } | GenericParamDefKind::Const => {
+                            GenericParamDefKind::Type { .. }
+                            | GenericParamDefKind::Const { .. } => {
                                 trait_ref.substs[param.index as usize]
                             }
                         });
diff --git a/compiler/rustc_mir/src/monomorphize/mod.rs b/compiler/rustc_mir/src/monomorphize/mod.rs
index d2586f0..9ca4b66 100644
--- a/compiler/rustc_mir/src/monomorphize/mod.rs
+++ b/compiler/rustc_mir/src/monomorphize/mod.rs
@@ -8,14 +8,14 @@
 pub mod partitioning;
 pub mod polymorphize;
 
-pub fn custom_coerce_unsize_info<'tcx>(
+fn custom_coerce_unsize_info<'tcx>(
     tcx: TyCtxt<'tcx>,
     source_ty: Ty<'tcx>,
     target_ty: Ty<'tcx>,
 ) -> CustomCoerceUnsized {
     let def_id = tcx.require_lang_item(LangItem::CoerceUnsized, None);
 
-    let trait_ref = ty::Binder::bind(ty::TraitRef {
+    let trait_ref = ty::Binder::dummy(ty::TraitRef {
         def_id,
         substs: tcx.mk_substs_trait(source_ty, &[target_ty.into()]),
     });
diff --git a/compiler/rustc_mir/src/monomorphize/polymorphize.rs b/compiler/rustc_mir/src/monomorphize/polymorphize.rs
index 05b0e3a..30e758c7 100644
--- a/compiler/rustc_mir/src/monomorphize/polymorphize.rs
+++ b/compiler/rustc_mir/src/monomorphize/polymorphize.rs
@@ -299,7 +299,7 @@
                 self.unused_parameters.clear(param.index);
                 ControlFlow::CONTINUE
             }
-            ty::ConstKind::Unevaluated(def, _, Some(p))
+            ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs: _, promoted: Some(p)})
                 // Avoid considering `T` unused when constants are of the form:
                 //   `<Self as Foo<T>>::foo::promoted[p]`
                 if self.def_id == def.did && !self.tcx.generics_of(def.did).has_self =>
@@ -310,10 +310,10 @@
                 self.visit_body(&promoted[p]);
                 ControlFlow::CONTINUE
             }
-            ty::ConstKind::Unevaluated(def, unevaluated_substs, None)
+            ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted: None })
                 if self.tcx.def_kind(def.did) == DefKind::AnonConst =>
             {
-                self.visit_child_body(def.did, unevaluated_substs);
+                self.visit_child_body(def.did, substs);
                 ControlFlow::CONTINUE
             }
             _ => c.super_visit_with(self),
diff --git a/compiler/rustc_mir/src/transform/check_consts/ops.rs b/compiler/rustc_mir/src/transform/check_consts/ops.rs
index a18c1f7..ffeaaf6 100644
--- a/compiler/rustc_mir/src/transform/check_consts/ops.rs
+++ b/compiler/rustc_mir/src/transform/check_consts/ops.rs
@@ -540,12 +540,17 @@
 pub struct UnsizingCast;
 impl NonConstOp for UnsizingCast {
     fn status_in_item(&self, ccx: &ConstCx<'_, '_>) -> Status {
-        mcf_status_in_item(ccx)
+        if ccx.const_kind() != hir::ConstContext::ConstFn {
+            Status::Allowed
+        } else {
+            Status::Unstable(sym::const_fn_unsize)
+        }
     }
 
     fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
-        mcf_build_error(
-            ccx,
+        feature_err(
+            &ccx.tcx.sess.parse_sess,
+            sym::const_fn_unsize,
             span,
             "unsizing casts to types besides slices are not allowed in const fn",
         )
@@ -642,12 +647,17 @@
         }
 
         fn status_in_item(&self, ccx: &ConstCx<'_, '_>) -> Status {
-            mcf_status_in_item(ccx)
+            if ccx.const_kind() != hir::ConstContext::ConstFn {
+                Status::Allowed
+            } else {
+                Status::Unstable(sym::const_fn_trait_bound)
+            }
         }
 
         fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
-            mcf_build_error(
-                ccx,
+            feature_err(
+                &ccx.tcx.sess.parse_sess,
+                sym::const_fn_trait_bound,
                 span,
                 "trait bounds other than `Sized` on const fn parameters are unstable",
             )
@@ -672,21 +682,3 @@
         }
     }
 }
-
-fn mcf_status_in_item(ccx: &ConstCx<'_, '_>) -> Status {
-    if ccx.const_kind() != hir::ConstContext::ConstFn {
-        Status::Allowed
-    } else {
-        Status::Unstable(sym::const_fn)
-    }
-}
-
-fn mcf_build_error(ccx: &ConstCx<'_, 'tcx>, span: Span, msg: &str) -> DiagnosticBuilder<'tcx> {
-    let mut err = struct_span_err!(ccx.tcx.sess, span, E0723, "{}", msg);
-    err.note(
-        "see issue #57563 <https://github.com/rust-lang/rust/issues/57563> \
-             for more information",
-    );
-    err.help("add `#![feature(const_fn)]` to the crate attributes to enable");
-    err
-}
diff --git a/compiler/rustc_mir/src/transform/check_consts/post_drop_elaboration.rs b/compiler/rustc_mir/src/transform/check_consts/post_drop_elaboration.rs
index 1a2d932..057092b 100644
--- a/compiler/rustc_mir/src/transform/check_consts/post_drop_elaboration.rs
+++ b/compiler/rustc_mir/src/transform/check_consts/post_drop_elaboration.rs
@@ -79,7 +79,9 @@
             mir::TerminatorKind::Drop { place: dropped_place, .. } => {
                 let dropped_ty = dropped_place.ty(self.body, self.tcx).ty;
                 if !NeedsDrop::in_any_value_of_ty(self.ccx, dropped_ty) {
-                    return;
+                    bug!(
+                        "Drop elaboration left behind a Drop for a type that does not need dropping"
+                    );
                 }
 
                 if dropped_place.is_indirect() {
@@ -87,6 +89,10 @@
                     return;
                 }
 
+                // Drop elaboration is not precise enough to accept code like
+                // `src/test/ui/consts/control-flow/drop-pass.rs`; e.g., when an `Option<Vec<T>>` is
+                // initialized with `None` and never changed, it still emits drop glue.
+                // Hence we additionally check the qualifs here to allow more code to pass.
                 if self.qualifs.needs_drop(self.ccx, dropped_place.local, location) {
                     // Use the span where the dropped local was declared for the error.
                     let span = self.body.local_decls[dropped_place.local].source_info.span;
diff --git a/compiler/rustc_mir/src/transform/check_consts/qualifs.rs b/compiler/rustc_mir/src/transform/check_consts/qualifs.rs
index 748f65c..ac8c748 100644
--- a/compiler/rustc_mir/src/transform/check_consts/qualifs.rs
+++ b/compiler/rustc_mir/src/transform/check_consts/qualifs.rs
@@ -29,11 +29,11 @@
 /// Normally, we would determine what qualifications apply to each type and error when an illegal
 /// operation is performed on such a type. However, this was found to be too imprecise, especially
 /// in the presence of `enum`s. If only a single variant of an enum has a certain qualification, we
-/// needn't reject code unless it actually constructs and operates on the qualifed variant.
+/// needn't reject code unless it actually constructs and operates on the qualified variant.
 ///
 /// To accomplish this, const-checking and promotion use a value-based analysis (as opposed to a
 /// type-based one). Qualifications propagate structurally across variables: If a local (or a
-/// projection of a local) is assigned a qualifed value, that local itself becomes qualifed.
+/// projection of a local) is assigned a qualified value, that local itself becomes qualified.
 pub trait Qualif {
     /// The name of the file used to debug the dataflow analysis that computes this qualif.
     const ANALYSIS_NAME: &'static str;
@@ -247,7 +247,7 @@
 
     // Check the qualifs of the value of `const` items.
     if let Some(ct) = constant.literal.const_for_ty() {
-        if let ty::ConstKind::Unevaluated(def, _, promoted) = ct.val {
+        if let ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs: _, promoted }) = ct.val {
             assert!(promoted.is_none());
             // Don't peek inside trait associated constants.
             if cx.tcx.trait_of_item(def.did).is_none() {
diff --git a/compiler/rustc_mir/src/transform/check_consts/validation.rs b/compiler/rustc_mir/src/transform/check_consts/validation.rs
index 1ad7b8f..63fc66f 100644
--- a/compiler/rustc_mir/src/transform/check_consts/validation.rs
+++ b/compiler/rustc_mir/src/transform/check_consts/validation.rs
@@ -1,6 +1,6 @@
 //! The `Visitor` responsible for actually checking a `mir::Body` for invalid operations.
 
-use rustc_errors::{struct_span_err, Applicability, Diagnostic, ErrorReported};
+use rustc_errors::{Applicability, Diagnostic, ErrorReported};
 use rustc_hir::def_id::DefId;
 use rustc_hir::{self as hir, HirId, LangItem};
 use rustc_index::bit_set::BitSet;
@@ -234,13 +234,11 @@
             if self.is_const_stable_const_fn() {
                 let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
                 if crate::const_eval::is_parent_const_impl_raw(tcx, hir_id) {
-                    struct_span_err!(
-                        self.ccx.tcx.sess,
-                        self.span,
-                        E0723,
-                        "trait methods cannot be stable const fn"
-                    )
-                    .emit();
+                    self.ccx
+                        .tcx
+                        .sess
+                        .struct_span_err(self.span, "trait methods cannot be stable const fn")
+                        .emit();
                 }
             }
 
@@ -428,7 +426,7 @@
                     ty::PredicateKind::Subtype(_) => {
                         bug!("subtype predicate on function: {:#?}", predicate)
                     }
-                    ty::PredicateKind::Trait(pred, constness) => {
+                    ty::PredicateKind::Trait(pred, _constness) => {
                         if Some(pred.def_id()) == tcx.lang_items().sized_trait() {
                             continue;
                         }
@@ -442,16 +440,7 @@
                                 // arguments when determining importance.
                                 let kind = LocalKind::Arg;
 
-                                if constness == hir::Constness::Const {
-                                    self.check_op_spanned(ops::ty::TraitBound(kind), span);
-                                } else if !tcx.features().const_fn
-                                    || self.ccx.is_const_stable_const_fn()
-                                {
-                                    // HACK: We shouldn't need the conditional above, but trait
-                                    // bounds on containing impl blocks are wrongly being marked as
-                                    // "not-const".
-                                    self.check_op_spanned(ops::ty::TraitBound(kind), span);
-                                }
+                                self.check_op_spanned(ops::ty::TraitBound(kind), span);
                             }
                             // other kinds of bounds are either tautologies
                             // or cause errors in other passes
@@ -850,9 +839,12 @@
                     let obligation = Obligation::new(
                         ObligationCause::dummy(),
                         param_env,
-                        Binder::bind(TraitPredicate {
-                            trait_ref: TraitRef::from_method(tcx, trait_id, substs),
-                        }),
+                        Binder::bind(
+                            TraitPredicate {
+                                trait_ref: TraitRef::from_method(tcx, trait_id, substs),
+                            },
+                            tcx,
+                        ),
                     );
 
                     let implsrc = tcx.infer_ctxt().enter(|infcx| {
diff --git a/compiler/rustc_mir/src/transform/check_packed_ref.rs b/compiler/rustc_mir/src/transform/check_packed_ref.rs
index ee88daa..13b7221 100644
--- a/compiler/rustc_mir/src/transform/check_packed_ref.rs
+++ b/compiler/rustc_mir/src/transform/check_packed_ref.rs
@@ -1,11 +1,18 @@
+use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_middle::mir::visit::{PlaceContext, Visitor};
 use rustc_middle::mir::*;
+use rustc_middle::ty::query::Providers;
 use rustc_middle::ty::{self, TyCtxt};
 use rustc_session::lint::builtin::UNALIGNED_REFERENCES;
+use rustc_span::symbol::sym;
 
 use crate::transform::MirPass;
 use crate::util;
 
+pub(crate) fn provide(providers: &mut Providers) {
+    *providers = Providers { unsafe_derive_on_repr_packed, ..*providers };
+}
+
 pub struct CheckPackedRef;
 
 impl<'tcx> MirPass<'tcx> for CheckPackedRef {
@@ -24,6 +31,41 @@
     source_info: SourceInfo,
 }
 
+fn unsafe_derive_on_repr_packed(tcx: TyCtxt<'_>, def_id: LocalDefId) {
+    let lint_hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
+
+    tcx.struct_span_lint_hir(UNALIGNED_REFERENCES, lint_hir_id, tcx.def_span(def_id), |lint| {
+        // FIXME: when we make this a hard error, this should have its
+        // own error code.
+        let message = if tcx.generics_of(def_id).own_requires_monomorphization() {
+            "`#[derive]` can't be used on a `#[repr(packed)]` struct with \
+             type or const parameters (error E0133)"
+                .to_string()
+        } else {
+            "`#[derive]` can't be used on a `#[repr(packed)]` struct that \
+             does not derive Copy (error E0133)"
+                .to_string()
+        };
+        lint.build(&message).emit()
+    });
+}
+
+fn builtin_derive_def_id(tcx: TyCtxt<'_>, def_id: DefId) -> Option<DefId> {
+    debug!("builtin_derive_def_id({:?})", def_id);
+    if let Some(impl_def_id) = tcx.impl_of_method(def_id) {
+        if tcx.has_attr(impl_def_id, sym::automatically_derived) {
+            debug!("builtin_derive_def_id({:?}) - is {:?}", def_id, impl_def_id);
+            Some(impl_def_id)
+        } else {
+            debug!("builtin_derive_def_id({:?}) - not automatically derived", def_id);
+            None
+        }
+    } else {
+        debug!("builtin_derive_def_id({:?}) - not a method", def_id);
+        None
+    }
+}
+
 impl<'a, 'tcx> Visitor<'tcx> for PackedRefChecker<'a, 'tcx> {
     fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location) {
         // Make sure we know where in the MIR we are.
@@ -40,26 +82,33 @@
     fn visit_place(&mut self, place: &Place<'tcx>, context: PlaceContext, _location: Location) {
         if context.is_borrow() {
             if util::is_disaligned(self.tcx, self.body, self.param_env, *place) {
-                let source_info = self.source_info;
-                let lint_root = self.body.source_scopes[source_info.scope]
-                    .local_data
-                    .as_ref()
-                    .assert_crate_local()
-                    .lint_root;
-                self.tcx.struct_span_lint_hir(
-                    UNALIGNED_REFERENCES,
-                    lint_root,
-                    source_info.span,
-                    |lint| {
-                        lint.build("reference to packed field is unaligned")
-                            .note(
-                                "fields of packed structs are not properly aligned, and creating \
-                                a misaligned reference is undefined behavior (even if that \
-                                reference is never dereferenced)",
-                            )
-                            .emit()
-                    },
-                );
+                let def_id = self.body.source.instance.def_id();
+                if let Some(impl_def_id) = builtin_derive_def_id(self.tcx, def_id) {
+                    // If a method is defined in the local crate,
+                    // the impl containing that method should also be.
+                    self.tcx.ensure().unsafe_derive_on_repr_packed(impl_def_id.expect_local());
+                } else {
+                    let source_info = self.source_info;
+                    let lint_root = self.body.source_scopes[source_info.scope]
+                        .local_data
+                        .as_ref()
+                        .assert_crate_local()
+                        .lint_root;
+                    self.tcx.struct_span_lint_hir(
+                        UNALIGNED_REFERENCES,
+                        lint_root,
+                        source_info.span,
+                        |lint| {
+                            lint.build("reference to packed field is unaligned")
+                                .note(
+                                    "fields of packed structs are not properly aligned, and creating \
+                                    a misaligned reference is undefined behavior (even if that \
+                                    reference is never dereferenced)",
+                                )
+                                .emit()
+                        },
+                    );
+                }
             }
         }
     }
diff --git a/compiler/rustc_mir/src/transform/check_unsafety.rs b/compiler/rustc_mir/src/transform/check_unsafety.rs
index 532d201..955be8c 100644
--- a/compiler/rustc_mir/src/transform/check_unsafety.rs
+++ b/compiler/rustc_mir/src/transform/check_unsafety.rs
@@ -10,20 +10,15 @@
 use rustc_middle::ty::cast::CastTy;
 use rustc_middle::ty::query::Providers;
 use rustc_middle::ty::{self, TyCtxt};
-use rustc_session::lint::builtin::{SAFE_PACKED_BORROWS, UNSAFE_OP_IN_UNSAFE_FN, UNUSED_UNSAFE};
+use rustc_session::lint::builtin::{UNSAFE_OP_IN_UNSAFE_FN, UNUSED_UNSAFE};
 use rustc_session::lint::Level;
-use rustc_span::symbol::sym;
 
 use std::ops::Bound;
 
-use crate::const_eval::is_min_const_fn;
-use crate::util;
-
 pub struct UnsafetyChecker<'a, 'tcx> {
     body: &'a Body<'tcx>,
     body_did: LocalDefId,
     const_context: bool,
-    min_const_fn: bool,
     violations: Vec<UnsafetyViolation>,
     source_info: SourceInfo,
     tcx: TyCtxt<'tcx>,
@@ -36,21 +31,15 @@
 impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> {
     fn new(
         const_context: bool,
-        min_const_fn: bool,
         body: &'a Body<'tcx>,
         body_did: LocalDefId,
         tcx: TyCtxt<'tcx>,
         param_env: ty::ParamEnv<'tcx>,
     ) -> Self {
-        // sanity check
-        if min_const_fn {
-            assert!(const_context);
-        }
         Self {
             body,
             body_did,
             const_context,
-            min_const_fn,
             violations: vec![],
             source_info: SourceInfo::outermost(body.span),
             tcx,
@@ -86,7 +75,7 @@
                 let sig = func_ty.fn_sig(self.tcx);
                 if let hir::Unsafety::Unsafe = sig.unsafety() {
                     self.require_unsafe(
-                        UnsafetyViolationKind::GeneralAndConstFn,
+                        UnsafetyViolationKind::General,
                         UnsafetyViolationDetails::CallToUnsafeFunction,
                     )
                 }
@@ -136,7 +125,7 @@
                     match self.tcx.layout_scalar_valid_range(def.did) {
                         (Bound::Unbounded, Bound::Unbounded) => {}
                         _ => self.require_unsafe(
-                            UnsafetyViolationKind::GeneralAndConstFn,
+                            UnsafetyViolationKind::General,
                             UnsafetyViolationDetails::InitializingTypeWith,
                         ),
                     }
@@ -182,18 +171,6 @@
             self.check_mut_borrowing_layout_constrained_field(*place, context.is_mutating_use());
         }
 
-        // Check for borrows to packed fields.
-        // `is_disaligned` already traverses the place to consider all projections after the last
-        // `Deref`, so this only needs to be called once at the top level.
-        if context.is_borrow() {
-            if util::is_disaligned(self.tcx, self.body, self.param_env, *place) {
-                self.require_unsafe(
-                    UnsafetyViolationKind::BorrowPacked,
-                    UnsafetyViolationDetails::BorrowOfPackedField,
-                );
-            }
-        }
-
         // Some checks below need the extra metainfo of the local declaration.
         let decl = &self.body.local_decls[place.local];
 
@@ -227,7 +204,7 @@
                 let base_ty = base.ty(self.body, self.tcx).ty;
                 if base_ty.is_unsafe_ptr() {
                     self.require_unsafe(
-                        UnsafetyViolationKind::GeneralAndConstFn,
+                        UnsafetyViolationKind::General,
                         UnsafetyViolationDetails::DerefOfRawPointer,
                     )
                 }
@@ -272,7 +249,7 @@
                         );
                     if !nodrop {
                         self.require_unsafe(
-                            UnsafetyViolationKind::GeneralAndConstFn,
+                            UnsafetyViolationKind::General,
                             UnsafetyViolationDetails::AssignToDroppingUnionField,
                         );
                     } else {
@@ -280,7 +257,7 @@
                     }
                 } else {
                     self.require_unsafe(
-                        UnsafetyViolationKind::GeneralAndConstFn,
+                        UnsafetyViolationKind::General,
                         UnsafetyViolationDetails::AccessToUnionField,
                     )
                 }
@@ -291,6 +268,9 @@
 
 impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> {
     fn require_unsafe(&mut self, kind: UnsafetyViolationKind, details: UnsafetyViolationDetails) {
+        // Violations can turn out to be `UnsafeFn` during analysis, but they should not start out as such.
+        assert_ne!(kind, UnsafetyViolationKind::UnsafeFn);
+
         let source_info = self.source_info;
         let lint_root = self.body.source_scopes[self.source_info.scope]
             .local_data
@@ -317,25 +297,14 @@
             // `unsafe` blocks are required in safe code
             Safety::Safe => {
                 for violation in violations {
-                    let mut violation = *violation;
                     match violation.kind {
-                        UnsafetyViolationKind::GeneralAndConstFn
-                        | UnsafetyViolationKind::General => {}
-                        UnsafetyViolationKind::BorrowPacked => {
-                            if self.min_const_fn {
-                                // const fns don't need to be backwards compatible and can
-                                // emit these violations as a hard error instead of a backwards
-                                // compat lint
-                                violation.kind = UnsafetyViolationKind::General;
-                            }
-                        }
-                        UnsafetyViolationKind::UnsafeFn
-                        | UnsafetyViolationKind::UnsafeFnBorrowPacked => {
+                        UnsafetyViolationKind::General => {}
+                        UnsafetyViolationKind::UnsafeFn => {
                             bug!("`UnsafetyViolationKind::UnsafeFn` in an `Safe` context")
                         }
                     }
-                    if !self.violations.contains(&violation) {
-                        self.violations.push(violation)
+                    if !self.violations.contains(violation) {
+                        self.violations.push(*violation)
                     }
                 }
                 false
@@ -345,11 +314,7 @@
                 for violation in violations {
                     let mut violation = *violation;
 
-                    if violation.kind == UnsafetyViolationKind::BorrowPacked {
-                        violation.kind = UnsafetyViolationKind::UnsafeFnBorrowPacked;
-                    } else {
-                        violation.kind = UnsafetyViolationKind::UnsafeFn;
-                    }
+                    violation.kind = UnsafetyViolationKind::UnsafeFn;
                     if !self.violations.contains(&violation) {
                         self.violations.push(violation)
                     }
@@ -362,31 +327,6 @@
                 if !violations.is_empty() {
                     self.used_unsafe.insert(hir_id);
                 }
-                // only some unsafety is allowed in const fn
-                if self.min_const_fn {
-                    for violation in violations {
-                        match violation.kind {
-                            // these unsafe things are stable in const fn
-                            UnsafetyViolationKind::GeneralAndConstFn => {}
-                            // these things are forbidden in const fns
-                            UnsafetyViolationKind::General
-                            | UnsafetyViolationKind::BorrowPacked => {
-                                let mut violation = *violation;
-                                // const fns don't need to be backwards compatible and can
-                                // emit these violations as a hard error instead of a backwards
-                                // compat lint
-                                violation.kind = UnsafetyViolationKind::General;
-                                if !self.violations.contains(&violation) {
-                                    self.violations.push(violation)
-                                }
-                            }
-                            UnsafetyViolationKind::UnsafeFn
-                            | UnsafetyViolationKind::UnsafeFnBorrowPacked => bug!(
-                                "`UnsafetyViolationKind::UnsafeFn` in an `ExplicitUnsafe` context"
-                            ),
-                        }
-                    }
-                }
                 true
             }
         };
@@ -424,7 +364,7 @@
                             } else {
                                 continue;
                             };
-                            self.require_unsafe(UnsafetyViolationKind::GeneralAndConstFn, details);
+                            self.require_unsafe(UnsafetyViolationKind::General, details);
                         }
                     }
                 }
@@ -442,7 +382,7 @@
         // Is `callee_features` a subset of `calling_features`?
         if !callee_features.iter().all(|feature| self_features.contains(feature)) {
             self.require_unsafe(
-                UnsafetyViolationKind::GeneralAndConstFn,
+                UnsafetyViolationKind::General,
                 UnsafetyViolationDetails::CallToFunctionWith,
             )
         }
@@ -464,7 +404,6 @@
                 ty::WithOptConstParam { did, const_param_did: Some(param_did) },
             )
         },
-        unsafe_derive_on_repr_packed,
         ..*providers
     };
 }
@@ -525,15 +464,12 @@
     let param_env = tcx.param_env(def.did);
 
     let id = tcx.hir().local_def_id_to_hir_id(def.did);
-    let (const_context, min_const_fn) = match tcx.hir().body_owner_kind(id) {
-        hir::BodyOwnerKind::Closure => (false, false),
-        hir::BodyOwnerKind::Fn => {
-            (tcx.is_const_fn_raw(def.did.to_def_id()), is_min_const_fn(tcx, def.did.to_def_id()))
-        }
-        hir::BodyOwnerKind::Const | hir::BodyOwnerKind::Static(_) => (true, false),
+    let const_context = match tcx.hir().body_owner_kind(id) {
+        hir::BodyOwnerKind::Closure => false,
+        hir::BodyOwnerKind::Fn => tcx.is_const_fn_raw(def.did.to_def_id()),
+        hir::BodyOwnerKind::Const | hir::BodyOwnerKind::Static(_) => true,
     };
-    let mut checker =
-        UnsafetyChecker::new(const_context, min_const_fn, body, def.did, tcx, param_env);
+    let mut checker = UnsafetyChecker::new(const_context, body, def.did, tcx, param_env);
     checker.visit_body(&body);
 
     check_unused_unsafe(tcx, def.did, &checker.used_unsafe, &mut checker.inherited_blocks);
@@ -544,25 +480,6 @@
     })
 }
 
-fn unsafe_derive_on_repr_packed(tcx: TyCtxt<'_>, def_id: LocalDefId) {
-    let lint_hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
-
-    tcx.struct_span_lint_hir(SAFE_PACKED_BORROWS, lint_hir_id, tcx.def_span(def_id), |lint| {
-        // FIXME: when we make this a hard error, this should have its
-        // own error code.
-        let message = if tcx.generics_of(def_id).own_requires_monomorphization() {
-            "`#[derive]` can't be used on a `#[repr(packed)]` struct with \
-             type or const parameters (error E0133)"
-                .to_string()
-        } else {
-            "`#[derive]` can't be used on a `#[repr(packed)]` struct that \
-             does not derive Copy (error E0133)"
-                .to_string()
-        };
-        lint.build(&message).emit()
-    });
-}
-
 /// Returns the `HirId` for an enclosing scope that is also `unsafe`.
 fn is_enclosed(
     tcx: TyCtxt<'_>,
@@ -609,22 +526,6 @@
     });
 }
 
-fn builtin_derive_def_id(tcx: TyCtxt<'_>, def_id: DefId) -> Option<DefId> {
-    debug!("builtin_derive_def_id({:?})", def_id);
-    if let Some(impl_def_id) = tcx.impl_of_method(def_id) {
-        if tcx.has_attr(impl_def_id, sym::automatically_derived) {
-            debug!("builtin_derive_def_id({:?}) - is {:?}", def_id, impl_def_id);
-            Some(impl_def_id)
-        } else {
-            debug!("builtin_derive_def_id({:?}) - not automatically derived", def_id);
-            None
-        }
-    } else {
-        debug!("builtin_derive_def_id({:?}) - not a method", def_id);
-        None
-    }
-}
-
 pub fn check_unsafety(tcx: TyCtxt<'_>, def_id: LocalDefId) {
     debug!("check_unsafety({:?})", def_id);
 
@@ -643,7 +544,7 @@
             if unsafe_op_in_unsafe_fn_allowed(tcx, lint_root) { " function or" } else { "" };
 
         match kind {
-            UnsafetyViolationKind::GeneralAndConstFn | UnsafetyViolationKind::General => {
+            UnsafetyViolationKind::General => {
                 // once
                 struct_span_err!(
                     tcx.sess,
@@ -657,27 +558,6 @@
                 .note(note)
                 .emit();
             }
-            UnsafetyViolationKind::BorrowPacked => {
-                if let Some(impl_def_id) = builtin_derive_def_id(tcx, def_id.to_def_id()) {
-                    // If a method is defined in the local crate,
-                    // the impl containing that method should also be.
-                    tcx.ensure().unsafe_derive_on_repr_packed(impl_def_id.expect_local());
-                } else {
-                    tcx.struct_span_lint_hir(
-                        SAFE_PACKED_BORROWS,
-                        lint_root,
-                        source_info.span,
-                        |lint| {
-                            lint.build(&format!(
-                                "{} is unsafe and requires unsafe{} block (error E0133)",
-                                description, unsafe_fn_msg,
-                            ))
-                            .note(note)
-                            .emit()
-                        },
-                    )
-                }
-            }
             UnsafetyViolationKind::UnsafeFn => tcx.struct_span_lint_hir(
                 UNSAFE_OP_IN_UNSAFE_FN,
                 lint_root,
@@ -692,35 +572,6 @@
                     .emit();
                 },
             ),
-            UnsafetyViolationKind::UnsafeFnBorrowPacked => {
-                // When `unsafe_op_in_unsafe_fn` is disallowed, the behavior of safe and unsafe functions
-                // should be the same in terms of warnings and errors. Therefore, with `#[warn(safe_packed_borrows)]`,
-                // a safe packed borrow should emit a warning *but not an error* in an unsafe function,
-                // just like in a safe function, even if `unsafe_op_in_unsafe_fn` is `deny`.
-                //
-                // Also, `#[warn(unsafe_op_in_unsafe_fn)]` can't cause any new errors. Therefore, with
-                // `#[deny(safe_packed_borrows)]` and `#[warn(unsafe_op_in_unsafe_fn)]`, a packed borrow
-                // should only issue a warning for the sake of backwards compatibility.
-                //
-                // The solution those 2 expectations is to always take the minimum of both lints.
-                // This prevent any new errors (unless both lints are explicitly set to `deny`).
-                let lint = if tcx.lint_level_at_node(SAFE_PACKED_BORROWS, lint_root).0
-                    <= tcx.lint_level_at_node(UNSAFE_OP_IN_UNSAFE_FN, lint_root).0
-                {
-                    SAFE_PACKED_BORROWS
-                } else {
-                    UNSAFE_OP_IN_UNSAFE_FN
-                };
-                tcx.struct_span_lint_hir(&lint, lint_root, source_info.span, |lint| {
-                    lint.build(&format!(
-                        "{} is unsafe and requires unsafe block (error E0133)",
-                        description,
-                    ))
-                    .span_label(source_info.span, description)
-                    .note(note)
-                    .emit();
-                })
-            }
         }
     }
 
diff --git a/compiler/rustc_mir/src/transform/const_prop.rs b/compiler/rustc_mir/src/transform/const_prop.rs
index cc8669d..5968bbb 100644
--- a/compiler/rustc_mir/src/transform/const_prop.rs
+++ b/compiler/rustc_mir/src/transform/const_prop.rs
@@ -13,9 +13,9 @@
     MutVisitor, MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor,
 };
 use rustc_middle::mir::{
-    AssertKind, BasicBlock, BinOp, Body, ClearCrossCrate, Constant, ConstantKind, Local, LocalDecl,
-    LocalKind, Location, Operand, Place, Rvalue, SourceInfo, SourceScope, SourceScopeData,
-    Statement, StatementKind, Terminator, TerminatorKind, UnOp, RETURN_PLACE,
+    AssertKind, BasicBlock, BinOp, Body, Constant, ConstantKind, Local, LocalDecl, LocalKind,
+    Location, Operand, Place, Rvalue, SourceInfo, SourceScope, SourceScopeData, Statement,
+    StatementKind, Terminator, TerminatorKind, UnOp, RETURN_PLACE,
 };
 use rustc_middle::ty::layout::{HasTyCtxt, LayoutError, TyAndLayout};
 use rustc_middle::ty::subst::{InternalSubsts, Subst};
@@ -440,18 +440,7 @@
     }
 
     fn lint_root(&self, source_info: SourceInfo) -> Option<HirId> {
-        let mut data = &self.source_scopes[source_info.scope];
-        // FIXME(oli-obk): we should be able to just walk the `inlined_parent_scope`, but it
-        // does not work as I thought it would. Needs more investigation and documentation.
-        while data.inlined.is_some() {
-            trace!(?data);
-            data = &self.source_scopes[data.parent_scope.unwrap()];
-        }
-        trace!(?data);
-        match &data.local_data {
-            ClearCrossCrate::Set(data) => Some(data.lint_root),
-            ClearCrossCrate::Clear => None,
-        }
+        source_info.scope.lint_root(&self.source_scopes)
     }
 
     fn use_ecx<F, T>(&mut self, f: F) -> Option<T>
@@ -491,7 +480,11 @@
                     let lint_only = match c.literal {
                         ConstantKind::Ty(ct) => match ct.val {
                             // Promoteds must lint and not error as the user didn't ask for them
-                            ConstKind::Unevaluated(_, _, Some(_)) => true,
+                            ConstKind::Unevaluated(ty::Unevaluated {
+                                def: _,
+                                substs: _,
+                                promoted: Some(_),
+                            }) => true,
                             // Out of backwards compatibility we cannot report hard errors in unused
                             // generic functions using associated constants of the generic parameters.
                             _ => c.literal.needs_subst(),
diff --git a/compiler/rustc_mir/src/transform/coverage/debug.rs b/compiler/rustc_mir/src/transform/coverage/debug.rs
index aabfee5..4836148 100644
--- a/compiler/rustc_mir/src/transform/coverage/debug.rs
+++ b/compiler/rustc_mir/src/transform/coverage/debug.rs
@@ -121,6 +121,7 @@
 use rustc_middle::mir::{self, BasicBlock, TerminatorKind};
 use rustc_middle::ty::TyCtxt;
 
+use std::iter;
 use std::lazy::SyncOnceCell;
 
 pub const NESTED_INDENT: &str = "    ";
@@ -703,9 +704,7 @@
         let edge_counters = from_terminator
             .successors()
             .map(|&successor_bb| graphviz_data.get_edge_counter(from_bcb, successor_bb));
-        edge_labels
-            .iter()
-            .zip(edge_counters)
+        iter::zip(&edge_labels, edge_counters)
             .map(|(label, some_counter)| {
                 if let Some(counter) = some_counter {
                     format!("{}\n{}", label, debug_counters.format_counter(counter))
@@ -817,7 +816,7 @@
     sections
 }
 
-/// Returns a simple string representation of a `TerminatorKind` variant, indenpendent of any
+/// Returns a simple string representation of a `TerminatorKind` variant, independent of any
 /// values it might hold.
 pub(super) fn term_type(kind: &TerminatorKind<'tcx>) -> &'static str {
     match kind {
diff --git a/compiler/rustc_mir/src/transform/coverage/mod.rs b/compiler/rustc_mir/src/transform/coverage/mod.rs
index 93133e9..eaeb442 100644
--- a/compiler/rustc_mir/src/transform/coverage/mod.rs
+++ b/compiler/rustc_mir/src/transform/coverage/mod.rs
@@ -23,6 +23,7 @@
 use rustc_middle::hir;
 use rustc_middle::hir::map::blocks::FnLikeNode;
 use rustc_middle::ich::StableHashingContext;
+use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
 use rustc_middle::mir::coverage::*;
 use rustc_middle::mir::{
     self, BasicBlock, BasicBlockData, Coverage, SourceInfo, Statement, StatementKind, Terminator,
@@ -87,6 +88,11 @@
             _ => {}
         }
 
+        let codegen_fn_attrs = tcx.codegen_fn_attrs(mir_source.def_id());
+        if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::NO_COVERAGE) {
+            return;
+        }
+
         trace!("InstrumentCoverage starting for {:?}", mir_source.def_id());
         Instrumentor::new(&self.name(), tcx, mir_body).inject_counters();
         trace!("InstrumentCoverage starting for {:?}", mir_source.def_id());
@@ -111,7 +117,8 @@
         let body_span = hir_body.value.span;
         let source_file = source_map.lookup_source_file(body_span.lo());
         let fn_sig_span = match some_fn_sig.filter(|fn_sig| {
-            Lrc::ptr_eq(&source_file, &source_map.lookup_source_file(fn_sig.span.hi()))
+            fn_sig.span.ctxt() == body_span.ctxt()
+                && Lrc::ptr_eq(&source_file, &source_map.lookup_source_file(fn_sig.span.lo()))
         }) {
             Some(fn_sig) => fn_sig.span.with_hi(body_span.lo()),
             None => body_span.shrink_to_lo(),
diff --git a/compiler/rustc_mir/src/transform/coverage/query.rs b/compiler/rustc_mir/src/transform/coverage/query.rs
index de8447f..2ba9d1b 100644
--- a/compiler/rustc_mir/src/transform/coverage/query.rs
+++ b/compiler/rustc_mir/src/transform/coverage/query.rs
@@ -6,10 +6,9 @@
 use rustc_middle::ty::{self, TyCtxt};
 use rustc_span::def_id::DefId;
 
-/// The `query` provider for `CoverageInfo`, requested by `codegen_coverage()` (to inject each
-/// counter) and `FunctionCoverage::new()` (to extract the coverage map metadata from the MIR).
+/// A `query` provider for retrieving coverage information injected into MIR.
 pub(crate) fn provide(providers: &mut Providers) {
-    providers.coverageinfo = |tcx, def_id| coverageinfo_from_mir(tcx, def_id);
+    providers.coverageinfo = |tcx, def_id| coverageinfo(tcx, def_id);
     providers.covered_file_name = |tcx, def_id| covered_file_name(tcx, def_id);
     providers.covered_code_regions = |tcx, def_id| covered_code_regions(tcx, def_id);
 }
@@ -121,7 +120,7 @@
     }
 }
 
-fn coverageinfo_from_mir<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> CoverageInfo {
+fn coverageinfo<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> CoverageInfo {
     let mir_body = mir_body(tcx, def_id);
 
     let mut coverage_visitor = CoverageVisitor {
@@ -139,29 +138,22 @@
 }
 
 fn covered_file_name<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> Option<Symbol> {
-    let body = mir_body(tcx, def_id);
-    for bb_data in body.basic_blocks().iter() {
-        for statement in bb_data.statements.iter() {
-            if let StatementKind::Coverage(box ref coverage) = statement.kind {
-                if let Some(code_region) = coverage.code_region.as_ref() {
-                    if is_inlined(body, statement) {
-                        continue;
+    if tcx.is_mir_available(def_id) {
+        let body = mir_body(tcx, def_id);
+        for bb_data in body.basic_blocks().iter() {
+            for statement in bb_data.statements.iter() {
+                if let StatementKind::Coverage(box ref coverage) = statement.kind {
+                    if let Some(code_region) = coverage.code_region.as_ref() {
+                        if is_inlined(body, statement) {
+                            continue;
+                        }
+                        return Some(code_region.file_name);
                     }
-                    return Some(code_region.file_name);
                 }
             }
         }
     }
-    None
-}
-
-/// This function ensures we obtain the correct MIR for the given item irrespective of
-/// whether that means const mir or runtime mir. For `const fn` this opts for runtime
-/// mir.
-fn mir_body<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> &'tcx mir::Body<'tcx> {
-    let id = ty::WithOptConstParam::unknown(def_id);
-    let def = ty::InstanceDef::Item(id);
-    tcx.instance_mir(def)
+    return None;
 }
 
 fn covered_code_regions<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> Vec<&'tcx CodeRegion> {
@@ -188,3 +180,12 @@
     let scope_data = &body.source_scopes[statement.source_info.scope];
     scope_data.inlined.is_some() || scope_data.inlined_parent_scope.is_some()
 }
+
+/// This function ensures we obtain the correct MIR for the given item irrespective of
+/// whether that means const mir or runtime mir. For `const fn` this opts for runtime
+/// mir.
+fn mir_body<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> &'tcx mir::Body<'tcx> {
+    let id = ty::WithOptConstParam::unknown(def_id);
+    let def = ty::InstanceDef::Item(id);
+    tcx.instance_mir(def)
+}
diff --git a/compiler/rustc_mir/src/transform/coverage/spans.rs b/compiler/rustc_mir/src/transform/coverage/spans.rs
index e7097ce..2041109 100644
--- a/compiler/rustc_mir/src/transform/coverage/spans.rs
+++ b/compiler/rustc_mir/src/transform/coverage/spans.rs
@@ -11,7 +11,7 @@
 use rustc_middle::ty::TyCtxt;
 
 use rustc_span::source_map::original_sp;
-use rustc_span::{BytePos, Span, SyntaxContext};
+use rustc_span::{BytePos, Span};
 
 use std::cmp::Ordering;
 
@@ -240,7 +240,7 @@
     /// to be).
     pub(super) fn generate_coverage_spans(
         mir_body: &'a mir::Body<'tcx>,
-        fn_sig_span: Span,
+        fn_sig_span: Span, // Ensured to be same SourceFile and SyntaxContext as `body_span`
         body_span: Span,
         basic_coverage_blocks: &'a CoverageGraph,
     ) -> Vec<CoverageSpan> {
@@ -683,10 +683,10 @@
         // and `_1` is the `Place` for `somenum`.
         //
         // If and when the Issue is resolved, remove this special case match pattern:
-        StatementKind::FakeRead(cause, _) if cause == FakeReadCause::ForGuardBinding => None,
+        StatementKind::FakeRead(box (cause, _)) if cause == FakeReadCause::ForGuardBinding => None,
 
         // Retain spans from all other statements
-        StatementKind::FakeRead(_, _) // Not including `ForGuardBinding`
+        StatementKind::FakeRead(box (_, _)) // Not including `ForGuardBinding`
         | StatementKind::CopyNonOverlapping(..)
         | StatementKind::Assign(_)
         | StatementKind::SetDiscriminant { .. }
@@ -717,11 +717,21 @@
         | TerminatorKind::FalseEdge { .. }
         | TerminatorKind::Goto { .. } => None,
 
+        // Call `func` operand can have a more specific span when part of a chain of calls
+        | TerminatorKind::Call { ref func, .. } => {
+            let mut span = terminator.source_info.span;
+            if let mir::Operand::Constant(box constant) = func {
+                if constant.span.lo() > span.lo() {
+                    span = span.with_lo(constant.span.lo());
+                }
+            }
+            Some(function_source_span(span, body_span))
+        }
+
         // Retain spans from all other terminators
         TerminatorKind::Resume
         | TerminatorKind::Abort
         | TerminatorKind::Return
-        | TerminatorKind::Call { .. }
         | TerminatorKind::Yield { .. }
         | TerminatorKind::GeneratorDrop
         | TerminatorKind::FalseUnwind { .. }
@@ -733,6 +743,6 @@
 
 #[inline]
 fn function_source_span(span: Span, body_span: Span) -> Span {
-    let span = original_sp(span, body_span).with_ctxt(SyntaxContext::root());
+    let span = original_sp(span, body_span).with_ctxt(body_span.ctxt());
     if body_span.contains(span) { span } else { body_span }
 }
diff --git a/compiler/rustc_mir/src/transform/coverage/tests.rs b/compiler/rustc_mir/src/transform/coverage/tests.rs
index 7a9bfaa..dee1124 100644
--- a/compiler/rustc_mir/src/transform/coverage/tests.rs
+++ b/compiler/rustc_mir/src/transform/coverage/tests.rs
@@ -17,7 +17,7 @@
 //! Also note, some basic features of `Span` also rely on the `Span`s own "session globals", which
 //! are unrelated to the `TyCtxt` global. Without initializing the `Span` session globals, some
 //! basic, coverage-specific features would be impossible to test, but thankfully initializing these
-//! globals is comparitively simpler. The easiest way is to wrap the test in a closure argument
+//! globals is comparatively simpler. The easiest way is to wrap the test in a closure argument
 //! to: `rustc_span::with_default_session_globals(|| { test_here(); })`.
 
 use super::counters;
diff --git a/compiler/rustc_mir/src/transform/deduplicate_blocks.rs b/compiler/rustc_mir/src/transform/deduplicate_blocks.rs
index e102512..c41e71e 100644
--- a/compiler/rustc_mir/src/transform/deduplicate_blocks.rs
+++ b/compiler/rustc_mir/src/transform/deduplicate_blocks.rs
@@ -1,7 +1,7 @@
 //! This pass finds basic blocks that are completely equal,
 //! and replaces all uses with just one of them.
 
-use std::{collections::hash_map::Entry, hash::Hash, hash::Hasher};
+use std::{collections::hash_map::Entry, hash::Hash, hash::Hasher, iter};
 
 use crate::transform::MirPass;
 
@@ -115,11 +115,7 @@
     fn eq(&self, other: &Self) -> bool {
         self.basic_block_data.statements.len() == other.basic_block_data.statements.len()
             && &self.basic_block_data.terminator().kind == &other.basic_block_data.terminator().kind
-            && self
-                .basic_block_data
-                .statements
-                .iter()
-                .zip(&other.basic_block_data.statements)
+            && iter::zip(&self.basic_block_data.statements, &other.basic_block_data.statements)
                 .all(|(x, y)| statement_eq(&x.kind, &y.kind))
     }
 }
diff --git a/compiler/rustc_mir/src/transform/dest_prop.rs b/compiler/rustc_mir/src/transform/dest_prop.rs
index 6656dea..29df86c 100644
--- a/compiler/rustc_mir/src/transform/dest_prop.rs
+++ b/compiler/rustc_mir/src/transform/dest_prop.rs
@@ -720,9 +720,6 @@
                                 }
                             }
                         }
-                        InlineAsmOperand::Const { value } => {
-                            assert!(value.place().is_none());
-                        }
                         InlineAsmOperand::InOut {
                             reg: _,
                             late: _,
@@ -731,6 +728,7 @@
                         }
                         | InlineAsmOperand::In { reg: _, value: _ }
                         | InlineAsmOperand::Out { reg: _, late: _, place: None }
+                        | InlineAsmOperand::Const { value: _ }
                         | InlineAsmOperand::SymFn { value: _ }
                         | InlineAsmOperand::SymStatic { def_id: _ } => {}
                     }
diff --git a/compiler/rustc_mir/src/transform/generator.rs b/compiler/rustc_mir/src/transform/generator.rs
index c85e9b9..003003a 100644
--- a/compiler/rustc_mir/src/transform/generator.rs
+++ b/compiler/rustc_mir/src/transform/generator.rs
@@ -751,9 +751,10 @@
             span_bug!(
                 body.span,
                 "Broken MIR: generator contains type {} in MIR, \
-                       but typeck only knows about {}",
-                decl.ty,
-                witness,
+                       but typeck only knows about {} and {:?}",
+                decl_ty,
+                allowed,
+                allowed_upvars
             );
         }
     }
diff --git a/compiler/rustc_mir/src/transform/inline.rs b/compiler/rustc_mir/src/transform/inline.rs
index 12fdbd6..b6f8076 100644
--- a/compiler/rustc_mir/src/transform/inline.rs
+++ b/compiler/rustc_mir/src/transform/inline.rs
@@ -630,7 +630,7 @@
                 caller_body.required_consts.extend(
                     callee_body.required_consts.iter().copied().filter(|&ct| {
                         match ct.literal.const_for_ty() {
-                            Some(ct) => matches!(ct.val, ConstKind::Unevaluated(_, _, _)),
+                            Some(ct) => matches!(ct.val, ConstKind::Unevaluated(_)),
                             None => true,
                         }
                     }),
diff --git a/compiler/rustc_mir/src/transform/match_branches.rs b/compiler/rustc_mir/src/transform/match_branches.rs
index d04a701..f7a9835 100644
--- a/compiler/rustc_mir/src/transform/match_branches.rs
+++ b/compiler/rustc_mir/src/transform/match_branches.rs
@@ -1,6 +1,7 @@
 use crate::transform::MirPass;
 use rustc_middle::mir::*;
 use rustc_middle::ty::TyCtxt;
+use std::iter;
 
 use super::simplify::simplify_cfg;
 
@@ -83,7 +84,7 @@
             if first_stmts.len() != scnd_stmts.len() {
                 continue;
             }
-            for (f, s) in first_stmts.iter().zip(scnd_stmts.iter()) {
+            for (f, s) in iter::zip(first_stmts, scnd_stmts) {
                 match (&f.kind, &s.kind) {
                     // If two statements are exactly the same, we can optimize.
                     (f_s, s_s) if f_s == s_s => {}
@@ -113,7 +114,7 @@
             // and bb_idx has a different terminator from both of them.
             let (from, first, second) = bbs.pick3_mut(bb_idx, first, second);
 
-            let new_stmts = first.statements.iter().zip(second.statements.iter()).map(|(f, s)| {
+            let new_stmts = iter::zip(&first.statements, &second.statements).map(|(f, s)| {
                 match (&f.kind, &s.kind) {
                     (f_s, s_s) if f_s == s_s => (*f).clone(),
 
diff --git a/compiler/rustc_mir/src/transform/mod.rs b/compiler/rustc_mir/src/transform/mod.rs
index 1354644..5c49ee6 100644
--- a/compiler/rustc_mir/src/transform/mod.rs
+++ b/compiler/rustc_mir/src/transform/mod.rs
@@ -44,6 +44,7 @@
 pub mod remove_noop_landing_pads;
 pub mod remove_storage_markers;
 pub mod remove_unneeded_drops;
+pub mod remove_zsts;
 pub mod required_consts;
 pub mod rustc_peek;
 pub mod simplify;
@@ -58,6 +59,7 @@
 
 pub(crate) fn provide(providers: &mut Providers) {
     self::check_unsafety::provide(providers);
+    self::check_packed_ref::provide(providers);
     *providers = Providers {
         mir_keys,
         mir_const,
@@ -313,11 +315,8 @@
         &simplify::SimplifyCfg::new("promote-consts"),
     ];
 
-    let opt_coverage: &[&dyn MirPass<'tcx>] = if tcx.sess.opts.debugging_opts.instrument_coverage {
-        &[&coverage::InstrumentCoverage]
-    } else {
-        &[]
-    };
+    let opt_coverage: &[&dyn MirPass<'tcx>] =
+        if tcx.sess.instrument_coverage() { &[&coverage::InstrumentCoverage] } else { &[] };
 
     run_passes(tcx, &mut body, MirPhase::ConstPromotion, &[promote, opt_coverage]);
 
@@ -494,6 +493,7 @@
     // The main optimizations that we do on MIR.
     let optimizations: &[&dyn MirPass<'tcx>] = &[
         &remove_storage_markers::RemoveStorageMarkers,
+        &remove_zsts::RemoveZsts,
         &const_goto::ConstGoto,
         &remove_unneeded_drops::RemoveUnneededDrops,
         &match_branches::MatchBranchSimplification,
diff --git a/compiler/rustc_mir/src/transform/promote_consts.rs b/compiler/rustc_mir/src/transform/promote_consts.rs
index 7db790c..1bbaf83 100644
--- a/compiler/rustc_mir/src/transform/promote_consts.rs
+++ b/compiler/rustc_mir/src/transform/promote_consts.rs
@@ -108,9 +108,6 @@
     /// the attribute currently provides the semantic requirement that arguments
     /// must be constant.
     Argument { bb: BasicBlock, index: usize },
-
-    /// `const` operand in asm!.
-    InlineAsm { bb: BasicBlock, index: usize },
 }
 
 impl Candidate {
@@ -118,16 +115,14 @@
     fn forces_explicit_promotion(&self) -> bool {
         match self {
             Candidate::Ref(_) => false,
-            Candidate::Argument { .. } | Candidate::InlineAsm { .. } => true,
+            Candidate::Argument { .. } => true,
         }
     }
 
     fn source_info(&self, body: &Body<'_>) -> SourceInfo {
         match self {
             Candidate::Ref(location) => *body.source_info(*location),
-            Candidate::Argument { bb, .. } | Candidate::InlineAsm { bb, .. } => {
-                *body.source_info(body.terminator_loc(*bb))
-            }
+            Candidate::Argument { bb, .. } => *body.source_info(body.terminator_loc(*bb)),
         }
     }
 }
@@ -217,36 +212,25 @@
     fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location) {
         self.super_terminator(terminator, location);
 
-        match terminator.kind {
-            TerminatorKind::Call { ref func, .. } => {
-                if let ty::FnDef(def_id, _) = *func.ty(self.ccx.body, self.ccx.tcx).kind() {
-                    let fn_sig = self.ccx.tcx.fn_sig(def_id);
-                    if let Abi::RustIntrinsic | Abi::PlatformIntrinsic = fn_sig.abi() {
-                        let name = self.ccx.tcx.item_name(def_id);
-                        // FIXME(eddyb) use `#[rustc_args_required_const(2)]` for shuffles.
-                        if name.as_str().starts_with("simd_shuffle") {
-                            self.candidates
-                                .push(Candidate::Argument { bb: location.block, index: 2 });
+        if let TerminatorKind::Call { ref func, .. } = terminator.kind {
+            if let ty::FnDef(def_id, _) = *func.ty(self.ccx.body, self.ccx.tcx).kind() {
+                let fn_sig = self.ccx.tcx.fn_sig(def_id);
+                if let Abi::RustIntrinsic | Abi::PlatformIntrinsic = fn_sig.abi() {
+                    let name = self.ccx.tcx.item_name(def_id);
+                    // FIXME(eddyb) use `#[rustc_args_required_const(2)]` for shuffles.
+                    if name.as_str().starts_with("simd_shuffle") {
+                        self.candidates.push(Candidate::Argument { bb: location.block, index: 2 });
 
-                            return; // Don't double count `simd_shuffle` candidates
-                        }
+                        return; // Don't double count `simd_shuffle` candidates
                     }
+                }
 
-                    if let Some(constant_args) = args_required_const(self.ccx.tcx, def_id) {
-                        for index in constant_args {
-                            self.candidates.push(Candidate::Argument { bb: location.block, index });
-                        }
+                if let Some(constant_args) = args_required_const(self.ccx.tcx, def_id) {
+                    for index in constant_args {
+                        self.candidates.push(Candidate::Argument { bb: location.block, index });
                     }
                 }
             }
-            TerminatorKind::InlineAsm { ref operands, .. } => {
-                for (index, op) in operands.iter().enumerate() {
-                    if let InlineAsmOperand::Const { .. } = op {
-                        self.candidates.push(Candidate::InlineAsm { bb: location.block, index })
-                    }
-                }
-            }
-            _ => {}
         }
     }
 }
@@ -335,18 +319,6 @@
                     _ => bug!(),
                 }
             }
-            Candidate::InlineAsm { bb, index } => {
-                assert!(self.explicit);
-
-                let terminator = self.body[bb].terminator();
-                match &terminator.kind {
-                    TerminatorKind::InlineAsm { operands, .. } => match &operands[index] {
-                        InlineAsmOperand::Const { value } => self.validate_operand(value),
-                        _ => bug!(),
-                    },
-                    _ => bug!(),
-                }
-            }
         }
     }
 
@@ -818,9 +790,7 @@
             }
 
             match candidate {
-                Candidate::Argument { bb, index } | Candidate::InlineAsm { bb, index }
-                    if !is_promotable =>
-                {
+                Candidate::Argument { bb, index } if !is_promotable => {
                     let span = ccx.body[bb].terminator().source_info.span;
                     let msg = format!("argument {} is required to be a constant", index + 1);
                     ccx.tcx.sess.span_err(span, &msg);
@@ -1001,17 +971,17 @@
                     literal: tcx
                         .mk_const(ty::Const {
                             ty,
-                            val: ty::ConstKind::Unevaluated(
+                            val: ty::ConstKind::Unevaluated(ty::Unevaluated {
                                 def,
-                                InternalSubsts::for_item(tcx, def.did, |param, _| {
+                                substs: InternalSubsts::for_item(tcx, def.did, |param, _| {
                                     if let ty::GenericParamDefKind::Lifetime = param.kind {
                                         tcx.lifetimes.re_erased.into()
                                     } else {
                                         tcx.mk_param_from_def(param)
                                     }
                                 }),
-                                Some(promoted_id),
-                            ),
+                                promoted: Some(promoted_id),
+                            }),
                         })
                         .into(),
                 }))
@@ -1089,24 +1059,6 @@
                         _ => bug!(),
                     }
                 }
-                Candidate::InlineAsm { bb, index } => {
-                    let terminator = blocks[bb].terminator_mut();
-                    match terminator.kind {
-                        TerminatorKind::InlineAsm { ref mut operands, .. } => {
-                            match &mut operands[index] {
-                                InlineAsmOperand::Const { ref mut value } => {
-                                    let ty = value.ty(local_decls, self.tcx);
-                                    let span = terminator.source_info.span;
-
-                                    Rvalue::Use(mem::replace(value, promoted_operand(ty, span)))
-                                }
-                                _ => bug!(),
-                            }
-                        }
-
-                        _ => bug!(),
-                    }
-                }
             }
         };
 
@@ -1161,7 +1113,7 @@
                     }
                 }
             }
-            Candidate::Argument { .. } | Candidate::InlineAsm { .. } => {}
+            Candidate::Argument { .. } => {}
         }
 
         // Declare return place local so that `mir::Body::new` doesn't complain.
diff --git a/compiler/rustc_mir/src/transform/remove_zsts.rs b/compiler/rustc_mir/src/transform/remove_zsts.rs
new file mode 100644
index 0000000..70f7538
--- /dev/null
+++ b/compiler/rustc_mir/src/transform/remove_zsts.rs
@@ -0,0 +1,89 @@
+//! Removes assignments to ZST places.
+
+use crate::transform::MirPass;
+use rustc_middle::mir::tcx::PlaceTy;
+use rustc_middle::mir::{Body, LocalDecls, Place, StatementKind};
+use rustc_middle::ty::{self, Ty, TyCtxt};
+
+pub struct RemoveZsts;
+
+impl<'tcx> MirPass<'tcx> for RemoveZsts {
+    fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
+        if tcx.sess.mir_opt_level() < 3 {
+            return;
+        }
+        let param_env = tcx.param_env(body.source.def_id());
+        let (basic_blocks, local_decls) = body.basic_blocks_and_local_decls_mut();
+        for block in basic_blocks.iter_mut() {
+            for statement in block.statements.iter_mut() {
+                match statement.kind {
+                    StatementKind::Assign(box (place, _)) => {
+                        let place_ty = place.ty(local_decls, tcx).ty;
+                        if !maybe_zst(place_ty) {
+                            continue;
+                        }
+                        let layout = match tcx.layout_of(param_env.and(place_ty)) {
+                            Ok(layout) => layout,
+                            Err(_) => continue,
+                        };
+                        if !layout.is_zst() {
+                            continue;
+                        }
+                        if involves_a_union(place, local_decls, tcx) {
+                            continue;
+                        }
+                        if tcx.consider_optimizing(|| {
+                            format!(
+                                "RemoveZsts - Place: {:?} SourceInfo: {:?}",
+                                place, statement.source_info
+                            )
+                        }) {
+                            statement.make_nop();
+                        }
+                    }
+                    _ => {}
+                }
+            }
+        }
+    }
+}
+
+/// A cheap, approximate check to avoid unnecessary `layout_of` calls.
+fn maybe_zst(ty: Ty<'_>) -> bool {
+    match ty.kind() {
+        // maybe ZST (could be more precise)
+        ty::Adt(..) | ty::Array(..) | ty::Closure(..) | ty::Tuple(..) | ty::Opaque(..) => true,
+        // definitely ZST
+        ty::FnDef(..) | ty::Never => true,
+        // unreachable or can't be ZST
+        _ => false,
+    }
+}
+
+/// Miri lazily allocates memory for locals on assignment,
+/// so we must preserve writes to unions and union fields,
+/// or it will ICE on reads of those fields.
+fn involves_a_union<'tcx>(
+    place: Place<'tcx>,
+    local_decls: &LocalDecls<'tcx>,
+    tcx: TyCtxt<'tcx>,
+) -> bool {
+    let mut place_ty = PlaceTy::from_ty(local_decls[place.local].ty);
+    if is_union(place_ty.ty) {
+        return true;
+    }
+    for elem in place.projection {
+        place_ty = place_ty.projection_ty(tcx, elem);
+        if is_union(place_ty.ty) {
+            return true;
+        }
+    }
+    return false;
+}
+
+fn is_union(ty: Ty<'_>) -> bool {
+    match ty.kind() {
+        ty::Adt(def, _) if def.is_union() => true,
+        _ => false,
+    }
+}
diff --git a/compiler/rustc_mir/src/transform/required_consts.rs b/compiler/rustc_mir/src/transform/required_consts.rs
index 2b518bd..8b64ad6 100644
--- a/compiler/rustc_mir/src/transform/required_consts.rs
+++ b/compiler/rustc_mir/src/transform/required_consts.rs
@@ -15,7 +15,7 @@
 impl<'a, 'tcx> Visitor<'tcx> for RequiredConstsVisitor<'a, 'tcx> {
     fn visit_constant(&mut self, constant: &Constant<'tcx>, _: Location) {
         if let Some(ct) = constant.literal.const_for_ty() {
-            if let ConstKind::Unevaluated(_, _, _) = ct.val {
+            if let ConstKind::Unevaluated(_) = ct.val {
                 self.required_consts.push(*constant);
             }
         }
diff --git a/compiler/rustc_mir/src/transform/simplify.rs b/compiler/rustc_mir/src/transform/simplify.rs
index d2314a9..65e2d09 100644
--- a/compiler/rustc_mir/src/transform/simplify.rs
+++ b/compiler/rustc_mir/src/transform/simplify.rs
@@ -31,10 +31,10 @@
 use rustc_index::vec::{Idx, IndexVec};
 use rustc_middle::mir::visit::{MutVisitor, MutatingUseContext, PlaceContext, Visitor};
 use rustc_middle::mir::*;
-use rustc_middle::ty::ParamEnv;
 use rustc_middle::ty::TyCtxt;
 use smallvec::SmallVec;
-use std::{borrow::Cow, convert::TryInto};
+use std::borrow::Cow;
+use std::convert::TryInto;
 
 pub struct SimplifyCfg {
     label: String,
@@ -326,7 +326,7 @@
 
 pub fn simplify_locals<'tcx>(body: &mut Body<'tcx>, tcx: TyCtxt<'tcx>) {
     // First, we're going to get a count of *actual* uses for every `Local`.
-    let mut used_locals = UsedLocals::new(body, tcx);
+    let mut used_locals = UsedLocals::new(body);
 
     // Next, we're going to remove any `Local` with zero actual uses. When we remove those
     // `Locals`, we're also going to subtract any uses of other `Locals` from the `used_locals`
@@ -336,8 +336,7 @@
     remove_unused_definitions(&mut used_locals, body);
 
     // Finally, we'll actually do the work of shrinking `body.local_decls` and remapping the `Local`s.
-    let arg_count = body.arg_count.try_into().unwrap();
-    let map = make_local_map(&mut body.local_decls, &used_locals, arg_count);
+    let map = make_local_map(&mut body.local_decls, &used_locals);
 
     // Only bother running the `LocalUpdater` if we actually found locals to remove.
     if map.iter().any(Option::is_none) {
@@ -350,61 +349,54 @@
 }
 
 /// Construct the mapping while swapping out unused stuff out from the `vec`.
-fn make_local_map<'tcx, V>(
+fn make_local_map<V>(
     local_decls: &mut IndexVec<Local, V>,
-    used_locals: &UsedLocals<'tcx>,
-    arg_count: u32,
+    used_locals: &UsedLocals,
 ) -> IndexVec<Local, Option<Local>> {
-    let mut map: IndexVec<Local, Option<Local>> = IndexVec::from_elem(None, local_decls);
+    let mut map: IndexVec<Local, Option<Local>> = IndexVec::from_elem(None, &*local_decls);
     let mut used = Local::new(0);
 
     for alive_index in local_decls.indices() {
-        // When creating the local map treat the `RETURN_PLACE` and arguments as used.
-        if alive_index.as_u32() <= arg_count || used_locals.is_used(alive_index) {
-            map[alive_index] = Some(used);
-            if alive_index != used {
-                local_decls.swap(alive_index, used);
-            }
-            used.increment_by(1);
+        // `is_used` treats the `RETURN_PLACE` and arguments as used.
+        if !used_locals.is_used(alive_index) {
+            continue;
         }
+
+        map[alive_index] = Some(used);
+        if alive_index != used {
+            local_decls.swap(alive_index, used);
+        }
+        used.increment_by(1);
     }
     local_decls.truncate(used.index());
     map
 }
 
 /// Keeps track of used & unused locals.
-struct UsedLocals<'tcx> {
+struct UsedLocals {
     increment: bool,
+    arg_count: u32,
     use_count: IndexVec<Local, u32>,
-    is_static: bool,
-    local_decls: IndexVec<Local, LocalDecl<'tcx>>,
-    param_env: ParamEnv<'tcx>,
-    tcx: TyCtxt<'tcx>,
 }
 
-impl UsedLocals<'tcx> {
+impl UsedLocals {
     /// Determines which locals are used & unused in the given body.
-    fn new(body: &Body<'tcx>, tcx: TyCtxt<'tcx>) -> Self {
-        let def_id = body.source.def_id();
-        let is_static = tcx.is_static(def_id);
-        let param_env = tcx.param_env(def_id);
-        let local_decls = body.local_decls.clone();
+    fn new(body: &Body<'_>) -> Self {
         let mut this = Self {
             increment: true,
+            arg_count: body.arg_count.try_into().unwrap(),
             use_count: IndexVec::from_elem(0, &body.local_decls),
-            is_static,
-            local_decls,
-            param_env,
-            tcx,
         };
         this.visit_body(body);
         this
     }
 
     /// Checks if local is used.
+    ///
+    /// Return place and arguments are always considered used.
     fn is_used(&self, local: Local) -> bool {
         trace!("is_used({:?}): use_count: {:?}", local, self.use_count[local]);
-        self.use_count[local] != 0
+        local.as_u32() <= self.arg_count || self.use_count[local] != 0
     }
 
     /// Updates the use counts to reflect the removal of given statement.
@@ -422,7 +414,9 @@
             // A use, not a definition.
             self.visit_place(place, PlaceContext::MutatingUse(MutatingUseContext::Store), location);
         } else {
-            // A definition. Although, it still might use other locals for indexing.
+            // A definition. The base local itself is not visited, so this occurrence is not counted
+            // toward its use count. There might be other locals still, used in an indexing
+            // projection.
             self.super_projection(
                 place.as_ref(),
                 PlaceContext::MutatingUse(MutatingUseContext::Projection),
@@ -432,7 +426,7 @@
     }
 }
 
-impl Visitor<'tcx> for UsedLocals<'tcx> {
+impl Visitor<'_> for UsedLocals {
     fn visit_statement(&mut self, statement: &Statement<'tcx>, location: Location) {
         match statement.kind {
             StatementKind::LlvmInlineAsm(..)
@@ -459,21 +453,7 @@
         }
     }
 
-    fn visit_local(&mut self, local: &Local, ctx: PlaceContext, _location: Location) {
-        debug!("local: {:?} is_static: {:?}, ctx: {:?}", local, self.is_static, ctx);
-        // Do not count _0 as a used in `return;` if it is a ZST.
-        let return_place = *local == RETURN_PLACE
-            && matches!(ctx, PlaceContext::NonMutatingUse(visit::NonMutatingUseContext::Move));
-        if !self.is_static && return_place {
-            let ty = self.local_decls[*local].ty;
-            let param_env_and = self.param_env.and(ty);
-            if let Ok(layout) = self.tcx.layout_of(param_env_and) {
-                debug!("layout.is_zst: {:?}", layout.is_zst());
-                if layout.is_zst() {
-                    return;
-                }
-            }
-        }
+    fn visit_local(&mut self, local: &Local, _ctx: PlaceContext, _location: Location) {
         if self.increment {
             self.use_count[*local] += 1;
         } else {
@@ -484,10 +464,7 @@
 }
 
 /// Removes unused definitions. Updates the used locals to reflect the changes made.
-fn remove_unused_definitions<'a, 'tcx>(
-    used_locals: &'a mut UsedLocals<'tcx>,
-    body: &mut Body<'tcx>,
-) {
+fn remove_unused_definitions<'a, 'tcx>(used_locals: &'a mut UsedLocals, body: &mut Body<'tcx>) {
     // The use counts are updated as we remove the statements. A local might become unused
     // during the retain operation, leading to a temporary inconsistency (storage statements or
     // definitions referencing the local might remain). For correctness it is crucial that this
diff --git a/compiler/rustc_mir/src/util/alignment.rs b/compiler/rustc_mir/src/util/alignment.rs
index f567c9c..5d4ca87 100644
--- a/compiler/rustc_mir/src/util/alignment.rs
+++ b/compiler/rustc_mir/src/util/alignment.rs
@@ -1,5 +1,6 @@
 use rustc_middle::mir::*;
 use rustc_middle::ty::{self, TyCtxt};
+use rustc_target::abi::Align;
 
 /// Returns `true` if this place is allowed to be less aligned
 /// than its containing struct (because it is within a packed
@@ -14,17 +15,25 @@
     L: HasLocalDecls<'tcx>,
 {
     debug!("is_disaligned({:?})", place);
-    if !is_within_packed(tcx, local_decls, place) {
-        debug!("is_disaligned({:?}) - not within packed", place);
-        return false;
-    }
+    let pack = match is_within_packed(tcx, local_decls, place) {
+        None => {
+            debug!("is_disaligned({:?}) - not within packed", place);
+            return false;
+        }
+        Some(pack) => pack,
+    };
 
     let ty = place.ty(local_decls, tcx).ty;
     match tcx.layout_raw(param_env.and(ty)) {
-        Ok(layout) if layout.align.abi.bytes() == 1 => {
-            // if the alignment is 1, the type can't be further
-            // disaligned.
-            debug!("is_disaligned({:?}) - align = 1", place);
+        Ok(layout) if layout.align.abi <= pack => {
+            // If the packed alignment is greater or equal to the field alignment, the type won't be
+            // further disaligned.
+            debug!(
+                "is_disaligned({:?}) - align = {}, packed = {}; not disaligned",
+                place,
+                layout.align.abi.bytes(),
+                pack.bytes()
+            );
             false
         }
         _ => {
@@ -34,7 +43,11 @@
     }
 }
 
-fn is_within_packed<'tcx, L>(tcx: TyCtxt<'tcx>, local_decls: &L, place: Place<'tcx>) -> bool
+fn is_within_packed<'tcx, L>(
+    tcx: TyCtxt<'tcx>,
+    local_decls: &L,
+    place: Place<'tcx>,
+) -> Option<Align>
 where
     L: HasLocalDecls<'tcx>,
 {
@@ -45,7 +58,7 @@
             ProjectionElem::Field(..) => {
                 let ty = place_base.ty(local_decls, tcx).ty;
                 match ty.kind() {
-                    ty::Adt(def, _) if def.repr.packed() => return true,
+                    ty::Adt(def, _) => return def.repr.pack,
                     _ => {}
                 }
             }
@@ -53,5 +66,5 @@
         }
     }
 
-    false
+    None
 }
diff --git a/compiler/rustc_mir/src/util/find_self_call.rs b/compiler/rustc_mir/src/util/find_self_call.rs
index ddda98d..33ad128 100644
--- a/compiler/rustc_mir/src/util/find_self_call.rs
+++ b/compiler/rustc_mir/src/util/find_self_call.rs
@@ -3,7 +3,7 @@
 use rustc_middle::ty::{self, TyCtxt};
 use rustc_span::def_id::DefId;
 
-/// Checks if the specified `local` is used as the `self` prameter of a method call
+/// Checks if the specified `local` is used as the `self` parameter of a method call
 /// in the provided `BasicBlock`. If it is, then the `DefId` of the called method is
 /// returned.
 pub fn find_self_call<'tcx>(
diff --git a/compiler/rustc_mir/src/util/generic_graphviz.rs b/compiler/rustc_mir/src/util/generic_graphviz.rs
index fd41e28..21c18b2 100644
--- a/compiler/rustc_mir/src/util/generic_graphviz.rs
+++ b/compiler/rustc_mir/src/util/generic_graphviz.rs
@@ -40,22 +40,6 @@
         }
     }
 
-    pub fn new_subgraph(
-        graph: &'a G,
-        graphviz_name: &str,
-        node_content_fn: NodeContentFn,
-        edge_labels_fn: EdgeLabelsFn,
-    ) -> Self {
-        Self {
-            graph,
-            is_subgraph: true,
-            graphviz_name: graphviz_name.to_owned(),
-            graph_label: None,
-            node_content_fn,
-            edge_labels_fn,
-        }
-    }
-
     pub fn set_graph_label(&mut self, graph_label: &str) {
         self.graph_label = Some(graph_label.to_owned());
     }
diff --git a/compiler/rustc_mir/src/util/patch.rs b/compiler/rustc_mir/src/util/patch.rs
index 6566a99..d09195f 100644
--- a/compiler/rustc_mir/src/util/patch.rs
+++ b/compiler/rustc_mir/src/util/patch.rs
@@ -13,7 +13,6 @@
     new_locals: Vec<LocalDecl<'tcx>>,
     resume_block: BasicBlock,
     next_local: usize,
-    make_nop: Vec<Location>,
 }
 
 impl<'tcx> MirPatch<'tcx> {
@@ -25,7 +24,6 @@
             new_locals: vec![],
             next_local: body.local_decls.len(),
             resume_block: START_BLOCK,
-            make_nop: vec![],
         };
 
         // make sure the MIR we create has a resume block. It is
@@ -117,15 +115,7 @@
         self.add_statement(loc, StatementKind::Assign(box (place, rv)));
     }
 
-    pub fn make_nop(&mut self, loc: Location) {
-        self.make_nop.push(loc);
-    }
-
     pub fn apply(self, body: &mut Body<'tcx>) {
-        debug!("MirPatch: make nops at: {:?}", self.make_nop);
-        for loc in self.make_nop {
-            body.make_statement_nop(loc);
-        }
         debug!(
             "MirPatch: {:?} new temps, starting from index {}: {:?}",
             self.new_locals.len(),
diff --git a/compiler/rustc_mir/src/util/pretty.rs b/compiler/rustc_mir/src/util/pretty.rs
index 1bf010f..3b88aec 100644
--- a/compiler/rustc_mir/src/util/pretty.rs
+++ b/compiler/rustc_mir/src/util/pretty.rs
@@ -452,7 +452,11 @@
                 match literal {
                     ConstantKind::Ty(literal) => self.push(&format!("+ literal: {:?}", literal)),
                     ConstantKind::Val(val, ty) => {
-                        self.push(&format!("+ literal: {:?}, {}", val, ty))
+                        // To keep the diffs small, we render this almost like we render ty::Const
+                        self.push(&format!(
+                            "+ literal: Const {{ ty: {}, val: Value({:?}) }}",
+                            ty, val
+                        ))
                     }
                 }
             }
@@ -465,7 +469,21 @@
         if use_verbose(ty) {
             self.push("ty::Const");
             self.push(&format!("+ ty: {:?}", ty));
-            self.push(&format!("+ val: {:?}", val));
+            let val = match val {
+                ty::ConstKind::Param(p) => format!("Param({})", p),
+                ty::ConstKind::Infer(infer) => format!("Infer({:?})", infer),
+                ty::ConstKind::Bound(idx, var) => format!("Bound({:?}, {:?})", idx, var),
+                ty::ConstKind::Placeholder(ph) => format!("PlaceHolder({:?})", ph),
+                ty::ConstKind::Unevaluated(uv) => format!(
+                    "Unevaluated({}, {:?}, {:?})",
+                    self.tcx.def_path_str(uv.def.did),
+                    uv.substs,
+                    uv.promoted
+                ),
+                ty::ConstKind::Value(val) => format!("Value({:?})", val),
+                ty::ConstKind::Error(_) => format!("Error"),
+            };
+            self.push(&format!("+ val: {}", val));
         }
     }