Shrink LocalDecl by 16 bytes.

By boxing `user_ty`.
This commit is contained in:
Nicholas Nethercote 2020-05-06 12:41:15 +10:00
parent 27ae2f0d60
commit 001496c0eb
6 changed files with 51 additions and 41 deletions

View File

@ -732,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
@ -818,7 +818,7 @@ pub struct LocalDecl<'tcx> {
// `LocalDecl` is used a lot. Make sure it doesn't unintentionally get bigger.
#[cfg(target_arch = "x86_64")]
static_assert_size!(LocalDecl<'_>, 72);
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
@ -937,7 +937,7 @@ impl<'tcx> LocalDecl<'tcx> {
internal: false,
is_block_tail: None,
ty,
user_ty: UserTypeProjections::none(),
user_ty: None,
source_info,
}
}
@ -2451,7 +2451,7 @@ 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 {
@ -2459,6 +2459,10 @@ impl<'tcx> UserTypeProjections {
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() }
}

View File

@ -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);
}

View File

@ -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 Some(box 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)
{

View File

@ -405,35 +405,38 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
self.super_local_decl(local, local_decl);
self.sanitize_type(local_decl, local_decl.ty);
for (user_ty, span) in local_decl.user_ty.projections_and_spans() {
let ty = if !local_decl.is_nonref_binding() {
// If we have a binding of the form `let ref x: T = ..` then remove the outermost
// reference so we can check the type annotation for the remaining type.
if let ty::Ref(_, rty, _) = local_decl.ty.kind {
rty
if let Some(user_ty) = &local_decl.user_ty {
for (user_ty, span) in user_ty.projections_and_spans() {
let ty = if !local_decl.is_nonref_binding() {
// If we have a binding of the form `let ref x: T = ..`
// then remove the outermost reference so we can check the
// type annotation for the remaining type.
if let ty::Ref(_, rty, _) = local_decl.ty.kind {
rty
} else {
bug!("{:?} with ref binding has wrong type {}", local, local_decl.ty);
}
} else {
bug!("{:?} with ref binding has wrong type {}", local, local_decl.ty);
}
} else {
local_decl.ty
};
local_decl.ty
};
if let Err(terr) = self.cx.relate_type_and_user_type(
ty,
ty::Variance::Invariant,
user_ty,
Locations::All(*span),
ConstraintCategory::TypeAnnotation,
) {
span_mirbug!(
self,
local,
"bad user type on variable {:?}: {:?} != {:?} ({:?})",
local,
local_decl.ty,
local_decl.user_ty,
terr,
);
if let Err(terr) = self.cx.relate_type_and_user_type(
ty,
ty::Variance::Invariant,
user_ty,
Locations::All(*span),
ConstraintCategory::TypeAnnotation,
) {
span_mirbug!(
self,
local,
"bad user type on variable {:?}: {:?} != {:?} ({:?})",
local,
local_decl.ty,
local_decl.user_ty,
terr,
);
}
}
}
}

View File

@ -472,8 +472,10 @@ fn write_scope_tree(
let mut indented_decl =
format!("{0:1$}let {2}{3:?}: {4:?}", INDENT, indent, mut_str, local, local_decl.ty);
for user_ty in local_decl.user_ty.projections() {
write!(indented_decl, " as {:?}", user_ty).unwrap();
if let Some(user_ty) = &local_decl.user_ty {
for user_ty in user_ty.projections() {
write!(indented_decl, " as {:?}", user_ty).unwrap();
}
}
indented_decl.push_str(";");

View File

@ -1949,7 +1949,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
let local = LocalDecl::<'tcx> {
mutability,
ty: var_ty,
user_ty,
user_ty: if user_ty.is_empty() { None } else { Some(box user_ty) },
source_info,
internal: false,
is_block_tail: None,
@ -1976,7 +1976,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
// immutable to avoid the unused mut lint.
mutability: Mutability::Not,
ty: tcx.mk_imm_ref(tcx.lifetimes.re_erased, var_ty),
user_ty: UserTypeProjections::none(),
user_ty: None,
source_info,
internal: false,
is_block_tail: None,