about summary refs log tree commit diff
diff options
context:
space:
mode:
authorCamille GILLOT <gillot.camille@gmail.com>2023-03-09 16:55:20 +0000
committerCamille GILLOT <gillot.camille@gmail.com>2023-03-14 20:52:42 +0100
commitbcb161def7dbef64aebe698c42373d13b44a1c53 (patch)
treefc2f5ec048a3de96ac50aead6fcccab1247369b5
parent2e7034ebf7f57066c260b680c5e9dfcf04ca4cd5 (diff)
downloadrust-bcb161def7dbef64aebe698c42373d13b44a1c53.tar.gz
rust-bcb161def7dbef64aebe698c42373d13b44a1c53.zip
Wrap the whole LocalInfo in ClearCrossCrate.
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs13
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/mod.rs6
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/move_errors.rs19
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs92
-rw-r--r--compiler/rustc_borrowck/src/type_check/mod.rs5
-rw-r--r--compiler/rustc_const_eval/src/transform/check_consts/check.rs2
-rw-r--r--compiler/rustc_middle/src/mir/mod.rs39
-rw-r--r--compiler/rustc_middle/src/mir/patch.rs4
-rw-r--r--compiler/rustc_mir_build/src/build/expr/as_operand.rs11
-rw-r--r--compiler/rustc_mir_build/src/build/expr/as_rvalue.rs22
-rw-r--r--compiler/rustc_mir_build/src/build/expr/as_temp.rs10
-rw-r--r--compiler/rustc_mir_build/src/build/expr/into.rs5
-rw-r--r--compiler/rustc_mir_build/src/build/matches/mod.rs14
-rw-r--r--compiler/rustc_mir_build/src/build/mod.rs10
-rw-r--r--compiler/rustc_mir_transform/src/check_const_item_mutation.rs2
-rw-r--r--compiler/rustc_mir_transform/src/check_unsafety.rs2
-rw-r--r--compiler/rustc_mir_transform/src/deref_separator.rs2
-rw-r--r--compiler/rustc_mir_transform/src/generator.rs10
-rw-r--r--tests/mir-opt/separate_const_switch.identity.SeparateConstSwitch.diff8
19 files changed, 134 insertions, 142 deletions
diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
index f43b611f54e..efa75668fac 100644
--- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
@@ -2482,15 +2482,14 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         let (place_description, assigned_span) = match local_decl {
             Some(LocalDecl {
                 local_info:
-                    Some(box LocalInfo::User(
-                        ClearCrossCrate::Clear
-                        | ClearCrossCrate::Set(BindingForm::Var(VarBindingForm {
+                    ClearCrossCrate::Set(
+                        box LocalInfo::User(BindingForm::Var(VarBindingForm {
                             opt_match_place: None,
                             ..
-                        })),
-                    ))
-                    | Some(box LocalInfo::StaticRef { .. })
-                    | None,
+                        }))
+                        | box LocalInfo::StaticRef { .. }
+                        | box LocalInfo::Boring,
+                    ),
                 ..
             })
             | None => (self.describe_any_place(place.as_ref()), assigned_span),
diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs
index af705e6a80f..611abb01238 100644
--- a/compiler/rustc_borrowck/src/diagnostics/mod.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs
@@ -196,10 +196,10 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                         if self.body.local_decls[local].is_ref_for_guard() {
                             continue;
                         }
-                        if let Some(box LocalInfo::StaticRef { def_id, .. }) =
-                            &self.body.local_decls[local].local_info
+                        if let LocalInfo::StaticRef { def_id, .. } =
+                            *self.body.local_decls[local].local_info()
                         {
-                            buf.push_str(self.infcx.tcx.item_name(*def_id).as_str());
+                            buf.push_str(self.infcx.tcx.item_name(def_id).as_str());
                             ok = Ok(());
                             continue;
                         }
diff --git a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs
index 5e4c7292e59..3662bec0c76 100644
--- a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs
@@ -102,14 +102,12 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
                         //
                         // opt_match_place is None for let [mut] x = ... statements,
                         // whether or not the right-hand side is a place expression
-                        if let Some(box LocalInfo::User(ClearCrossCrate::Set(BindingForm::Var(
-                            VarBindingForm {
-                                opt_match_place: Some((opt_match_place, match_span)),
-                                binding_mode: _,
-                                opt_ty_info: _,
-                                pat_span: _,
-                            },
-                        )))) = local_decl.local_info
+                        if let LocalInfo::User(BindingForm::Var(VarBindingForm {
+                            opt_match_place: Some((opt_match_place, match_span)),
+                            binding_mode: _,
+                            opt_ty_info: _,
+                            pat_span: _,
+                        })) = *local_decl.local_info()
                         {
                             let stmt_source_info = self.body.source_info(location);
                             self.append_binding_error(
@@ -478,9 +476,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
         let mut suggestions: Vec<(Span, String, String)> = Vec::new();
         for local in binds_to {
             let bind_to = &self.body.local_decls[*local];
-            if let Some(box LocalInfo::User(ClearCrossCrate::Set(BindingForm::Var(
-                VarBindingForm { pat_span, .. },
-            )))) = bind_to.local_info
+            if let LocalInfo::User(BindingForm::Var(VarBindingForm { pat_span, .. })) =
+                *bind_to.local_info()
             {
                 let Ok(pat_snippet) =
                     self.infcx.tcx.sess.source_map().span_to_snippet(pat_span) else { continue; };
diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
index eded913ae96..bad08451adf 100644
--- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
@@ -7,7 +7,7 @@ use rustc_middle::mir::{Mutability, Place, PlaceRef, ProjectionElem};
 use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_middle::{
     hir::place::PlaceBase,
-    mir::{self, BindingForm, ClearCrossCrate, Local, LocalDecl, LocalInfo, LocalKind, Location},
+    mir::{self, BindingForm, Local, LocalDecl, LocalInfo, LocalKind, Location},
 };
 use rustc_span::source_map::DesugaringKind;
 use rustc_span::symbol::{kw, Symbol};
@@ -105,8 +105,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
                     reason = String::new();
                 } else {
                     item_msg = access_place_desc;
-                    let local_info = &self.body.local_decls[local].local_info;
-                    if let Some(box LocalInfo::StaticRef { def_id, .. }) = *local_info {
+                    let local_info = self.body.local_decls[local].local_info();
+                    if let LocalInfo::StaticRef { def_id, .. } = *local_info {
                         let static_name = &self.infcx.tcx.item_name(def_id);
                         reason = format!(", as `{static_name}` is an immutable static item");
                     } else {
@@ -305,15 +305,13 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
                     ..
                 }) = &self.body[location.block].statements.get(location.statement_index)
                 {
-                    match decl.local_info {
-                        Some(box LocalInfo::User(ClearCrossCrate::Set(BindingForm::Var(
-                            mir::VarBindingForm {
-                                binding_mode: ty::BindingMode::BindByValue(Mutability::Not),
-                                opt_ty_info: Some(sp),
-                                opt_match_place: _,
-                                pat_span: _,
-                            },
-                        )))) => {
+                    match *decl.local_info() {
+                        LocalInfo::User(BindingForm::Var(mir::VarBindingForm {
+                            binding_mode: ty::BindingMode::BindByValue(Mutability::Not),
+                            opt_ty_info: Some(sp),
+                            opt_match_place: _,
+                            pat_span: _,
+                        })) => {
                             if suggest {
                                 err.span_note(sp, "the binding is already a mutable borrow");
                             }
@@ -346,10 +344,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
                     }
                 } else if decl.mutability.is_not() {
                     if matches!(
-                        decl.local_info,
-                        Some(box LocalInfo::User(ClearCrossCrate::Set(BindingForm::ImplicitSelf(
-                            hir::ImplicitSelfKind::MutRef
-                        ),)))
+                        decl.local_info(),
+                        LocalInfo::User(BindingForm::ImplicitSelf(hir::ImplicitSelfKind::MutRef))
                     ) {
                         err.note(
                             "as `Self` may be unsized, this call attempts to take `&mut &mut self`",
@@ -482,22 +478,18 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
 
                 match self.local_names[local] {
                     Some(name) if !local_decl.from_compiler_desugaring() => {
-                        let label = match local_decl.local_info.as_deref().unwrap() {
-                            LocalInfo::User(ClearCrossCrate::Set(
-                                mir::BindingForm::ImplicitSelf(_),
-                            )) => {
+                        let label = match *local_decl.local_info() {
+                            LocalInfo::User(mir::BindingForm::ImplicitSelf(_)) => {
                                 let (span, suggestion) =
                                     suggest_ampmut_self(self.infcx.tcx, local_decl);
                                 Some((true, span, suggestion))
                             }
 
-                            LocalInfo::User(ClearCrossCrate::Set(mir::BindingForm::Var(
-                                mir::VarBindingForm {
-                                    binding_mode: ty::BindingMode::BindByValue(_),
-                                    opt_ty_info,
-                                    ..
-                                },
-                            ))) => {
+                            LocalInfo::User(mir::BindingForm::Var(mir::VarBindingForm {
+                                binding_mode: ty::BindingMode::BindByValue(_),
+                                opt_ty_info,
+                                ..
+                            })) => {
                                 // check if the RHS is from desugaring
                                 let opt_assignment_rhs_span =
                                     self.body.find_assignments(local).first().map(|&location| {
@@ -534,16 +526,15 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
                                                 self.infcx.tcx,
                                                 local_decl,
                                                 opt_assignment_rhs_span,
-                                                *opt_ty_info,
+                                                opt_ty_info,
                                             )
                                         } else {
-                                            match local_decl.local_info.as_deref() {
-                                                Some(LocalInfo::User(ClearCrossCrate::Set(
-                                                    mir::BindingForm::Var(mir::VarBindingForm {
-                                                        opt_ty_info: None,
-                                                        ..
-                                                    }),
-                                                ))) => {
+                                            match local_decl.local_info() {
+                                                LocalInfo::User(mir::BindingForm::Var(
+                                                    mir::VarBindingForm {
+                                                        opt_ty_info: None, ..
+                                                    },
+                                                )) => {
                                                     let (span, sugg) = suggest_ampmut_self(
                                                         self.infcx.tcx,
                                                         local_decl,
@@ -555,7 +546,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
                                                     self.infcx.tcx,
                                                     local_decl,
                                                     opt_assignment_rhs_span,
-                                                    *opt_ty_info,
+                                                    opt_ty_info,
                                                 ),
                                             }
                                         };
@@ -564,21 +555,15 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
                                 }
                             }
 
-                            LocalInfo::User(ClearCrossCrate::Set(mir::BindingForm::Var(
-                                mir::VarBindingForm {
-                                    binding_mode: ty::BindingMode::BindByReference(_),
-                                    ..
-                                },
-                            ))) => {
+                            LocalInfo::User(mir::BindingForm::Var(mir::VarBindingForm {
+                                binding_mode: ty::BindingMode::BindByReference(_),
+                                ..
+                            })) => {
                                 let pattern_span = local_decl.source_info.span;
                                 suggest_ref_mut(self.infcx.tcx, pattern_span)
                                     .map(|replacement| (true, pattern_span, replacement))
                             }
 
-                            LocalInfo::User(ClearCrossCrate::Clear) => {
-                                bug!("saw cleared local state")
-                            }
-
                             _ => unreachable!(),
                         };
 
@@ -1151,20 +1136,19 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
 pub fn mut_borrow_of_mutable_ref(local_decl: &LocalDecl<'_>, local_name: Option<Symbol>) -> bool {
     debug!("local_info: {:?}, ty.kind(): {:?}", local_decl.local_info, local_decl.ty.kind());
 
-    match local_decl.local_info.as_deref() {
+    match *local_decl.local_info() {
         // Check if mutably borrowing a mutable reference.
-        Some(LocalInfo::User(ClearCrossCrate::Set(mir::BindingForm::Var(
-            mir::VarBindingForm {
-                binding_mode: ty::BindingMode::BindByValue(Mutability::Not), ..
-            },
-        )))) => matches!(local_decl.ty.kind(), ty::Ref(_, _, hir::Mutability::Mut)),
-        Some(LocalInfo::User(ClearCrossCrate::Set(mir::BindingForm::ImplicitSelf(kind)))) => {
+        LocalInfo::User(mir::BindingForm::Var(mir::VarBindingForm {
+            binding_mode: ty::BindingMode::BindByValue(Mutability::Not),
+            ..
+        })) => matches!(local_decl.ty.kind(), ty::Ref(_, _, hir::Mutability::Mut)),
+        LocalInfo::User(mir::BindingForm::ImplicitSelf(kind)) => {
             // Check if the user variable is a `&mut self` and we can therefore
             // suggest removing the `&mut`.
             //
             // Deliberately fall into this case for all implicit self types,
             // so that we don't fall in to the next case with them.
-            *kind == hir::ImplicitSelfKind::MutRef
+            kind == hir::ImplicitSelfKind::MutRef
         }
         _ if Some(kw::SelfLower) == local_name => {
             // Otherwise, check if the name is the `self` keyword - in which case
diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs
index 3919c4793a0..8f1e14365d7 100644
--- a/compiler/rustc_borrowck/src/type_check/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/mod.rs
@@ -1180,10 +1180,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                         }
                     }
                     Some(l)
-                        if matches!(
-                            body.local_decls[l].local_info,
-                            Some(box LocalInfo::AggregateTemp)
-                        ) =>
+                        if matches!(body.local_decls[l].local_info(), LocalInfo::AggregateTemp) =>
                     {
                         ConstraintCategory::Usage
                     }
diff --git a/compiler/rustc_const_eval/src/transform/check_consts/check.rs b/compiler/rustc_const_eval/src/transform/check_consts/check.rs
index db55dbc2bfd..f775b479667 100644
--- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs
@@ -643,7 +643,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
                 if base_ty.is_unsafe_ptr() {
                     if proj_base.is_empty() {
                         let decl = &self.body.local_decls[place_local];
-                        if let Some(box LocalInfo::StaticRef { def_id, .. }) = decl.local_info {
+                        if let LocalInfo::StaticRef { def_id, .. } = *decl.local_info() {
                             let span = decl.source_info.span;
                             self.check_static(def_id, span);
                             return;
diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs
index b34651c3ea7..b9725029276 100644
--- a/compiler/rustc_middle/src/mir/mod.rs
+++ b/compiler/rustc_middle/src/mir/mod.rs
@@ -572,6 +572,13 @@ impl<T> ClearCrossCrate<T> {
         }
     }
 
+    pub fn as_mut(&mut self) -> ClearCrossCrate<&mut T> {
+        match self {
+            ClearCrossCrate::Clear => ClearCrossCrate::Clear,
+            ClearCrossCrate::Set(v) => ClearCrossCrate::Set(v),
+        }
+    }
+
     pub fn assert_crate_local(self) -> T {
         match self {
             ClearCrossCrate::Clear => bug!("unwrapping cross-crate data"),
@@ -760,7 +767,7 @@ pub struct LocalDecl<'tcx> {
     pub mutability: Mutability,
 
     // FIXME(matthewjasper) Don't store in this in `Body`
-    pub local_info: Option<Box<LocalInfo<'tcx>>>,
+    pub local_info: ClearCrossCrate<Box<LocalInfo<'tcx>>>,
 
     /// `true` if this is an internal local.
     ///
@@ -890,7 +897,7 @@ pub enum LocalInfo<'tcx> {
     /// The `BindingForm` is solely used for local diagnostics when generating
     /// warnings/errors when compiling the current crate, and therefore it need
     /// not be visible across crates.
-    User(ClearCrossCrate<BindingForm<'tcx>>),
+    User(BindingForm<'tcx>),
     /// A temporary created that references the static with the given `DefId`.
     StaticRef { def_id: DefId, is_thread_local: bool },
     /// A temporary created that references the const with the given `DefId`
@@ -902,9 +909,15 @@ pub enum LocalInfo<'tcx> {
     DerefTemp,
     /// A temporary created for borrow checking.
     FakeBorrow,
+    /// A local without anything interesting about it.
+    Boring,
 }
 
 impl<'tcx> LocalDecl<'tcx> {
+    pub fn local_info(&self) -> &LocalInfo<'tcx> {
+        &**self.local_info.as_ref().assert_crate_local()
+    }
+
     /// Returns `true` only if local is a binding that can itself be
     /// made mutable via the addition of the `mut` keyword, namely
     /// something like the occurrences of `x` in:
@@ -914,14 +927,14 @@ impl<'tcx> LocalDecl<'tcx> {
     pub fn can_be_made_mutable(&self) -> bool {
         matches!(
             self.local_info,
-            Some(box LocalInfo::User(ClearCrossCrate::Set(
+            ClearCrossCrate::Set(box LocalInfo::User(
                 BindingForm::Var(VarBindingForm {
                     binding_mode: ty::BindingMode::BindByValue(_),
                     opt_ty_info: _,
                     opt_match_place: _,
                     pat_span: _,
                 }) | BindingForm::ImplicitSelf(ImplicitSelfKind::Imm),
-            )))
+            ))
         )
     }
 
@@ -931,14 +944,14 @@ impl<'tcx> LocalDecl<'tcx> {
     pub fn is_nonref_binding(&self) -> bool {
         matches!(
             self.local_info,
-            Some(box LocalInfo::User(ClearCrossCrate::Set(
+            ClearCrossCrate::Set(box LocalInfo::User(
                 BindingForm::Var(VarBindingForm {
                     binding_mode: ty::BindingMode::BindByValue(_),
                     opt_ty_info: _,
                     opt_match_place: _,
                     pat_span: _,
                 }) | BindingForm::ImplicitSelf(_),
-            )))
+            ))
         )
     }
 
@@ -946,7 +959,7 @@ impl<'tcx> LocalDecl<'tcx> {
     /// parameter declared by the user.
     #[inline]
     pub fn is_user_variable(&self) -> bool {
-        matches!(self.local_info, Some(box LocalInfo::User(_)))
+        matches!(self.local_info, ClearCrossCrate::Set(box LocalInfo::User(_)))
     }
 
     /// Returns `true` if this is a reference to a variable bound in a `match`
@@ -955,21 +968,23 @@ impl<'tcx> LocalDecl<'tcx> {
     pub fn is_ref_for_guard(&self) -> bool {
         matches!(
             self.local_info,
-            Some(box LocalInfo::User(ClearCrossCrate::Set(BindingForm::RefForGuard)))
+            ClearCrossCrate::Set(box LocalInfo::User(BindingForm::RefForGuard))
         )
     }
 
     /// Returns `Some` if this is a reference to a static item that is used to
     /// access that static.
     pub fn is_ref_to_static(&self) -> bool {
-        matches!(self.local_info, Some(box LocalInfo::StaticRef { .. }))
+        matches!(self.local_info, ClearCrossCrate::Set(box LocalInfo::StaticRef { .. }))
     }
 
     /// Returns `Some` if this is a reference to a thread-local static item that is used to
     /// access that static.
     pub fn is_ref_to_thread_local(&self) -> bool {
         match self.local_info {
-            Some(box LocalInfo::StaticRef { is_thread_local, .. }) => is_thread_local,
+            ClearCrossCrate::Set(box LocalInfo::StaticRef { is_thread_local, .. }) => {
+                is_thread_local
+            }
             _ => false,
         }
     }
@@ -977,7 +992,7 @@ impl<'tcx> LocalDecl<'tcx> {
     /// Returns `true` if this is a DerefTemp
     pub fn is_deref_temp(&self) -> bool {
         match self.local_info {
-            Some(box LocalInfo::DerefTemp) => return true,
+            ClearCrossCrate::Set(box LocalInfo::DerefTemp) => return true,
             _ => (),
         }
         return false;
@@ -1001,7 +1016,7 @@ impl<'tcx> LocalDecl<'tcx> {
     pub fn with_source_info(ty: Ty<'tcx>, source_info: SourceInfo) -> Self {
         LocalDecl {
             mutability: Mutability::Mut,
-            local_info: None,
+            local_info: ClearCrossCrate::Set(Box::new(LocalInfo::Boring)),
             internal: false,
             is_block_tail: None,
             ty,
diff --git a/compiler/rustc_middle/src/mir/patch.rs b/compiler/rustc_middle/src/mir/patch.rs
index 24fe3b47256..eb860c04de2 100644
--- a/compiler/rustc_middle/src/mir/patch.rs
+++ b/compiler/rustc_middle/src/mir/patch.rs
@@ -72,12 +72,12 @@ impl<'tcx> MirPatch<'tcx> {
         &mut self,
         ty: Ty<'tcx>,
         span: Span,
-        local_info: Option<Box<LocalInfo<'tcx>>>,
+        local_info: LocalInfo<'tcx>,
     ) -> Local {
         let index = self.next_local;
         self.next_local += 1;
         let mut new_decl = LocalDecl::new(ty, span).internal();
-        new_decl.local_info = local_info;
+        **new_decl.local_info.as_mut().assert_crate_local() = local_info;
         self.new_locals.push(new_decl);
         Local::new(index as usize)
     }
diff --git a/compiler/rustc_mir_build/src/build/expr/as_operand.rs b/compiler/rustc_mir_build/src/build/expr/as_operand.rs
index ff3198847df..4249a47621c 100644
--- a/compiler/rustc_mir_build/src/build/expr/as_operand.rs
+++ b/compiler/rustc_mir_build/src/build/expr/as_operand.rs
@@ -20,7 +20,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         expr: &Expr<'tcx>,
     ) -> BlockAnd<Operand<'tcx>> {
         let local_scope = self.local_scope();
-        self.as_operand(block, Some(local_scope), expr, None, NeedsTemporary::Maybe)
+        self.as_operand(block, Some(local_scope), expr, LocalInfo::Boring, NeedsTemporary::Maybe)
     }
 
     /// Returns an operand suitable for use until the end of the current scope expression and
@@ -102,7 +102,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         mut block: BasicBlock,
         scope: Option<region::Scope>,
         expr: &Expr<'tcx>,
-        local_info: Option<Box<LocalInfo<'tcx>>>,
+        local_info: LocalInfo<'tcx>,
         needs_temporary: NeedsTemporary,
     ) -> BlockAnd<Operand<'tcx>> {
         let this = self;
@@ -124,8 +124,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             }
             Category::Constant | Category::Place | Category::Rvalue(..) => {
                 let operand = unpack!(block = this.as_temp(block, scope, expr, Mutability::Mut));
-                if this.local_decls[operand].local_info.is_none() {
-                    this.local_decls[operand].local_info = local_info;
+                let decl_info = this.local_decls[operand].local_info.as_mut().assert_crate_local();
+                if let LocalInfo::Boring = **decl_info {
+                    **decl_info = local_info;
                 }
                 block.and(Operand::Move(Place::from(operand)))
             }
@@ -178,6 +179,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             }
         }
 
-        this.as_operand(block, scope, expr, None, NeedsTemporary::Maybe)
+        this.as_operand(block, scope, expr, LocalInfo::Boring, NeedsTemporary::Maybe)
     }
 }
diff --git a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
index a4e48c1545d..b8115f5aa18 100644
--- a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
+++ b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
@@ -63,7 +63,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                             block,
                             scope,
                             &this.thir[value],
-                            None,
+                            LocalInfo::Boring,
                             NeedsTemporary::No
                         )
                     );
@@ -73,18 +73,18 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             ExprKind::Binary { op, lhs, rhs } => {
                 let lhs = unpack!(
                     block =
-                        this.as_operand(block, scope, &this.thir[lhs], None, NeedsTemporary::Maybe)
+                        this.as_operand(block, scope, &this.thir[lhs], LocalInfo::Boring, NeedsTemporary::Maybe)
                 );
                 let rhs = unpack!(
                     block =
-                        this.as_operand(block, scope, &this.thir[rhs], None, NeedsTemporary::No)
+                        this.as_operand(block, scope, &this.thir[rhs], LocalInfo::Boring, NeedsTemporary::No)
                 );
                 this.build_binary_op(block, op, expr_span, expr.ty, lhs, rhs)
             }
             ExprKind::Unary { op, arg } => {
                 let arg = unpack!(
                     block =
-                        this.as_operand(block, scope, &this.thir[arg], None, NeedsTemporary::No)
+                        this.as_operand(block, scope, &this.thir[arg], LocalInfo::Boring, NeedsTemporary::No)
                 );
                 // Check for -MIN on signed integers
                 if this.check_overflow && op == UnOp::Neg && expr.ty.is_signed() {
@@ -259,7 +259,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 } else {
                     let ty = source.ty;
                     let source = unpack!(
-                        block = this.as_operand(block, scope, source, None, NeedsTemporary::No)
+                        block = this.as_operand(block, scope, source, LocalInfo::Boring, NeedsTemporary::No)
                     );
                     (source, ty)
                 };
@@ -272,7 +272,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             ExprKind::Pointer { cast, source } => {
                 let source = unpack!(
                     block =
-                        this.as_operand(block, scope, &this.thir[source], None, NeedsTemporary::No)
+                        this.as_operand(block, scope, &this.thir[source], LocalInfo::Boring, NeedsTemporary::No)
                 );
                 block.and(Rvalue::Cast(CastKind::Pointer(cast), source, expr.ty))
             }
@@ -314,7 +314,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                                 block,
                                 scope,
                                 &this.thir[f],
-                                None,
+                                LocalInfo::Boring,
                                 NeedsTemporary::Maybe
                             )
                         )
@@ -335,7 +335,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                                 block,
                                 scope,
                                 &this.thir[f],
-                                None,
+                                LocalInfo::Boring,
                                 NeedsTemporary::Maybe
                             )
                         )
@@ -423,7 +423,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                                                 block,
                                                 scope,
                                                 upvar,
-                                                None,
+                                                LocalInfo::Boring,
                                                 NeedsTemporary::Maybe
                                             )
                                         )
@@ -502,7 +502,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                     Some(Category::Rvalue(RvalueFunc::AsRvalue) | Category::Constant)
                 ));
                 let operand =
-                    unpack!(block = this.as_operand(block, scope, expr, None, NeedsTemporary::No));
+                    unpack!(block = this.as_operand(block, scope, expr, LocalInfo::Boring, NeedsTemporary::No));
                 block.and(Rvalue::Use(operand))
             }
         }
@@ -622,7 +622,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         } else {
             // For a non-const, we may need to generate an appropriate `Drop`
             let value_operand =
-                unpack!(block = this.as_operand(block, scope, value, None, NeedsTemporary::No));
+                unpack!(block = this.as_operand(block, scope, value, LocalInfo::Boring, NeedsTemporary::No));
             if let Operand::Move(to_drop) = value_operand {
                 let success = this.cfg.start_new_block();
                 this.cfg.terminate(
diff --git a/compiler/rustc_mir_build/src/build/expr/as_temp.rs b/compiler/rustc_mir_build/src/build/expr/as_temp.rs
index 3d3cf75559e..f978a920f43 100644
--- a/compiler/rustc_mir_build/src/build/expr/as_temp.rs
+++ b/compiler/rustc_mir_build/src/build/expr/as_temp.rs
@@ -58,17 +58,17 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 ExprKind::StaticRef { def_id, .. } => {
                     assert!(!this.tcx.is_thread_local_static(def_id));
                     local_decl.internal = true;
-                    local_decl.local_info =
-                        Some(Box::new(LocalInfo::StaticRef { def_id, is_thread_local: false }));
+                    **local_decl.local_info.as_mut().assert_crate_local() =
+                        LocalInfo::StaticRef { def_id, is_thread_local: false };
                 }
                 ExprKind::ThreadLocalRef(def_id) => {
                     assert!(this.tcx.is_thread_local_static(def_id));
                     local_decl.internal = true;
-                    local_decl.local_info =
-                        Some(Box::new(LocalInfo::StaticRef { def_id, is_thread_local: true }));
+                    **local_decl.local_info.as_mut().assert_crate_local() =
+                        LocalInfo::StaticRef { def_id, is_thread_local: true };
                 }
                 ExprKind::NamedConst { def_id, .. } | ExprKind::ConstParam { def_id, .. } => {
-                    local_decl.local_info = Some(Box::new(LocalInfo::ConstRef { def_id }));
+                    **local_decl.local_info.as_mut().assert_crate_local() = LocalInfo::ConstRef { def_id };
                 }
                 _ => {}
             }
diff --git a/compiler/rustc_mir_build/src/build/expr/into.rs b/compiler/rustc_mir_build/src/build/expr/into.rs
index dac9bf0a883..ebe8ea25ad3 100644
--- a/compiler/rustc_mir_build/src/build/expr/into.rs
+++ b/compiler/rustc_mir_build/src/build/expr/into.rs
@@ -328,7 +328,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 let fields_map: FxHashMap<_, _> = fields
                     .into_iter()
                     .map(|f| {
-                        let local_info = Box::new(LocalInfo::AggregateTemp);
                         (
                             f.name,
                             unpack!(
@@ -336,7 +335,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                                     block,
                                     Some(scope),
                                     &this.thir[f.expr],
-                                    Some(local_info),
+                                    LocalInfo::AggregateTemp,
                                     NeedsTemporary::Maybe,
                                 )
                             ),
@@ -526,7 +525,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                         block,
                         Some(scope),
                         &this.thir[value],
-                        None,
+                        LocalInfo::Boring,
                         NeedsTemporary::No
                     )
                 );
diff --git a/compiler/rustc_mir_build/src/build/matches/mod.rs b/compiler/rustc_mir_build/src/build/matches/mod.rs
index 3fb8a6db2d2..43d4a72390f 100644
--- a/compiler/rustc_mir_build/src/build/matches/mod.rs
+++ b/compiler/rustc_mir_build/src/build/matches/mod.rs
@@ -607,9 +607,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                     // };
                     // ```
                     if let Some(place) = initializer.try_to_place(self) {
-                        let Some(box LocalInfo::User(ClearCrossCrate::Set(BindingForm::Var(
+                        let LocalInfo::User(BindingForm::Var(
                             VarBindingForm { opt_match_place: Some((ref mut match_place, _)), .. },
-                        )))) = self.local_decls[local].local_info else {
+                        )) = **self.local_decls[local].local_info.as_mut().assert_crate_local() else {
                             bug!("Let binding to non-user variable.")
                         };
                         *match_place = Some(place);
@@ -1754,7 +1754,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 let fake_borrow_ty = tcx.mk_imm_ref(tcx.lifetimes.re_erased, fake_borrow_deref_ty);
                 let mut fake_borrow_temp = LocalDecl::new(fake_borrow_ty, temp_span);
                 fake_borrow_temp.internal = self.local_decls[matched_place.local].internal;
-                fake_borrow_temp.local_info = Some(Box::new(LocalInfo::FakeBorrow));
+                fake_borrow_temp.local_info = ClearCrossCrate::Set(Box::new(LocalInfo::FakeBorrow));
                 let fake_borrow_temp = self.local_decls.push(fake_borrow_temp);
 
                 (matched_place, fake_borrow_temp)
@@ -2225,7 +2225,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             source_info,
             internal: false,
             is_block_tail: None,
-            local_info: Some(Box::new(LocalInfo::User(ClearCrossCrate::Set(BindingForm::Var(
+            local_info: ClearCrossCrate::Set(Box::new(LocalInfo::User(BindingForm::Var(
                 VarBindingForm {
                     binding_mode,
                     // hypothetically, `visit_primary_bindings` could try to unzip
@@ -2236,7 +2236,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                     opt_match_place,
                     pat_span,
                 },
-            ))))),
+            )))),
         };
         let for_arm_body = self.local_decls.push(local);
         self.var_debug_info.push(VarDebugInfo {
@@ -2254,9 +2254,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 source_info,
                 internal: false,
                 is_block_tail: None,
-                local_info: Some(Box::new(LocalInfo::User(ClearCrossCrate::Set(
-                    BindingForm::RefForGuard,
-                )))),
+                local_info: ClearCrossCrate::Set(Box::new(LocalInfo::User(BindingForm::RefForGuard))),
             });
             self.var_debug_info.push(VarDebugInfo {
                 name,
diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs
index 70d5fc2d958..6814fd4cb35 100644
--- a/compiler/rustc_mir_build/src/build/mod.rs
+++ b/compiler/rustc_mir_build/src/build/mod.rs
@@ -876,20 +876,20 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 } => {
                     self.local_decls[local].mutability = mutability;
                     self.local_decls[local].source_info.scope = self.source_scope;
-                    self.local_decls[local].local_info = if let Some(kind) = param.self_kind {
-                        Some(Box::new(LocalInfo::User(ClearCrossCrate::Set(
+                    **self.local_decls[local].local_info.as_mut().assert_crate_local() = if let Some(kind) = param.self_kind {
+                        LocalInfo::User(
                             BindingForm::ImplicitSelf(kind),
-                        ))))
+                        )
                     } else {
                         let binding_mode = ty::BindingMode::BindByValue(mutability);
-                        Some(Box::new(LocalInfo::User(ClearCrossCrate::Set(BindingForm::Var(
+                        LocalInfo::User(BindingForm::Var(
                             VarBindingForm {
                                 binding_mode,
                                 opt_ty_info: param.ty_span,
                                 opt_match_place: Some((None, span)),
                                 pat_span: span,
                             },
-                        )))))
+                        ))
                     };
                     self.var_indices.insert(var, LocalsForNode::One(local));
                 }
diff --git a/compiler/rustc_mir_transform/src/check_const_item_mutation.rs b/compiler/rustc_mir_transform/src/check_const_item_mutation.rs
index 536745d2cfe..3d32c586554 100644
--- a/compiler/rustc_mir_transform/src/check_const_item_mutation.rs
+++ b/compiler/rustc_mir_transform/src/check_const_item_mutation.rs
@@ -24,7 +24,7 @@ struct ConstMutationChecker<'a, 'tcx> {
 
 impl<'tcx> ConstMutationChecker<'_, 'tcx> {
     fn is_const_item(&self, local: Local) -> Option<DefId> {
-        if let Some(box LocalInfo::ConstRef { def_id }) = self.body.local_decls[local].local_info {
+        if let LocalInfo::ConstRef { def_id } = *self.body.local_decls[local].local_info() {
             Some(def_id)
         } else {
             None
diff --git a/compiler/rustc_mir_transform/src/check_unsafety.rs b/compiler/rustc_mir_transform/src/check_unsafety.rs
index a8ec568eb0d..c4d058e8ecb 100644
--- a/compiler/rustc_mir_transform/src/check_unsafety.rs
+++ b/compiler/rustc_mir_transform/src/check_unsafety.rs
@@ -182,7 +182,7 @@ impl<'tcx> Visitor<'tcx> for UnsafetyChecker<'_, 'tcx> {
             // If the projection root is an artificial local that we introduced when
             // desugaring `static`, give a more specific error message
             // (avoid the general "raw pointer" clause below, that would only be confusing).
-            if let Some(box LocalInfo::StaticRef { def_id, .. }) = decl.local_info {
+            if let LocalInfo::StaticRef { def_id, .. } = *decl.local_info() {
                 if self.tcx.is_mutable_static(def_id) {
                     self.require_unsafe(
                         UnsafetyViolationKind::General,
diff --git a/compiler/rustc_mir_transform/src/deref_separator.rs b/compiler/rustc_mir_transform/src/deref_separator.rs
index 7508df92df1..b8a5b92be4a 100644
--- a/compiler/rustc_mir_transform/src/deref_separator.rs
+++ b/compiler/rustc_mir_transform/src/deref_separator.rs
@@ -40,7 +40,7 @@ impl<'tcx> MutVisitor<'tcx> for DerefChecker<'tcx> {
                     let temp = self.patcher.new_internal_with_info(
                         ty,
                         self.local_decls[p_ref.local].source_info.span,
-                        Some(Box::new(LocalInfo::DerefTemp)),
+                        LocalInfo::DerefTemp,
                     );
 
                     // We are adding current p_ref's projections to our
diff --git a/compiler/rustc_mir_transform/src/generator.rs b/compiler/rustc_mir_transform/src/generator.rs
index b7f1cdfc7f2..e6875fad306 100644
--- a/compiler/rustc_mir_transform/src/generator.rs
+++ b/compiler/rustc_mir_transform/src/generator.rs
@@ -924,13 +924,19 @@ fn compute_layout<'tcx>(
         debug!(?decl);
 
         let ignore_for_traits = if tcx.sess.opts.unstable_opts.drop_tracking_mir {
+            // Do not `assert_crate_local` here, as post-borrowck cleanup may have already cleared
+            // the information. This is alright, since `ignore_for_traits` is only relevant when
+            // this code runs on pre-cleanup MIR, and `ignore_for_traits = false` is the safer
+            // default.
             match decl.local_info {
                 // Do not include raw pointers created from accessing `static` items, as those could
                 // well be re-created by another access to the same static.
-                Some(box LocalInfo::StaticRef { is_thread_local, .. }) => !is_thread_local,
+                ClearCrossCrate::Set(box LocalInfo::StaticRef { is_thread_local, .. }) => {
+                    !is_thread_local
+                }
                 // Fake borrows are only read by fake reads, so do not have any reality in
                 // post-analysis MIR.
-                Some(box LocalInfo::FakeBorrow) => true,
+                ClearCrossCrate::Set(box LocalInfo::FakeBorrow) => true,
                 _ => false,
             }
         } else {
diff --git a/tests/mir-opt/separate_const_switch.identity.SeparateConstSwitch.diff b/tests/mir-opt/separate_const_switch.identity.SeparateConstSwitch.diff
index cfcd43093c0..bdf1de468b3 100644
--- a/tests/mir-opt/separate_const_switch.identity.SeparateConstSwitch.diff
+++ b/tests/mir-opt/separate_const_switch.identity.SeparateConstSwitch.diff
@@ -12,7 +12,6 @@
       let mut _7: !;                       // in scope 0 at $DIR/separate_const_switch.rs:+1:9: +1:10
       let mut _8: std::result::Result<std::convert::Infallible, i32>; // in scope 0 at $DIR/separate_const_switch.rs:+1:9: +1:10
       let _9: i32;                         // in scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10
-      let mut _16: i32;                    // in scope 0 at $SRC_DIR/core/src/result.rs:LL:COL
       scope 1 {
           debug residual => _6;            // in scope 1 at $DIR/separate_const_switch.rs:+1:9: +1:10
           scope 2 {
@@ -23,7 +22,7 @@
                   scope 9 {
                       debug e => _14;      // in scope 9 at $SRC_DIR/core/src/result.rs:LL:COL
                       scope 10 (inlined <i32 as From<i32>>::from) { // at $SRC_DIR/core/src/result.rs:LL:COL
-                          debug t => _16;  // in scope 10 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
+                          debug t => _14;  // in scope 10 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
                       }
                   }
               }
@@ -90,10 +89,7 @@
           StorageLive(_14);                // scope 2 at $DIR/separate_const_switch.rs:+1:8: +1:10
           _14 = move ((_8 as Err).0: i32); // scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
           StorageLive(_15);                // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL
-          StorageLive(_16);                // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL
-          _16 = move _14;                  // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL
-          _15 = move _16;                  // scope 10 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
-          StorageDead(_16);                // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL
+          _15 = move _14;                  // scope 10 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
           _0 = Result::<i32, i32>::Err(move _15); // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL
           StorageDead(_15);                // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL
           StorageDead(_14);                // scope 2 at $DIR/separate_const_switch.rs:+1:8: +1:10