1
Fork 0

Wrap the whole LocalInfo in ClearCrossCrate.

This commit is contained in:
Camille GILLOT 2023-03-09 16:55:20 +00:00
parent 2e7034ebf7
commit bcb161def7
19 changed files with 134 additions and 142 deletions

View file

@ -2482,15 +2482,14 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
let (place_description, assigned_span) = match local_decl { let (place_description, assigned_span) = match local_decl {
Some(LocalDecl { Some(LocalDecl {
local_info: local_info:
Some(box LocalInfo::User( ClearCrossCrate::Set(
ClearCrossCrate::Clear box LocalInfo::User(BindingForm::Var(VarBindingForm {
| ClearCrossCrate::Set(BindingForm::Var(VarBindingForm {
opt_match_place: None, opt_match_place: None,
.. ..
})), }))
)) | box LocalInfo::StaticRef { .. }
| Some(box LocalInfo::StaticRef { .. }) | box LocalInfo::Boring,
| None, ),
.. ..
}) })
| None => (self.describe_any_place(place.as_ref()), assigned_span), | None => (self.describe_any_place(place.as_ref()), assigned_span),

View file

@ -196,10 +196,10 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
if self.body.local_decls[local].is_ref_for_guard() { if self.body.local_decls[local].is_ref_for_guard() {
continue; continue;
} }
if let Some(box LocalInfo::StaticRef { def_id, .. }) = if let LocalInfo::StaticRef { def_id, .. } =
&self.body.local_decls[local].local_info *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(()); ok = Ok(());
continue; continue;
} }

View file

@ -102,14 +102,12 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
// //
// opt_match_place is None for let [mut] x = ... statements, // opt_match_place is None for let [mut] x = ... statements,
// whether or not the right-hand side is a place expression // whether or not the right-hand side is a place expression
if let Some(box LocalInfo::User(ClearCrossCrate::Set(BindingForm::Var( if let LocalInfo::User(BindingForm::Var(VarBindingForm {
VarBindingForm { opt_match_place: Some((opt_match_place, match_span)),
opt_match_place: Some((opt_match_place, match_span)), binding_mode: _,
binding_mode: _, opt_ty_info: _,
opt_ty_info: _, pat_span: _,
pat_span: _, })) = *local_decl.local_info()
},
)))) = local_decl.local_info
{ {
let stmt_source_info = self.body.source_info(location); let stmt_source_info = self.body.source_info(location);
self.append_binding_error( self.append_binding_error(
@ -478,9 +476,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
let mut suggestions: Vec<(Span, String, String)> = Vec::new(); let mut suggestions: Vec<(Span, String, String)> = Vec::new();
for local in binds_to { for local in binds_to {
let bind_to = &self.body.local_decls[*local]; let bind_to = &self.body.local_decls[*local];
if let Some(box LocalInfo::User(ClearCrossCrate::Set(BindingForm::Var( if let LocalInfo::User(BindingForm::Var(VarBindingForm { pat_span, .. })) =
VarBindingForm { pat_span, .. }, *bind_to.local_info()
)))) = bind_to.local_info
{ {
let Ok(pat_snippet) = let Ok(pat_snippet) =
self.infcx.tcx.sess.source_map().span_to_snippet(pat_span) else { continue; }; self.infcx.tcx.sess.source_map().span_to_snippet(pat_span) else { continue; };

View file

@ -7,7 +7,7 @@ use rustc_middle::mir::{Mutability, Place, PlaceRef, ProjectionElem};
use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_middle::{ use rustc_middle::{
hir::place::PlaceBase, 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::source_map::DesugaringKind;
use rustc_span::symbol::{kw, Symbol}; use rustc_span::symbol::{kw, Symbol};
@ -105,8 +105,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
reason = String::new(); reason = String::new();
} else { } else {
item_msg = access_place_desc; item_msg = access_place_desc;
let local_info = &self.body.local_decls[local].local_info; let local_info = self.body.local_decls[local].local_info();
if let Some(box LocalInfo::StaticRef { def_id, .. }) = *local_info { if let LocalInfo::StaticRef { def_id, .. } = *local_info {
let static_name = &self.infcx.tcx.item_name(def_id); let static_name = &self.infcx.tcx.item_name(def_id);
reason = format!(", as `{static_name}` is an immutable static item"); reason = format!(", as `{static_name}` is an immutable static item");
} else { } else {
@ -305,15 +305,13 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
.. ..
}) = &self.body[location.block].statements.get(location.statement_index) }) = &self.body[location.block].statements.get(location.statement_index)
{ {
match decl.local_info { match *decl.local_info() {
Some(box LocalInfo::User(ClearCrossCrate::Set(BindingForm::Var( LocalInfo::User(BindingForm::Var(mir::VarBindingForm {
mir::VarBindingForm { binding_mode: ty::BindingMode::BindByValue(Mutability::Not),
binding_mode: ty::BindingMode::BindByValue(Mutability::Not), opt_ty_info: Some(sp),
opt_ty_info: Some(sp), opt_match_place: _,
opt_match_place: _, pat_span: _,
pat_span: _, })) => {
},
)))) => {
if suggest { if suggest {
err.span_note(sp, "the binding is already a mutable borrow"); 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() { } else if decl.mutability.is_not() {
if matches!( if matches!(
decl.local_info, decl.local_info(),
Some(box LocalInfo::User(ClearCrossCrate::Set(BindingForm::ImplicitSelf( LocalInfo::User(BindingForm::ImplicitSelf(hir::ImplicitSelfKind::MutRef))
hir::ImplicitSelfKind::MutRef
),)))
) { ) {
err.note( err.note(
"as `Self` may be unsized, this call attempts to take `&mut &mut self`", "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] { match self.local_names[local] {
Some(name) if !local_decl.from_compiler_desugaring() => { Some(name) if !local_decl.from_compiler_desugaring() => {
let label = match local_decl.local_info.as_deref().unwrap() { let label = match *local_decl.local_info() {
LocalInfo::User(ClearCrossCrate::Set( LocalInfo::User(mir::BindingForm::ImplicitSelf(_)) => {
mir::BindingForm::ImplicitSelf(_),
)) => {
let (span, suggestion) = let (span, suggestion) =
suggest_ampmut_self(self.infcx.tcx, local_decl); suggest_ampmut_self(self.infcx.tcx, local_decl);
Some((true, span, suggestion)) Some((true, span, suggestion))
} }
LocalInfo::User(ClearCrossCrate::Set(mir::BindingForm::Var( LocalInfo::User(mir::BindingForm::Var(mir::VarBindingForm {
mir::VarBindingForm { binding_mode: ty::BindingMode::BindByValue(_),
binding_mode: ty::BindingMode::BindByValue(_), opt_ty_info,
opt_ty_info, ..
.. })) => {
},
))) => {
// check if the RHS is from desugaring // check if the RHS is from desugaring
let opt_assignment_rhs_span = let opt_assignment_rhs_span =
self.body.find_assignments(local).first().map(|&location| { self.body.find_assignments(local).first().map(|&location| {
@ -534,16 +526,15 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
self.infcx.tcx, self.infcx.tcx,
local_decl, local_decl,
opt_assignment_rhs_span, opt_assignment_rhs_span,
*opt_ty_info, opt_ty_info,
) )
} else { } else {
match local_decl.local_info.as_deref() { match local_decl.local_info() {
Some(LocalInfo::User(ClearCrossCrate::Set( LocalInfo::User(mir::BindingForm::Var(
mir::BindingForm::Var(mir::VarBindingForm { mir::VarBindingForm {
opt_ty_info: None, opt_ty_info: None, ..
.. },
}), )) => {
))) => {
let (span, sugg) = suggest_ampmut_self( let (span, sugg) = suggest_ampmut_self(
self.infcx.tcx, self.infcx.tcx,
local_decl, local_decl,
@ -555,7 +546,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
self.infcx.tcx, self.infcx.tcx,
local_decl, local_decl,
opt_assignment_rhs_span, 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( LocalInfo::User(mir::BindingForm::Var(mir::VarBindingForm {
mir::VarBindingForm { binding_mode: ty::BindingMode::BindByReference(_),
binding_mode: ty::BindingMode::BindByReference(_), ..
.. })) => {
},
))) => {
let pattern_span = local_decl.source_info.span; let pattern_span = local_decl.source_info.span;
suggest_ref_mut(self.infcx.tcx, pattern_span) suggest_ref_mut(self.infcx.tcx, pattern_span)
.map(|replacement| (true, pattern_span, replacement)) .map(|replacement| (true, pattern_span, replacement))
} }
LocalInfo::User(ClearCrossCrate::Clear) => {
bug!("saw cleared local state")
}
_ => unreachable!(), _ => 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 { 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()); 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. // Check if mutably borrowing a mutable reference.
Some(LocalInfo::User(ClearCrossCrate::Set(mir::BindingForm::Var( LocalInfo::User(mir::BindingForm::Var(mir::VarBindingForm {
mir::VarBindingForm { binding_mode: ty::BindingMode::BindByValue(Mutability::Not),
binding_mode: ty::BindingMode::BindByValue(Mutability::Not), .. ..
}, })) => matches!(local_decl.ty.kind(), ty::Ref(_, _, hir::Mutability::Mut)),
)))) => matches!(local_decl.ty.kind(), ty::Ref(_, _, hir::Mutability::Mut)), LocalInfo::User(mir::BindingForm::ImplicitSelf(kind)) => {
Some(LocalInfo::User(ClearCrossCrate::Set(mir::BindingForm::ImplicitSelf(kind)))) => {
// Check if the user variable is a `&mut self` and we can therefore // Check if the user variable is a `&mut self` and we can therefore
// suggest removing the `&mut`. // suggest removing the `&mut`.
// //
// Deliberately fall into this case for all implicit self types, // Deliberately fall into this case for all implicit self types,
// so that we don't fall in to the next case with them. // 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 => { _ if Some(kw::SelfLower) == local_name => {
// Otherwise, check if the name is the `self` keyword - in which case // Otherwise, check if the name is the `self` keyword - in which case

View file

@ -1180,10 +1180,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
} }
} }
Some(l) Some(l)
if matches!( if matches!(body.local_decls[l].local_info(), LocalInfo::AggregateTemp) =>
body.local_decls[l].local_info,
Some(box LocalInfo::AggregateTemp)
) =>
{ {
ConstraintCategory::Usage ConstraintCategory::Usage
} }

View file

@ -643,7 +643,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
if base_ty.is_unsafe_ptr() { if base_ty.is_unsafe_ptr() {
if proj_base.is_empty() { if proj_base.is_empty() {
let decl = &self.body.local_decls[place_local]; 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; let span = decl.source_info.span;
self.check_static(def_id, span); self.check_static(def_id, span);
return; return;

View file

@ -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 { pub fn assert_crate_local(self) -> T {
match self { match self {
ClearCrossCrate::Clear => bug!("unwrapping cross-crate data"), ClearCrossCrate::Clear => bug!("unwrapping cross-crate data"),
@ -760,7 +767,7 @@ pub struct LocalDecl<'tcx> {
pub mutability: Mutability, pub mutability: Mutability,
// FIXME(matthewjasper) Don't store in this in `Body` // 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. /// `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 /// The `BindingForm` is solely used for local diagnostics when generating
/// warnings/errors when compiling the current crate, and therefore it need /// warnings/errors when compiling the current crate, and therefore it need
/// not be visible across crates. /// not be visible across crates.
User(ClearCrossCrate<BindingForm<'tcx>>), User(BindingForm<'tcx>),
/// A temporary created that references the static with the given `DefId`. /// A temporary created that references the static with the given `DefId`.
StaticRef { def_id: DefId, is_thread_local: bool }, StaticRef { def_id: DefId, is_thread_local: bool },
/// A temporary created that references the const with the given `DefId` /// A temporary created that references the const with the given `DefId`
@ -902,9 +909,15 @@ pub enum LocalInfo<'tcx> {
DerefTemp, DerefTemp,
/// A temporary created for borrow checking. /// A temporary created for borrow checking.
FakeBorrow, FakeBorrow,
/// A local without anything interesting about it.
Boring,
} }
impl<'tcx> LocalDecl<'tcx> { 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 /// Returns `true` only if local is a binding that can itself be
/// made mutable via the addition of the `mut` keyword, namely /// made mutable via the addition of the `mut` keyword, namely
/// something like the occurrences of `x` in: /// something like the occurrences of `x` in:
@ -914,14 +927,14 @@ impl<'tcx> LocalDecl<'tcx> {
pub fn can_be_made_mutable(&self) -> bool { pub fn can_be_made_mutable(&self) -> bool {
matches!( matches!(
self.local_info, self.local_info,
Some(box LocalInfo::User(ClearCrossCrate::Set( ClearCrossCrate::Set(box LocalInfo::User(
BindingForm::Var(VarBindingForm { BindingForm::Var(VarBindingForm {
binding_mode: ty::BindingMode::BindByValue(_), binding_mode: ty::BindingMode::BindByValue(_),
opt_ty_info: _, opt_ty_info: _,
opt_match_place: _, opt_match_place: _,
pat_span: _, pat_span: _,
}) | BindingForm::ImplicitSelf(ImplicitSelfKind::Imm), }) | BindingForm::ImplicitSelf(ImplicitSelfKind::Imm),
))) ))
) )
} }
@ -931,14 +944,14 @@ impl<'tcx> LocalDecl<'tcx> {
pub fn is_nonref_binding(&self) -> bool { pub fn is_nonref_binding(&self) -> bool {
matches!( matches!(
self.local_info, self.local_info,
Some(box LocalInfo::User(ClearCrossCrate::Set( ClearCrossCrate::Set(box LocalInfo::User(
BindingForm::Var(VarBindingForm { BindingForm::Var(VarBindingForm {
binding_mode: ty::BindingMode::BindByValue(_), binding_mode: ty::BindingMode::BindByValue(_),
opt_ty_info: _, opt_ty_info: _,
opt_match_place: _, opt_match_place: _,
pat_span: _, pat_span: _,
}) | BindingForm::ImplicitSelf(_), }) | BindingForm::ImplicitSelf(_),
))) ))
) )
} }
@ -946,7 +959,7 @@ impl<'tcx> LocalDecl<'tcx> {
/// parameter declared by the user. /// parameter declared by the user.
#[inline] #[inline]
pub fn is_user_variable(&self) -> bool { 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` /// 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 { pub fn is_ref_for_guard(&self) -> bool {
matches!( matches!(
self.local_info, 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 /// Returns `Some` if this is a reference to a static item that is used to
/// access that static. /// access that static.
pub fn is_ref_to_static(&self) -> bool { 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 /// Returns `Some` if this is a reference to a thread-local static item that is used to
/// access that static. /// access that static.
pub fn is_ref_to_thread_local(&self) -> bool { pub fn is_ref_to_thread_local(&self) -> bool {
match self.local_info { 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, _ => false,
} }
} }
@ -977,7 +992,7 @@ impl<'tcx> LocalDecl<'tcx> {
/// Returns `true` if this is a DerefTemp /// Returns `true` if this is a DerefTemp
pub fn is_deref_temp(&self) -> bool { pub fn is_deref_temp(&self) -> bool {
match self.local_info { match self.local_info {
Some(box LocalInfo::DerefTemp) => return true, ClearCrossCrate::Set(box LocalInfo::DerefTemp) => return true,
_ => (), _ => (),
} }
return false; return false;
@ -1001,7 +1016,7 @@ impl<'tcx> LocalDecl<'tcx> {
pub fn with_source_info(ty: Ty<'tcx>, source_info: SourceInfo) -> Self { pub fn with_source_info(ty: Ty<'tcx>, source_info: SourceInfo) -> Self {
LocalDecl { LocalDecl {
mutability: Mutability::Mut, mutability: Mutability::Mut,
local_info: None, local_info: ClearCrossCrate::Set(Box::new(LocalInfo::Boring)),
internal: false, internal: false,
is_block_tail: None, is_block_tail: None,
ty, ty,

View file

@ -72,12 +72,12 @@ impl<'tcx> MirPatch<'tcx> {
&mut self, &mut self,
ty: Ty<'tcx>, ty: Ty<'tcx>,
span: Span, span: Span,
local_info: Option<Box<LocalInfo<'tcx>>>, local_info: LocalInfo<'tcx>,
) -> Local { ) -> Local {
let index = self.next_local; let index = self.next_local;
self.next_local += 1; self.next_local += 1;
let mut new_decl = LocalDecl::new(ty, span).internal(); 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); self.new_locals.push(new_decl);
Local::new(index as usize) Local::new(index as usize)
} }

View file

@ -20,7 +20,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
expr: &Expr<'tcx>, expr: &Expr<'tcx>,
) -> BlockAnd<Operand<'tcx>> { ) -> BlockAnd<Operand<'tcx>> {
let local_scope = self.local_scope(); 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 /// 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, mut block: BasicBlock,
scope: Option<region::Scope>, scope: Option<region::Scope>,
expr: &Expr<'tcx>, expr: &Expr<'tcx>,
local_info: Option<Box<LocalInfo<'tcx>>>, local_info: LocalInfo<'tcx>,
needs_temporary: NeedsTemporary, needs_temporary: NeedsTemporary,
) -> BlockAnd<Operand<'tcx>> { ) -> BlockAnd<Operand<'tcx>> {
let this = self; let this = self;
@ -124,8 +124,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
} }
Category::Constant | Category::Place | Category::Rvalue(..) => { Category::Constant | Category::Place | Category::Rvalue(..) => {
let operand = unpack!(block = this.as_temp(block, scope, expr, Mutability::Mut)); let operand = unpack!(block = this.as_temp(block, scope, expr, Mutability::Mut));
if this.local_decls[operand].local_info.is_none() { let decl_info = this.local_decls[operand].local_info.as_mut().assert_crate_local();
this.local_decls[operand].local_info = local_info; if let LocalInfo::Boring = **decl_info {
**decl_info = local_info;
} }
block.and(Operand::Move(Place::from(operand))) 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)
} }
} }

View file

@ -63,7 +63,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
block, block,
scope, scope,
&this.thir[value], &this.thir[value],
None, LocalInfo::Boring,
NeedsTemporary::No NeedsTemporary::No
) )
); );
@ -73,18 +73,18 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
ExprKind::Binary { op, lhs, rhs } => { ExprKind::Binary { op, lhs, rhs } => {
let lhs = unpack!( let lhs = unpack!(
block = 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!( let rhs = unpack!(
block = 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) this.build_binary_op(block, op, expr_span, expr.ty, lhs, rhs)
} }
ExprKind::Unary { op, arg } => { ExprKind::Unary { op, arg } => {
let arg = unpack!( let arg = unpack!(
block = 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 // Check for -MIN on signed integers
if this.check_overflow && op == UnOp::Neg && expr.ty.is_signed() { if this.check_overflow && op == UnOp::Neg && expr.ty.is_signed() {
@ -259,7 +259,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
} else { } else {
let ty = source.ty; let ty = source.ty;
let source = unpack!( 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) (source, ty)
}; };
@ -272,7 +272,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
ExprKind::Pointer { cast, source } => { ExprKind::Pointer { cast, source } => {
let source = unpack!( let source = unpack!(
block = 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)) block.and(Rvalue::Cast(CastKind::Pointer(cast), source, expr.ty))
} }
@ -314,7 +314,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
block, block,
scope, scope,
&this.thir[f], &this.thir[f],
None, LocalInfo::Boring,
NeedsTemporary::Maybe NeedsTemporary::Maybe
) )
) )
@ -335,7 +335,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
block, block,
scope, scope,
&this.thir[f], &this.thir[f],
None, LocalInfo::Boring,
NeedsTemporary::Maybe NeedsTemporary::Maybe
) )
) )
@ -423,7 +423,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
block, block,
scope, scope,
upvar, upvar,
None, LocalInfo::Boring,
NeedsTemporary::Maybe NeedsTemporary::Maybe
) )
) )
@ -502,7 +502,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
Some(Category::Rvalue(RvalueFunc::AsRvalue) | Category::Constant) Some(Category::Rvalue(RvalueFunc::AsRvalue) | Category::Constant)
)); ));
let operand = 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)) block.and(Rvalue::Use(operand))
} }
} }
@ -622,7 +622,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
} else { } else {
// For a non-const, we may need to generate an appropriate `Drop` // For a non-const, we may need to generate an appropriate `Drop`
let value_operand = 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 { if let Operand::Move(to_drop) = value_operand {
let success = this.cfg.start_new_block(); let success = this.cfg.start_new_block();
this.cfg.terminate( this.cfg.terminate(

View file

@ -58,17 +58,17 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
ExprKind::StaticRef { def_id, .. } => { ExprKind::StaticRef { def_id, .. } => {
assert!(!this.tcx.is_thread_local_static(def_id)); assert!(!this.tcx.is_thread_local_static(def_id));
local_decl.internal = true; local_decl.internal = true;
local_decl.local_info = **local_decl.local_info.as_mut().assert_crate_local() =
Some(Box::new(LocalInfo::StaticRef { def_id, is_thread_local: false })); LocalInfo::StaticRef { def_id, is_thread_local: false };
} }
ExprKind::ThreadLocalRef(def_id) => { ExprKind::ThreadLocalRef(def_id) => {
assert!(this.tcx.is_thread_local_static(def_id)); assert!(this.tcx.is_thread_local_static(def_id));
local_decl.internal = true; local_decl.internal = true;
local_decl.local_info = **local_decl.local_info.as_mut().assert_crate_local() =
Some(Box::new(LocalInfo::StaticRef { def_id, is_thread_local: true })); LocalInfo::StaticRef { def_id, is_thread_local: true };
} }
ExprKind::NamedConst { def_id, .. } | ExprKind::ConstParam { def_id, .. } => { 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 };
} }
_ => {} _ => {}
} }

View file

@ -328,7 +328,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
let fields_map: FxHashMap<_, _> = fields let fields_map: FxHashMap<_, _> = fields
.into_iter() .into_iter()
.map(|f| { .map(|f| {
let local_info = Box::new(LocalInfo::AggregateTemp);
( (
f.name, f.name,
unpack!( unpack!(
@ -336,7 +335,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
block, block,
Some(scope), Some(scope),
&this.thir[f.expr], &this.thir[f.expr],
Some(local_info), LocalInfo::AggregateTemp,
NeedsTemporary::Maybe, NeedsTemporary::Maybe,
) )
), ),
@ -526,7 +525,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
block, block,
Some(scope), Some(scope),
&this.thir[value], &this.thir[value],
None, LocalInfo::Boring,
NeedsTemporary::No NeedsTemporary::No
) )
); );

View file

@ -607,9 +607,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
// }; // };
// ``` // ```
if let Some(place) = initializer.try_to_place(self) { 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, _)), .. }, 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.") bug!("Let binding to non-user variable.")
}; };
*match_place = Some(place); *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 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); 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.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); let fake_borrow_temp = self.local_decls.push(fake_borrow_temp);
(matched_place, fake_borrow_temp) (matched_place, fake_borrow_temp)
@ -2225,7 +2225,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
source_info, source_info,
internal: false, internal: false,
is_block_tail: None, 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 { VarBindingForm {
binding_mode, binding_mode,
// hypothetically, `visit_primary_bindings` could try to unzip // hypothetically, `visit_primary_bindings` could try to unzip
@ -2236,7 +2236,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
opt_match_place, opt_match_place,
pat_span, pat_span,
}, },
))))), )))),
}; };
let for_arm_body = self.local_decls.push(local); let for_arm_body = self.local_decls.push(local);
self.var_debug_info.push(VarDebugInfo { self.var_debug_info.push(VarDebugInfo {
@ -2254,9 +2254,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
source_info, source_info,
internal: false, internal: false,
is_block_tail: None, is_block_tail: None,
local_info: Some(Box::new(LocalInfo::User(ClearCrossCrate::Set( local_info: ClearCrossCrate::Set(Box::new(LocalInfo::User(BindingForm::RefForGuard))),
BindingForm::RefForGuard,
)))),
}); });
self.var_debug_info.push(VarDebugInfo { self.var_debug_info.push(VarDebugInfo {
name, name,

View file

@ -876,20 +876,20 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
} => { } => {
self.local_decls[local].mutability = mutability; self.local_decls[local].mutability = mutability;
self.local_decls[local].source_info.scope = self.source_scope; self.local_decls[local].source_info.scope = self.source_scope;
self.local_decls[local].local_info = if let Some(kind) = param.self_kind { **self.local_decls[local].local_info.as_mut().assert_crate_local() = if let Some(kind) = param.self_kind {
Some(Box::new(LocalInfo::User(ClearCrossCrate::Set( LocalInfo::User(
BindingForm::ImplicitSelf(kind), BindingForm::ImplicitSelf(kind),
)))) )
} else { } else {
let binding_mode = ty::BindingMode::BindByValue(mutability); let binding_mode = ty::BindingMode::BindByValue(mutability);
Some(Box::new(LocalInfo::User(ClearCrossCrate::Set(BindingForm::Var( LocalInfo::User(BindingForm::Var(
VarBindingForm { VarBindingForm {
binding_mode, binding_mode,
opt_ty_info: param.ty_span, opt_ty_info: param.ty_span,
opt_match_place: Some((None, span)), opt_match_place: Some((None, span)),
pat_span: span, pat_span: span,
}, },
))))) ))
}; };
self.var_indices.insert(var, LocalsForNode::One(local)); self.var_indices.insert(var, LocalsForNode::One(local));
} }

View file

@ -24,7 +24,7 @@ struct ConstMutationChecker<'a, 'tcx> {
impl<'tcx> ConstMutationChecker<'_, 'tcx> { impl<'tcx> ConstMutationChecker<'_, 'tcx> {
fn is_const_item(&self, local: Local) -> Option<DefId> { 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) Some(def_id)
} else { } else {
None None

View file

@ -182,7 +182,7 @@ impl<'tcx> Visitor<'tcx> for UnsafetyChecker<'_, 'tcx> {
// If the projection root is an artificial local that we introduced when // If the projection root is an artificial local that we introduced when
// desugaring `static`, give a more specific error message // desugaring `static`, give a more specific error message
// (avoid the general "raw pointer" clause below, that would only be confusing). // (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) { if self.tcx.is_mutable_static(def_id) {
self.require_unsafe( self.require_unsafe(
UnsafetyViolationKind::General, UnsafetyViolationKind::General,

View file

@ -40,7 +40,7 @@ impl<'tcx> MutVisitor<'tcx> for DerefChecker<'tcx> {
let temp = self.patcher.new_internal_with_info( let temp = self.patcher.new_internal_with_info(
ty, ty,
self.local_decls[p_ref.local].source_info.span, 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 // We are adding current p_ref's projections to our

View file

@ -924,13 +924,19 @@ fn compute_layout<'tcx>(
debug!(?decl); debug!(?decl);
let ignore_for_traits = if tcx.sess.opts.unstable_opts.drop_tracking_mir { 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 { match decl.local_info {
// Do not include raw pointers created from accessing `static` items, as those could // Do not include raw pointers created from accessing `static` items, as those could
// well be re-created by another access to the same static. // 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 // Fake borrows are only read by fake reads, so do not have any reality in
// post-analysis MIR. // post-analysis MIR.
Some(box LocalInfo::FakeBorrow) => true, ClearCrossCrate::Set(box LocalInfo::FakeBorrow) => true,
_ => false, _ => false,
} }
} else { } else {

View file

@ -12,7 +12,6 @@
let mut _7: !; // in scope 0 at $DIR/separate_const_switch.rs:+1:9: +1:10 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 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 _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 { scope 1 {
debug residual => _6; // in scope 1 at $DIR/separate_const_switch.rs:+1:9: +1:10 debug residual => _6; // in scope 1 at $DIR/separate_const_switch.rs:+1:9: +1:10
scope 2 { scope 2 {
@ -23,7 +22,7 @@
scope 9 { scope 9 {
debug e => _14; // in scope 9 at $SRC_DIR/core/src/result.rs:LL:COL 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 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 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 _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(_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 _15 = move _14; // scope 10 at $SRC_DIR/core/src/convert/mod.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
_0 = Result::<i32, i32>::Err(move _15); // scope 9 at $SRC_DIR/core/src/result.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(_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 StorageDead(_14); // scope 2 at $DIR/separate_const_switch.rs:+1:8: +1:10