From 9c3dc7e8721c03e1e033895f327ff71f8fd400b4 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Thu, 1 Feb 2018 00:00:38 +0200 Subject: [PATCH] rustc: prefer ParamEnvAnd and LayoutCx over tuples for LayoutOf. --- src/librustc/lint/context.rs | 2 +- src/librustc/ty/layout.rs | 171 ++++++++++++--------- src/librustc_const_eval/eval.rs | 3 +- src/librustc_lint/types.rs | 4 +- src/librustc_mir/interpret/eval_context.rs | 2 +- src/librustc_mir/transform/inline.rs | 3 +- src/librustc_trans/context.rs | 3 +- src/librustc_typeck/check/mod.rs | 3 +- 8 files changed, 107 insertions(+), 84 deletions(-) diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs index 5336c1944e8..929d5e7ec62 100644 --- a/src/librustc/lint/context.rs +++ b/src/librustc/lint/context.rs @@ -631,7 +631,7 @@ impl<'a, 'tcx> LayoutOf> for &'a LateContext<'a, 'tcx> { type TyLayout = Result, LayoutError<'tcx>>; fn layout_of(self, ty: Ty<'tcx>) -> Self::TyLayout { - (self.tcx, self.param_env.reveal_all()).layout_of(ty) + self.tcx.layout_of(self.param_env.and(ty)) } } diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index 69d07eafdca..63b91ff1101 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -895,7 +895,8 @@ fn layout_raw<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } tcx.layout_depth.set(depth+1); - let layout = LayoutDetails::compute_uncached(tcx, param_env, ty); + let cx = LayoutCx { tcx, param_env }; + let layout = cx.layout_raw_uncached(ty); tcx.layout_depth.set(depth); layout @@ -908,13 +909,18 @@ pub fn provide(providers: &mut ty::maps::Providers) { }; } -impl<'a, 'tcx> LayoutDetails { - fn compute_uncached(tcx: TyCtxt<'a, 'tcx, 'tcx>, - param_env: ty::ParamEnv<'tcx>, - ty: Ty<'tcx>) - -> Result<&'tcx Self, LayoutError<'tcx>> { - let cx = (tcx, param_env); - let dl = cx.data_layout(); +#[derive(Copy, Clone)] +pub struct LayoutCx<'tcx, C> { + pub tcx: C, + pub param_env: ty::ParamEnv<'tcx> +} + +impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> { + fn layout_raw_uncached(self, ty: Ty<'tcx>) + -> Result<&'tcx LayoutDetails, LayoutError<'tcx>> { + let tcx = self.tcx; + let param_env = self.param_env; + let dl = self.data_layout(); let scalar_unit = |value: Primitive| { let bits = value.size(dl).bits(); assert!(bits <= 128); @@ -924,7 +930,7 @@ impl<'a, 'tcx> LayoutDetails { } }; let scalar = |value: Primitive| { - tcx.intern_layout(LayoutDetails::scalar(cx, scalar_unit(value))) + tcx.intern_layout(LayoutDetails::scalar(self, scalar_unit(value))) }; let scalar_pair = |a: Scalar, b: Scalar| { let align = a.value.align(dl).max(b.value.align(dl)).max(dl.aggregate_align); @@ -1158,13 +1164,13 @@ impl<'a, 'tcx> LayoutDetails { Ok(match ty.sty { // Basic scalars. ty::TyBool => { - tcx.intern_layout(LayoutDetails::scalar(cx, Scalar { + tcx.intern_layout(LayoutDetails::scalar(self, Scalar { value: Int(I8, false), valid_range: 0..=1 })) } ty::TyChar => { - tcx.intern_layout(LayoutDetails::scalar(cx, Scalar { + tcx.intern_layout(LayoutDetails::scalar(self, Scalar { value: Int(I32, false), valid_range: 0..=0x10FFFF })) @@ -1180,7 +1186,7 @@ impl<'a, 'tcx> LayoutDetails { ty::TyFnPtr(_) => { let mut ptr = scalar_unit(Pointer); ptr.valid_range.start = 1; - tcx.intern_layout(LayoutDetails::scalar(cx, ptr)) + tcx.intern_layout(LayoutDetails::scalar(self, ptr)) } // The never type. @@ -1198,13 +1204,13 @@ impl<'a, 'tcx> LayoutDetails { let pointee = tcx.normalize_associated_type_in_env(&pointee, param_env); if pointee.is_sized(tcx, param_env, DUMMY_SP) { - return Ok(tcx.intern_layout(LayoutDetails::scalar(cx, data_ptr))); + return Ok(tcx.intern_layout(LayoutDetails::scalar(self, data_ptr))); } let unsized_part = tcx.struct_tail(pointee); let metadata = match unsized_part.sty { ty::TyForeign(..) => { - return Ok(tcx.intern_layout(LayoutDetails::scalar(cx, data_ptr))); + return Ok(tcx.intern_layout(LayoutDetails::scalar(self, data_ptr))); } ty::TySlice(_) | ty::TyStr => { scalar_unit(Int(dl.ptr_sized_integer(), false)) @@ -1230,7 +1236,7 @@ impl<'a, 'tcx> LayoutDetails { } } - let element = cx.layout_of(element)?; + let element = self.layout_of(element)?; let count = count.val.to_const_int().unwrap().to_u64().unwrap(); let size = element.size.checked_mul(count, dl) .ok_or(LayoutError::SizeOverflow(ty))?; @@ -1247,7 +1253,7 @@ impl<'a, 'tcx> LayoutDetails { }) } ty::TySlice(element) => { - let element = cx.layout_of(element)?; + let element = self.layout_of(element)?; tcx.intern_layout(LayoutDetails { variants: Variants::Single { index: 0 }, fields: FieldPlacement::Array { @@ -1289,14 +1295,14 @@ impl<'a, 'tcx> LayoutDetails { // Tuples, generators and closures. ty::TyGenerator(def_id, ref substs, _) => { let tys = substs.field_tys(def_id, tcx); - univariant(&tys.map(|ty| cx.layout_of(ty)).collect::, _>>()?, + univariant(&tys.map(|ty| self.layout_of(ty)).collect::, _>>()?, &ReprOptions::default(), StructKind::AlwaysSized)? } ty::TyClosure(def_id, ref substs) => { let tys = substs.upvar_tys(def_id, tcx); - univariant(&tys.map(|ty| cx.layout_of(ty)).collect::, _>>()?, + univariant(&tys.map(|ty| self.layout_of(ty)).collect::, _>>()?, &ReprOptions::default(), StructKind::AlwaysSized)? } @@ -1308,13 +1314,13 @@ impl<'a, 'tcx> LayoutDetails { StructKind::MaybeUnsized }; - univariant(&tys.iter().map(|ty| cx.layout_of(ty)).collect::, _>>()?, + univariant(&tys.iter().map(|ty| self.layout_of(ty)).collect::, _>>()?, &ReprOptions::default(), kind)? } // SIMD vector types. ty::TyAdt(def, ..) if def.repr.simd() => { - let element = cx.layout_of(ty.simd_type(tcx))?; + let element = self.layout_of(ty.simd_type(tcx))?; let count = ty.simd_size(tcx) as u64; assert!(count > 0); let scalar = match element.abi { @@ -1350,7 +1356,7 @@ impl<'a, 'tcx> LayoutDetails { // Cache the field layouts. let variants = def.variants.iter().map(|v| { v.fields.iter().map(|field| { - cx.layout_of(field.ty(tcx, substs)) + self.layout_of(field.ty(tcx, substs)) }).collect::, _>>() }).collect::, _>>()?; @@ -1430,7 +1436,7 @@ impl<'a, 'tcx> LayoutDetails { let mut st = univariant_uninterned(&variants[v], &def.repr, kind)?; st.variants = Variants::Single { index: v }; // Exclude 0 from the range of a newtype ABI NonZero. - if Some(def.did) == cx.tcx().lang_items().non_zero() { + if Some(def.did) == self.tcx.lang_items().non_zero() { match st.abi { Abi::Scalar(ref mut scalar) | Abi::ScalarPair(ref mut scalar, _) => { @@ -1482,7 +1488,7 @@ impl<'a, 'tcx> LayoutDetails { let count = (niche_variants.end - niche_variants.start + 1) as u128; for (field_index, field) in variants[i].iter().enumerate() { let (offset, niche, niche_start) = - match field.find_niche(cx, count)? { + match field.find_niche(self, count)? { Some(niche) => niche, None => continue }; @@ -1687,56 +1693,49 @@ impl<'a, 'tcx> LayoutDetails { /// This is invoked by the `layout_raw` query to record the final /// layout of each type. #[inline] - fn record_layout_for_printing(tcx: TyCtxt<'a, 'tcx, 'tcx>, - ty: Ty<'tcx>, - param_env: ty::ParamEnv<'tcx>, - layout: TyLayout<'tcx>) { + fn record_layout_for_printing(self, layout: TyLayout<'tcx>) { // If we are running with `-Zprint-type-sizes`, record layouts for // dumping later. Ignore layouts that are done with non-empty // environments or non-monomorphic layouts, as the user only wants // to see the stuff resulting from the final trans session. if - !tcx.sess.opts.debugging_opts.print_type_sizes || - ty.has_param_types() || - ty.has_self_ty() || - !param_env.caller_bounds.is_empty() + !self.tcx.sess.opts.debugging_opts.print_type_sizes || + layout.ty.has_param_types() || + layout.ty.has_self_ty() || + !self.param_env.caller_bounds.is_empty() { return; } - Self::record_layout_for_printing_outlined(tcx, ty, param_env, layout) + self.record_layout_for_printing_outlined(layout) } - fn record_layout_for_printing_outlined(tcx: TyCtxt<'a, 'tcx, 'tcx>, - ty: Ty<'tcx>, - param_env: ty::ParamEnv<'tcx>, - layout: TyLayout<'tcx>) { - let cx = (tcx, param_env); + fn record_layout_for_printing_outlined(self, layout: TyLayout<'tcx>) { // (delay format until we actually need it) let record = |kind, opt_discr_size, variants| { - let type_desc = format!("{:?}", ty); - tcx.sess.code_stats.borrow_mut().record_type_size(kind, - type_desc, - layout.align, - layout.size, - opt_discr_size, - variants); + let type_desc = format!("{:?}", layout.ty); + self.tcx.sess.code_stats.borrow_mut().record_type_size(kind, + type_desc, + layout.align, + layout.size, + opt_discr_size, + variants); }; - let adt_def = match ty.sty { + let adt_def = match layout.ty.sty { ty::TyAdt(ref adt_def, _) => { - debug!("print-type-size t: `{:?}` process adt", ty); + debug!("print-type-size t: `{:?}` process adt", layout.ty); adt_def } ty::TyClosure(..) => { - debug!("print-type-size t: `{:?}` record closure", ty); + debug!("print-type-size t: `{:?}` record closure", layout.ty); record(DataTypeKind::Closure, None, vec![]); return; } _ => { - debug!("print-type-size t: `{:?}` skip non-nominal", ty); + debug!("print-type-size t: `{:?}` skip non-nominal", layout.ty); return; } }; @@ -1748,7 +1747,7 @@ impl<'a, 'tcx> LayoutDetails { layout: TyLayout<'tcx>| { let mut min_size = Size::from_bytes(0); let field_info: Vec<_> = flds.iter().enumerate().map(|(i, &name)| { - match layout.field(cx, i) { + match layout.field(self, i) { Err(err) => { bug!("no layout found for field {}: `{:?}`", name, err); } @@ -1808,18 +1807,18 @@ impl<'a, 'tcx> LayoutDetails { Variants::NicheFilling { .. } | Variants::Tagged { .. } => { debug!("print-type-size `{:#?}` adt general variants def {}", - ty, adt_def.variants.len()); + layout.ty, adt_def.variants.len()); let variant_infos: Vec<_> = adt_def.variants.iter().enumerate().map(|(i, variant_def)| { let fields: Vec<_> = variant_def.fields.iter().map(|f| f.name).collect(); build_variant_info(Some(variant_def.name), &fields, - layout.for_variant(cx, i)) + layout.for_variant(self, i)) }) .collect(); record(adt_kind.into(), match layout.variants { - Variants::Tagged { ref discr, .. } => Some(discr.value.size(tcx)), + Variants::Tagged { ref discr, .. } => Some(discr.value.size(self)), _ => None }, variant_infos); } @@ -1855,7 +1854,7 @@ impl<'a, 'tcx> SizeSkeleton<'tcx> { assert!(!ty.has_infer_types()); // First try computing a static layout. - let err = match (tcx, param_env).layout_of(ty) { + let err = match tcx.layout_of(param_env.and(ty)) { Ok(layout) => { return Ok(SizeSkeleton::Known(layout.size)); } @@ -2001,15 +2000,15 @@ impl<'a, 'gcx, 'tcx> HasTyCtxt<'gcx> for TyCtxt<'a, 'gcx, 'tcx> { } } -impl<'a, 'gcx, 'tcx, T: Copy> HasDataLayout for (TyCtxt<'a, 'gcx, 'tcx>, T) { +impl<'tcx, T: HasDataLayout> HasDataLayout for LayoutCx<'tcx, T> { fn data_layout(&self) -> &TargetDataLayout { - self.0.data_layout() + self.tcx.data_layout() } } -impl<'a, 'gcx, 'tcx, T: Copy> HasTyCtxt<'gcx> for (TyCtxt<'a, 'gcx, 'tcx>, T) { +impl<'gcx, 'tcx, T: HasTyCtxt<'gcx>> HasTyCtxt<'gcx> for LayoutCx<'tcx, T> { fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'gcx> { - self.0.tcx() + self.tcx.tcx() } } @@ -2042,17 +2041,15 @@ pub trait LayoutOf { fn layout_of(self, ty: T) -> Self::TyLayout; } -impl<'a, 'tcx> LayoutOf> for (TyCtxt<'a, 'tcx, 'tcx>, ty::ParamEnv<'tcx>) { +impl<'a, 'tcx> LayoutOf> for LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> { type TyLayout = Result, LayoutError<'tcx>>; /// Computes the layout of a type. Note that this implicitly /// executes in "reveal all" mode. - #[inline] fn layout_of(self, ty: Ty<'tcx>) -> Self::TyLayout { - let (tcx, param_env) = self; - - let ty = tcx.normalize_associated_type_in_env(&ty, param_env.reveal_all()); - let details = tcx.layout_raw(param_env.reveal_all().and(ty))?; + let param_env = self.param_env.reveal_all(); + let ty = self.tcx.normalize_associated_type_in_env(&ty, param_env); + let details = self.tcx.layout_raw(param_env.and(ty))?; let layout = TyLayout { ty, details @@ -2064,24 +2061,21 @@ impl<'a, 'tcx> LayoutOf> for (TyCtxt<'a, 'tcx, 'tcx>, ty::ParamEnv<'tcx // completed, to avoid problems around recursive structures // and the like. (Admitedly, I wasn't able to reproduce a problem // here, but it seems like the right thing to do. -nmatsakis) - LayoutDetails::record_layout_for_printing(tcx, ty, param_env, layout); + self.record_layout_for_printing(layout); Ok(layout) } } -impl<'a, 'tcx> LayoutOf> for (ty::maps::TyCtxtAt<'a, 'tcx, 'tcx>, - ty::ParamEnv<'tcx>) { +impl<'a, 'tcx> LayoutOf> for LayoutCx<'tcx, ty::maps::TyCtxtAt<'a, 'tcx, 'tcx>> { type TyLayout = Result, LayoutError<'tcx>>; /// Computes the layout of a type. Note that this implicitly /// executes in "reveal all" mode. - #[inline] fn layout_of(self, ty: Ty<'tcx>) -> Self::TyLayout { - let (tcx_at, param_env) = self; - - let ty = tcx_at.tcx.normalize_associated_type_in_env(&ty, param_env.reveal_all()); - let details = tcx_at.layout_raw(param_env.reveal_all().and(ty))?; + let param_env = self.param_env.reveal_all(); + let ty = self.tcx.normalize_associated_type_in_env(&ty, param_env.reveal_all()); + let details = self.tcx.layout_raw(param_env.reveal_all().and(ty))?; let layout = TyLayout { ty, details @@ -2093,12 +2087,45 @@ impl<'a, 'tcx> LayoutOf> for (ty::maps::TyCtxtAt<'a, 'tcx, 'tcx>, // completed, to avoid problems around recursive structures // and the like. (Admitedly, I wasn't able to reproduce a problem // here, but it seems like the right thing to do. -nmatsakis) - LayoutDetails::record_layout_for_printing(tcx_at.tcx, ty, param_env, layout); + let cx = LayoutCx { + tcx: *self.tcx, + param_env: self.param_env + }; + cx.record_layout_for_printing(layout); Ok(layout) } } +// Helper (inherent) `layout_of` methods to avoid pushing `LayoutCx` to users. +impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> { + /// Computes the layout of a type. Note that this implicitly + /// executes in "reveal all" mode. + #[inline] + pub fn layout_of(self, param_env_and_ty: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) + -> Result, LayoutError<'tcx>> { + let cx = LayoutCx { + tcx: self, + param_env: param_env_and_ty.param_env + }; + cx.layout_of(param_env_and_ty.value) + } +} + +impl<'a, 'tcx> ty::maps::TyCtxtAt<'a, 'tcx, 'tcx> { + /// Computes the layout of a type. Note that this implicitly + /// executes in "reveal all" mode. + #[inline] + pub fn layout_of(self, param_env_and_ty: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) + -> Result, LayoutError<'tcx>> { + let cx = LayoutCx { + tcx: self, + param_env: param_env_and_ty.param_env + }; + cx.layout_of(param_env_and_ty.value) + } +} + impl<'a, 'tcx> TyLayout<'tcx> { pub fn for_variant(&self, cx: C, variant_index: usize) -> Self where C: LayoutOf> + HasTyCtxt<'tcx>, diff --git a/src/librustc_const_eval/eval.rs b/src/librustc_const_eval/eval.rs index 418bd4b5eff..1d2813e4f67 100644 --- a/src/librustc_const_eval/eval.rs +++ b/src/librustc_const_eval/eval.rs @@ -17,7 +17,6 @@ use rustc::hir::map::blocks::FnLikeNode; use rustc::hir::def::{Def, CtorKind}; use rustc::hir::def_id::DefId; use rustc::ty::{self, Ty, TyCtxt}; -use rustc::ty::layout::LayoutOf; use rustc::ty::util::IntTypeExt; use rustc::ty::subst::{Substs, Subst}; use rustc::util::common::ErrorReported; @@ -313,7 +312,7 @@ fn eval_const_expr_partial<'a, 'tcx>(cx: &ConstContext<'a, 'tcx>, if tcx.fn_sig(def_id).abi() == Abi::RustIntrinsic { let layout_of = |ty: Ty<'tcx>| { let ty = tcx.erase_regions(&ty); - (tcx.at(e.span), cx.param_env).layout_of(ty).map_err(|err| { + tcx.at(e.span).layout_of(cx.param_env.and(ty)).map_err(|err| { ConstEvalErr { span: e.span, kind: LayoutError(err) } }) }; diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs index e0999db6e3e..e7e4119b999 100644 --- a/src/librustc_lint/types.rs +++ b/src/librustc_lint/types.rs @@ -437,8 +437,8 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { // repr(transparent) types are allowed to have arbitrary ZSTs, not just // PhantomData -- skip checking all ZST fields if def.repr.transparent() { - let is_zst = (cx, cx.param_env(field.did)) - .layout_of(field_ty) + let is_zst = cx + .layout_of(cx.param_env(field.did).and(field_ty)) .map(|layout| layout.is_zst()) .unwrap_or(false); if is_zst { diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs index baec0fea50f..02fcb69fef5 100644 --- a/src/librustc_mir/interpret/eval_context.rs +++ b/src/librustc_mir/interpret/eval_context.rs @@ -172,7 +172,7 @@ impl<'a, 'tcx, M: Machine<'tcx>> LayoutOf> for &'a EvalContext<'a, 'tcx type TyLayout = EvalResult<'tcx, TyLayout<'tcx>>; fn layout_of(self, ty: Ty<'tcx>) -> Self::TyLayout { - (self.tcx, self.param_env).layout_of(ty) + self.tcx.layout_of(self.param_env.and(ty)) .map_err(|layout| EvalErrorKind::Layout(layout).into()) } } diff --git a/src/librustc_mir/transform/inline.rs b/src/librustc_mir/transform/inline.rs index 43ee75d1e2b..ceea97e3ed3 100644 --- a/src/librustc_mir/transform/inline.rs +++ b/src/librustc_mir/transform/inline.rs @@ -19,7 +19,6 @@ use rustc_data_structures::indexed_vec::{Idx, IndexVec}; use rustc::mir::*; use rustc::mir::visit::*; use rustc::ty::{self, Instance, Ty, TyCtxt, TypeFoldable}; -use rustc::ty::layout::LayoutOf; use rustc::ty::subst::{Subst,Substs}; use std::collections::VecDeque; @@ -655,7 +654,7 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> { fn type_size_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, param_env: ty::ParamEnv<'tcx>, ty: Ty<'tcx>) -> Option { - (tcx, param_env).layout_of(ty).ok().map(|layout| layout.size.bytes()) + tcx.layout_of(param_env.and(ty)).ok().map(|layout| layout.size.bytes()) } fn subst_and_normalize<'a, 'tcx: 'a>( diff --git a/src/librustc_trans/context.rs b/src/librustc_trans/context.rs index 06b8d9ff7b3..a285e5f263a 100644 --- a/src/librustc_trans/context.rs +++ b/src/librustc_trans/context.rs @@ -464,8 +464,7 @@ impl<'a, 'tcx> LayoutOf> for &'a CodegenCx<'a, 'tcx> { type TyLayout = TyLayout<'tcx>; fn layout_of(self, ty: Ty<'tcx>) -> Self::TyLayout { - (self.tcx, ty::ParamEnv::empty(traits::Reveal::All)) - .layout_of(ty) + self.tcx.layout_of(ty::ParamEnv::empty(traits::Reveal::All).and(ty)) .unwrap_or_else(|e| match e { LayoutError::SizeOverflow(_) => self.sess().fatal(&e.to_string()), _ => bug!("failed to get layout for `{}`: {}", ty, e) diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 483dd345286..e4023b4d959 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -100,7 +100,6 @@ use rustc::ty::adjustment::{Adjust, Adjustment, AutoBorrow}; use rustc::ty::fold::TypeFoldable; use rustc::ty::maps::Providers; use rustc::ty::util::{Representability, IntTypeExt}; -use rustc::ty::layout::LayoutOf; use errors::{DiagnosticBuilder, DiagnosticId}; use require_c_abi_if_variadic; @@ -1551,7 +1550,7 @@ fn check_transparent<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, sp: Span, def_id: De let field_infos: Vec<_> = adt.non_enum_variant().fields.iter().map(|field| { let ty = field.ty(tcx, Substs::identity_for_item(tcx, field.did)); let param_env = tcx.param_env(field.did); - let layout = (tcx, param_env).layout_of(ty); + let layout = tcx.layout_of(param_env.and(ty)); // We are currently checking the type this field came from, so it must be local let span = tcx.hir.span_if_local(field.did).unwrap(); let zst = layout.map(|layout| layout.is_zst()).unwrap_or(false);