Auto merge of #108944 - cjgillot:clear-local-info, r=oli-obk
Wrap the whole LocalInfo in ClearCrossCrate. MIR contains a lot of information about locals. The primary purpose of this information is the quality of borrowck diagnostics. This PR aims to drop this information after MIR analyses are finished, ie. starting from post-cleanup runtime MIR.
This commit is contained in:
commit
511364e787
30 changed files with 188 additions and 214 deletions
|
@ -401,8 +401,6 @@ impl<'tcx> Body<'tcx> {
|
|||
LocalKind::ReturnPointer
|
||||
} else if index < self.arg_count + 1 {
|
||||
LocalKind::Arg
|
||||
} else if self.local_decls[local].is_user_variable() {
|
||||
LocalKind::Var
|
||||
} else {
|
||||
LocalKind::Temp
|
||||
}
|
||||
|
@ -572,6 +570,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"),
|
||||
|
@ -661,9 +666,7 @@ impl Atom for Local {
|
|||
/// Classifies locals into categories. See `Body::local_kind`.
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Debug, HashStable)]
|
||||
pub enum LocalKind {
|
||||
/// User-declared variable binding.
|
||||
Var,
|
||||
/// Compiler-introduced temporary.
|
||||
/// User-declared variable binding or compiler-introduced temporary.
|
||||
Temp,
|
||||
/// Function argument.
|
||||
Arg,
|
||||
|
@ -760,7 +763,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.
|
||||
///
|
||||
|
@ -778,13 +781,6 @@ pub struct LocalDecl<'tcx> {
|
|||
/// generator.
|
||||
pub internal: bool,
|
||||
|
||||
/// If this local is a temporary and `is_block_tail` is `Some`,
|
||||
/// then it is a temporary created for evaluation of some
|
||||
/// subexpression of some block's tail expression (with no
|
||||
/// intervening statement context).
|
||||
// FIXME(matthewjasper) Don't store in this in `Body`
|
||||
pub is_block_tail: Option<BlockTailInfo>,
|
||||
|
||||
/// The type of this local.
|
||||
pub ty: Ty<'tcx>,
|
||||
|
||||
|
@ -890,7 +886,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`
|
||||
|
@ -898,13 +894,23 @@ pub enum LocalInfo<'tcx> {
|
|||
/// A temporary created during the creation of an aggregate
|
||||
/// (e.g. a temporary for `foo` in `MyStruct { my_field: foo }`)
|
||||
AggregateTemp,
|
||||
/// A temporary created for evaluation of some subexpression of some block's tail expression
|
||||
/// (with no intervening statement context).
|
||||
// FIXME(matthewjasper) Don't store in this in `Body`
|
||||
BlockTailTemp(BlockTailInfo),
|
||||
/// A temporary created during the pass `Derefer` to avoid it's retagging
|
||||
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:
|
||||
|
@ -913,15 +919,15 @@ impl<'tcx> LocalDecl<'tcx> {
|
|||
/// - or `match ... { C(x) => ... }`
|
||||
pub fn can_be_made_mutable(&self) -> bool {
|
||||
matches!(
|
||||
self.local_info,
|
||||
Some(box LocalInfo::User(ClearCrossCrate::Set(
|
||||
self.local_info(),
|
||||
LocalInfo::User(
|
||||
BindingForm::Var(VarBindingForm {
|
||||
binding_mode: ty::BindingMode::BindByValue(_),
|
||||
opt_ty_info: _,
|
||||
opt_match_place: _,
|
||||
pat_span: _,
|
||||
}) | BindingForm::ImplicitSelf(ImplicitSelfKind::Imm),
|
||||
)))
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -930,15 +936,15 @@ impl<'tcx> LocalDecl<'tcx> {
|
|||
/// mutable bindings, but the inverse does not necessarily hold).
|
||||
pub fn is_nonref_binding(&self) -> bool {
|
||||
matches!(
|
||||
self.local_info,
|
||||
Some(box LocalInfo::User(ClearCrossCrate::Set(
|
||||
self.local_info(),
|
||||
LocalInfo::User(
|
||||
BindingForm::Var(VarBindingForm {
|
||||
binding_mode: ty::BindingMode::BindByValue(_),
|
||||
opt_ty_info: _,
|
||||
opt_match_place: _,
|
||||
pat_span: _,
|
||||
}) | BindingForm::ImplicitSelf(_),
|
||||
)))
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -946,38 +952,35 @@ 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(), LocalInfo::User(_))
|
||||
}
|
||||
|
||||
/// Returns `true` if this is a reference to a variable bound in a `match`
|
||||
/// expression that is used to access said variable for the guard of the
|
||||
/// match arm.
|
||||
pub fn is_ref_for_guard(&self) -> bool {
|
||||
matches!(
|
||||
self.local_info,
|
||||
Some(box LocalInfo::User(ClearCrossCrate::Set(BindingForm::RefForGuard)))
|
||||
)
|
||||
matches!(self.local_info(), 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(), 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,
|
||||
match self.local_info() {
|
||||
LocalInfo::StaticRef { is_thread_local, .. } => *is_thread_local,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns `true` if this is a DerefTemp
|
||||
pub fn is_deref_temp(&self) -> bool {
|
||||
match self.local_info {
|
||||
Some(box LocalInfo::DerefTemp) => return true,
|
||||
match self.local_info() {
|
||||
LocalInfo::DerefTemp => return true,
|
||||
_ => (),
|
||||
}
|
||||
return false;
|
||||
|
@ -1001,9 +1004,8 @@ 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,
|
||||
user_ty: None,
|
||||
source_info,
|
||||
|
@ -1023,14 +1025,6 @@ impl<'tcx> LocalDecl<'tcx> {
|
|||
self.mutability = Mutability::Not;
|
||||
self
|
||||
}
|
||||
|
||||
/// Converts `self` into same `LocalDecl` except tagged as internal temporary.
|
||||
#[inline]
|
||||
pub fn block_tail(mut self, info: BlockTailInfo) -> Self {
|
||||
assert!(self.is_block_tail.is_none());
|
||||
self.is_block_tail = Some(info);
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)]
|
||||
|
@ -3091,7 +3085,7 @@ mod size_asserts {
|
|||
use rustc_data_structures::static_assert_size;
|
||||
// tidy-alphabetical-start
|
||||
static_assert_size!(BasicBlockData<'_>, 144);
|
||||
static_assert_size!(LocalDecl<'_>, 56);
|
||||
static_assert_size!(LocalDecl<'_>, 40);
|
||||
static_assert_size!(Statement<'_>, 32);
|
||||
static_assert_size!(StatementKind<'_>, 16);
|
||||
static_assert_size!(Terminator<'_>, 112);
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -804,7 +804,6 @@ macro_rules! make_mir_visitor {
|
|||
source_info,
|
||||
internal: _,
|
||||
local_info: _,
|
||||
is_block_tail: _,
|
||||
} = local_decl;
|
||||
|
||||
self.visit_ty($(& $mutability)? *ty, TyContext::LocalDecl {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue