Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Shrink LocalDecl #71942

Merged
merged 5 commits into from
May 9, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
116 changes: 57 additions & 59 deletions src/librustc_middle/mir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -474,6 +474,13 @@ pub struct SourceInfo {
pub scope: SourceScope,
}

impl SourceInfo {
#[inline]
pub fn outermost(span: Span) -> Self {
SourceInfo { span, scope: OUTERMOST_SOURCE_SCOPE }
}
}

///////////////////////////////////////////////////////////////////////////
// Borrow kinds

Expand Down Expand Up @@ -689,7 +696,7 @@ pub struct LocalDecl<'tcx> {
pub mutability: Mutability,

// FIXME(matthewjasper) Don't store in this in `Body`
pub local_info: LocalInfo<'tcx>,
pub local_info: Option<Box<LocalInfo<'tcx>>>,

/// `true` if this is an internal local.
///
Expand Down Expand Up @@ -725,7 +732,7 @@ pub struct LocalDecl<'tcx> {
/// borrow checker needs this information since it can affect
/// region inference.
// FIXME(matthewjasper) Don't store in this in `Body`
pub user_ty: UserTypeProjections,
pub user_ty: Option<Box<UserTypeProjections>>,

/// The *syntactic* (i.e., not visibility) source scope the local is defined
/// in. If the local was defined in a let-statement, this
Expand Down Expand Up @@ -809,7 +816,13 @@ pub struct LocalDecl<'tcx> {
pub source_info: SourceInfo,
}

/// Extra information about a local that's used for diagnostics.
// `LocalDecl` is used a lot. Make sure it doesn't unintentionally get bigger.
#[cfg(target_arch = "x86_64")]
static_assert_size!(LocalDecl<'_>, 56);

/// Extra information about a some locals that's used for diagnostics. (Not
/// used for non-StaticRef temporaries, the return place, or anonymous function
/// parameters.)
#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable, TypeFoldable)]
pub enum LocalInfo<'tcx> {
/// A user-defined local variable or function parameter
Expand All @@ -820,8 +833,6 @@ pub enum LocalInfo<'tcx> {
User(ClearCrossCrate<BindingForm<'tcx>>),
/// A temporary created that references the static with the given `DefId`.
StaticRef { def_id: DefId, is_thread_local: bool },
/// Any other temporary, the return place, or an anonymous function parameter.
Other,
}

impl<'tcx> LocalDecl<'tcx> {
Expand All @@ -833,16 +844,16 @@ impl<'tcx> LocalDecl<'tcx> {
/// - or `match ... { C(x) => ... }`
pub fn can_be_made_mutable(&self) -> bool {
match self.local_info {
LocalInfo::User(ClearCrossCrate::Set(BindingForm::Var(VarBindingForm {
Some(box LocalInfo::User(ClearCrossCrate::Set(BindingForm::Var(VarBindingForm {
binding_mode: ty::BindingMode::BindByValue(_),
opt_ty_info: _,
opt_match_place: _,
pat_span: _,
}))) => true,
})))) => true,

LocalInfo::User(ClearCrossCrate::Set(BindingForm::ImplicitSelf(
Some(box LocalInfo::User(ClearCrossCrate::Set(BindingForm::ImplicitSelf(
ImplicitSelfKind::Imm,
))) => true,
)))) => true,

_ => false,
}
Expand All @@ -853,14 +864,14 @@ impl<'tcx> LocalDecl<'tcx> {
/// mutable bindings, but the inverse does not necessarily hold).
pub fn is_nonref_binding(&self) -> bool {
match self.local_info {
LocalInfo::User(ClearCrossCrate::Set(BindingForm::Var(VarBindingForm {
Some(box LocalInfo::User(ClearCrossCrate::Set(BindingForm::Var(VarBindingForm {
binding_mode: ty::BindingMode::BindByValue(_),
opt_ty_info: _,
opt_match_place: _,
pat_span: _,
}))) => true,
})))) => true,

LocalInfo::User(ClearCrossCrate::Set(BindingForm::ImplicitSelf(_))) => true,
Some(box LocalInfo::User(ClearCrossCrate::Set(BindingForm::ImplicitSelf(_)))) => true,

_ => false,
}
Expand All @@ -871,7 +882,7 @@ impl<'tcx> LocalDecl<'tcx> {
#[inline]
pub fn is_user_variable(&self) -> bool {
match self.local_info {
LocalInfo::User(_) => true,
Some(box LocalInfo::User(_)) => true,
_ => false,
}
}
Expand All @@ -881,7 +892,7 @@ impl<'tcx> LocalDecl<'tcx> {
/// match arm.
pub fn is_ref_for_guard(&self) -> bool {
match self.local_info {
LocalInfo::User(ClearCrossCrate::Set(BindingForm::RefForGuard)) => true,
Some(box LocalInfo::User(ClearCrossCrate::Set(BindingForm::RefForGuard))) => true,
_ => false,
}
}
Expand All @@ -890,7 +901,7 @@ impl<'tcx> LocalDecl<'tcx> {
/// access that static
pub fn is_ref_to_static(&self) -> bool {
match self.local_info {
LocalInfo::StaticRef { .. } => true,
Some(box LocalInfo::StaticRef { .. }) => true,
_ => false,
}
}
Expand All @@ -899,7 +910,7 @@ impl<'tcx> LocalDecl<'tcx> {
/// access that static
pub fn is_ref_to_thread_local(&self) -> bool {
match self.local_info {
LocalInfo::StaticRef { is_thread_local, .. } => is_thread_local,
Some(box LocalInfo::StaticRef { is_thread_local, .. }) => is_thread_local,
_ => false,
}
}
Expand All @@ -911,10 +922,31 @@ impl<'tcx> LocalDecl<'tcx> {
self.source_info.span.desugaring_kind().is_some()
}

/// Creates a new `LocalDecl` for a temporary.
/// Creates a new `LocalDecl` for a temporary: mutable, non-internal.
#[inline]
pub fn new_temp(ty: Ty<'tcx>, span: Span) -> Self {
Self::new_local(ty, Mutability::Mut, false, span)
pub fn new(ty: Ty<'tcx>, span: Span) -> Self {
Self::with_source_info(ty, SourceInfo::outermost(span))
}

/// Like `LocalDecl::new`, but takes a `SourceInfo` instead of a `Span`.
#[inline]
pub fn with_source_info(ty: Ty<'tcx>, source_info: SourceInfo) -> Self {
LocalDecl {
mutability: Mutability::Mut,
local_info: None,
internal: false,
is_block_tail: None,
ty,
user_ty: None,
source_info,
}
}

/// Converts `self` into same `LocalDecl` except tagged as internal.
#[inline]
pub fn internal(mut self) -> Self {
self.internal = true;
self
}

/// Converts `self` into same `LocalDecl` except tagged as immutable.
Expand All @@ -931,41 +963,6 @@ impl<'tcx> LocalDecl<'tcx> {
self.is_block_tail = Some(info);
self
}

/// Creates a new `LocalDecl` for a internal temporary.
#[inline]
pub fn new_internal(ty: Ty<'tcx>, span: Span) -> Self {
Self::new_local(ty, Mutability::Mut, true, span)
}

#[inline]
fn new_local(ty: Ty<'tcx>, mutability: Mutability, internal: bool, span: Span) -> Self {
LocalDecl {
mutability,
ty,
user_ty: UserTypeProjections::none(),
source_info: SourceInfo { span, scope: OUTERMOST_SOURCE_SCOPE },
internal,
local_info: LocalInfo::Other,
is_block_tail: None,
}
}

/// Builds a `LocalDecl` for the return place.
///
/// This must be inserted into the `local_decls` list as the first local.
#[inline]
pub fn new_return_place(return_ty: Ty<'_>, span: Span) -> LocalDecl<'_> {
LocalDecl {
mutability: Mutability::Mut,
ty: return_ty,
user_ty: UserTypeProjections::none(),
source_info: SourceInfo { span, scope: OUTERMOST_SOURCE_SCOPE },
internal: false,
is_block_tail: None,
local_info: LocalInfo::Other,
}
}
}

/// Debug information pertaining to a user variable.
Expand Down Expand Up @@ -1406,10 +1403,7 @@ impl<'tcx> BasicBlockData<'tcx> {
let mut gap = self.statements.len()..self.statements.len() + extra_stmts;
self.statements.resize(
gap.end,
Statement {
source_info: SourceInfo { span: DUMMY_SP, scope: OUTERMOST_SOURCE_SCOPE },
kind: StatementKind::Nop,
},
Statement { source_info: SourceInfo::outermost(DUMMY_SP), kind: StatementKind::Nop },
);
for (splice_start, new_stmts) in splices.into_iter().rev() {
let splice_end = splice_start + new_stmts.size_hint().0;
Expand Down Expand Up @@ -2457,14 +2451,18 @@ impl Constant<'tcx> {
/// &'static str`.
#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable, TypeFoldable)]
pub struct UserTypeProjections {
pub(crate) contents: Vec<(UserTypeProjection, Span)>,
pub contents: Vec<(UserTypeProjection, Span)>,
}

impl<'tcx> UserTypeProjections {
pub fn none() -> Self {
UserTypeProjections { contents: vec![] }
}

pub fn is_empty(&self) -> bool {
self.contents.is_empty()
}

pub fn from_projections(projs: impl Iterator<Item = (UserTypeProjection, Span)>) -> Self {
UserTypeProjections { contents: projs.collect() }
}
Expand Down
22 changes: 12 additions & 10 deletions src/librustc_middle/mir/visit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -242,10 +242,10 @@ macro_rules! make_mir_visitor {
) {
let span = body.span;
if let Some(yield_ty) = &$($mutability)? body.yield_ty {
self.visit_ty(yield_ty, TyContext::YieldTy(SourceInfo {
span,
scope: OUTERMOST_SOURCE_SCOPE,
}));
self.visit_ty(
yield_ty,
TyContext::YieldTy(SourceInfo::outermost(span))
);
}

// for best performance, we want to use an iterator rather
Expand All @@ -263,10 +263,10 @@ macro_rules! make_mir_visitor {
self.visit_source_scope_data(scope);
}

self.visit_ty(&$($mutability)? body.return_ty(), TyContext::ReturnTy(SourceInfo {
span: body.span,
scope: OUTERMOST_SOURCE_SCOPE,
}));
self.visit_ty(
&$($mutability)? body.return_ty(),
TyContext::ReturnTy(SourceInfo::outermost(body.span))
);

for local in body.local_decls.indices() {
self.visit_local_decl(local, & $($mutability)? body.local_decls[local]);
Expand Down Expand Up @@ -715,8 +715,10 @@ macro_rules! make_mir_visitor {
local,
source_info: *source_info,
});
for (user_ty, _) in & $($mutability)? user_ty.contents {
self.visit_user_type_projection(user_ty);
if let Some(user_ty) = user_ty {
for (user_ty, _) in & $($mutability)? user_ty.contents {
self.visit_user_type_projection(user_ty);
}
}
self.visit_source_info(source_info);
}
Expand Down
8 changes: 4 additions & 4 deletions src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1448,15 +1448,15 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
let (place_description, assigned_span) = match local_decl {
Some(LocalDecl {
local_info:
LocalInfo::User(
Some(box LocalInfo::User(
ClearCrossCrate::Clear
| ClearCrossCrate::Set(BindingForm::Var(VarBindingForm {
opt_match_place: None,
..
})),
)
| LocalInfo::StaticRef { .. }
| LocalInfo::Other,
))
| Some(box LocalInfo::StaticRef { .. })
| None,
..
})
| None => (self.describe_any_place(place.as_ref()), assigned_span),
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_mir/borrow_check/diagnostics/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
if self.body.local_decls[local].is_ref_to_static() =>
{
let local_info = &self.body.local_decls[local].local_info;
if let LocalInfo::StaticRef { def_id, .. } = *local_info {
if let Some(box LocalInfo::StaticRef { def_id, .. }) = *local_info {
buf.push_str(&self.infcx.tcx.item_name(def_id).as_str());
} else {
unreachable!();
Expand Down
11 changes: 5 additions & 6 deletions src/librustc_mir/borrow_check/diagnostics/move_errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,14 +103,14 @@ 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 LocalInfo::User(ClearCrossCrate::Set(BindingForm::Var(
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
)))) = local_decl.local_info
{
let stmt_source_info = self.body.source_info(location);
self.append_binding_error(
Expand Down Expand Up @@ -482,10 +482,9 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
let mut suggestions: Vec<(Span, &str, String)> = Vec::new();
for local in binds_to {
let bind_to = &self.body.local_decls[*local];
if let LocalInfo::User(ClearCrossCrate::Set(BindingForm::Var(VarBindingForm {
pat_span,
..
}))) = bind_to.local_info
if let Some(box LocalInfo::User(ClearCrossCrate::Set(BindingForm::Var(
VarBindingForm { pat_span, .. },
)))) = bind_to.local_info
{
if let Ok(pat_snippet) = self.infcx.tcx.sess.source_map().span_to_snippet(pat_span)
{
Expand Down
Loading