From 001496c0ebb27373ace8bd019b78b3f02ce531d1 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 6 May 2020 12:41:15 +1000 Subject: [PATCH] Shrink `LocalDecl` by 16 bytes. By boxing `user_ty`. --- src/librustc_middle/mir/mod.rs | 12 ++-- src/librustc_middle/mir/visit.rs | 6 +- .../borrow_check/diagnostics/move_errors.rs | 7 +-- .../borrow_check/type_check/mod.rs | 57 ++++++++++--------- src/librustc_mir/util/pretty.rs | 6 +- src/librustc_mir_build/build/matches/mod.rs | 4 +- 6 files changed, 51 insertions(+), 41 deletions(-) diff --git a/src/librustc_middle/mir/mod.rs b/src/librustc_middle/mir/mod.rs index 0c1b99d871e2..158626605122 100644 --- a/src/librustc_middle/mir/mod.rs +++ b/src/librustc_middle/mir/mod.rs @@ -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>, /// 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) -> Self { UserTypeProjections { contents: projs.collect() } } diff --git a/src/librustc_middle/mir/visit.rs b/src/librustc_middle/mir/visit.rs index 2b6d44984bf5..2f3d89dc0298 100644 --- a/src/librustc_middle/mir/visit.rs +++ b/src/librustc_middle/mir/visit.rs @@ -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); } diff --git a/src/librustc_mir/borrow_check/diagnostics/move_errors.rs b/src/librustc_mir/borrow_check/diagnostics/move_errors.rs index ddaf78626f2c..67254811ec52 100644 --- a/src/librustc_mir/borrow_check/diagnostics/move_errors.rs +++ b/src/librustc_mir/borrow_check/diagnostics/move_errors.rs @@ -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) { diff --git a/src/librustc_mir/borrow_check/type_check/mod.rs b/src/librustc_mir/borrow_check/type_check/mod.rs index 7f554742777e..bd38ad04e7ea 100644 --- a/src/librustc_mir/borrow_check/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/type_check/mod.rs @@ -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, + ); + } } } } diff --git a/src/librustc_mir/util/pretty.rs b/src/librustc_mir/util/pretty.rs index 098601626db8..090cd4154373 100644 --- a/src/librustc_mir/util/pretty.rs +++ b/src/librustc_mir/util/pretty.rs @@ -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(";"); diff --git a/src/librustc_mir_build/build/matches/mod.rs b/src/librustc_mir_build/build/matches/mod.rs index 7812848e9266..f14de38a3f94 100644 --- a/src/librustc_mir_build/build/matches/mod.rs +++ b/src/librustc_mir_build/build/matches/mod.rs @@ -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,