rustc: remove Ty::layout and move everything to layout_of.

This commit is contained in:
Eduard-Mihai Burtescu 2017-09-13 02:19:11 +03:00
parent 8864668d53
commit 8c4d5af52b
19 changed files with 201 additions and 250 deletions

View file

@ -34,7 +34,8 @@ use middle::privacy::AccessLevels;
use rustc_serialize::{Decoder, Decodable, Encoder, Encodable};
use session::{config, early_error, Session};
use traits::Reveal;
use ty::{self, TyCtxt};
use ty::{self, TyCtxt, Ty};
use ty::layout::{FullLayout, LayoutError, LayoutOf};
use util::nodemap::FxHashMap;
use std::default::Default as StdDefault;
@ -626,6 +627,14 @@ impl<'a, 'tcx> LateContext<'a, 'tcx> {
}
}
impl<'a, 'tcx> LayoutOf<Ty<'tcx>> for &'a LateContext<'a, 'tcx> {
type FullLayout = Result<FullLayout<'tcx>, LayoutError<'tcx>>;
fn layout_of(self, ty: Ty<'tcx>) -> Self::FullLayout {
(self.tcx, self.param_env.reveal_all()).layout_of(ty)
}
}
impl<'a, 'tcx> hir_visit::Visitor<'tcx> for LateContext<'a, 'tcx> {
/// Because lints are scoped lexically, we want to walk nested
/// items in the context of the outer item, so enable

View file

@ -653,7 +653,7 @@ enum StructKind {
impl<'a, 'tcx> Struct {
fn new(dl: &TargetDataLayout,
fields: &Vec<&'a Layout>,
fields: &[FullLayout],
repr: &ReprOptions,
kind: StructKind,
scapegoat: Ty<'tcx>)
@ -793,19 +793,6 @@ impl<'a, 'tcx> Struct {
self.min_size.abi_align(self.align)
}
/// Determine whether a structure would be zero-sized, given its fields.
fn would_be_zero_sized<I>(dl: &TargetDataLayout, fields: I)
-> Result<bool, LayoutError<'tcx>>
where I: Iterator<Item=Result<&'a Layout, LayoutError<'tcx>>> {
for field in fields {
let field = field?;
if field.is_unsized() || field.size(dl).bytes() > 0 {
return Ok(false);
}
}
Ok(true)
}
/// Get indices of the tys that made this struct by increasing offset.
#[inline]
pub fn field_index_by_increasing_offset<'b>(&'b self) -> impl iter::Iterator<Item=usize>+'b {
@ -837,10 +824,10 @@ impl<'a, 'tcx> Struct {
// FIXME(eddyb) track value ranges and traverse already optimized enums.
fn non_zero_field_in_type(tcx: TyCtxt<'a, 'tcx, 'tcx>,
param_env: ty::ParamEnv<'tcx>,
ty: Ty<'tcx>)
layout: FullLayout<'tcx>)
-> Result<Option<(Size, Primitive)>, LayoutError<'tcx>> {
let layout = ty.layout(tcx, param_env)?;
match (layout, &ty.sty) {
let cx = (tcx, param_env);
match (layout.layout, &layout.ty.sty) {
(&Scalar { non_zero: true, value, .. }, _) => {
Ok(Some((Size::from_bytes(0), value)))
}
@ -849,49 +836,33 @@ impl<'a, 'tcx> Struct {
}
(&FatPointer { non_zero: true, .. }, _) => {
Ok(Some((layout.field_offset(tcx, FAT_PTR_ADDR, None),
Pointer)))
Ok(Some((layout.field_offset(tcx, FAT_PTR_ADDR), Pointer)))
}
// Is this the NonZero lang item wrapping a pointer or integer type?
(&Univariant { non_zero: true, .. }, &ty::TyAdt(def, substs)) => {
let fields = &def.struct_variant().fields;
assert_eq!(fields.len(), 1);
let field = fields[0].ty(tcx, substs).layout(tcx, param_env)?;
(_, &ty::TyAdt(def, _)) if Some(def.did) == tcx.lang_items().non_zero() => {
let field = layout.field(cx, 0)?;
match *field {
// FIXME(eddyb) also allow floating-point types here.
Scalar { value: value @ Int(_), non_zero: false } |
Scalar { value: value @ Pointer, non_zero: false } => {
Ok(Some((layout.field_offset(tcx, 0, None), value)))
Ok(Some((layout.field_offset(tcx, 0), value)))
}
FatPointer { non_zero: false, .. } => {
Ok(Some((layout.field_offset(tcx, 0, None) +
field.field_offset(tcx, FAT_PTR_ADDR, None),
Ok(Some((layout.field_offset(tcx, 0) +
field.field_offset(tcx, FAT_PTR_ADDR),
Pointer)))
}
_ => Ok(None)
}
}
// Perhaps one of the fields of this struct is non-zero
// let's recurse and find out
(&Univariant { ref variant, .. }, &ty::TyAdt(def, substs)) if def.is_struct() => {
// Perhaps one of the fields is non-zero, let's recurse and find out.
(&Univariant(ref variant), _) => {
variant.non_zero_field(
tcx,
param_env,
def.struct_variant().fields.iter().map(|field| {
field.ty(tcx, substs)
}))
}
// Perhaps one of the upvars of this closure is non-zero
(&Univariant { ref variant, .. }, &ty::TyClosure(def, substs)) => {
let upvar_tys = substs.upvar_tys(def, tcx);
variant.non_zero_field(tcx, param_env, upvar_tys)
}
// Can we use one of the fields in this tuple?
(&Univariant { ref variant, .. }, &ty::TyTuple(tys, _)) => {
variant.non_zero_field(tcx, param_env, tys.iter().cloned())
(0..layout.field_count()).map(|i| layout.field(cx, i)))
}
// Is this a fixed-size array of something non-zero
@ -900,22 +871,18 @@ impl<'a, 'tcx> Struct {
if count.has_projections() {
count = tcx.normalize_associated_type_in_env(&count, param_env);
if count.has_projections() {
return Err(LayoutError::Unknown(ty));
return Err(LayoutError::Unknown(layout.ty));
}
}
if count.val.to_const_int().unwrap().to_u64().unwrap() != 0 {
Struct::non_zero_field_in_type(tcx, param_env, ety)
Struct::non_zero_field_in_type(tcx, param_env, cx.layout_of(ety)?)
} else {
Ok(None)
}
}
(_, &ty::TyProjection(_)) | (_, &ty::TyAnon(..)) => {
let normalized = tcx.normalize_associated_type_in_env(&ty, param_env);
if ty == normalized {
return Ok(None);
}
return Struct::non_zero_field_in_type(tcx, param_env, normalized);
bug!("Struct::non_zero_field_in_type: {:?} not normalized", layout);
}
// Anything else is not a non-zero type.
@ -930,9 +897,9 @@ impl<'a, 'tcx> Struct {
param_env: ty::ParamEnv<'tcx>,
fields: I)
-> Result<Option<(Size, Primitive)>, LayoutError<'tcx>>
where I: Iterator<Item=Ty<'tcx>> {
for (ty, &field_offset) in fields.zip(&self.offsets) {
let r = Struct::non_zero_field_in_type(tcx, param_env, ty)?;
where I: Iterator<Item = Result<FullLayout<'tcx>, LayoutError<'tcx>>> {
for (field, &field_offset) in fields.zip(&self.offsets) {
let r = Struct::non_zero_field_in_type(tcx, param_env, field?)?;
if let Some((offset, primitive)) = r {
return Ok(Some((field_offset + offset, primitive)));
}
@ -981,7 +948,7 @@ impl<'a, 'tcx> Union {
}
}
/// Extend the Struct with more fields.
/// Extend the Union with more fields.
fn extend<I>(&mut self, dl: &TargetDataLayout,
fields: I,
scapegoat: Ty<'tcx>)
@ -1077,17 +1044,10 @@ pub enum Layout {
},
/// Single-case enums, and structs/tuples.
Univariant {
variant: Struct,
/// If true, the structure is NonZero.
// FIXME(eddyb) use a newtype Layout kind for this.
non_zero: bool
},
Univariant(Struct),
/// Untagged unions.
UntaggedUnion {
variants: Union,
},
UntaggedUnion(Union),
/// General-case enums: for each case there is a struct, and they all have
/// all space reserved for the discriminant, and their first field starts
@ -1145,31 +1105,59 @@ impl<'tcx> fmt::Display for LayoutError<'tcx> {
}
}
fn layout_raw<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>)
-> Result<&'tcx Layout, LayoutError<'tcx>>
{
let (param_env, ty) = query.into_parts();
let rec_limit = tcx.sess.recursion_limit.get();
let depth = tcx.layout_depth.get();
if depth > rec_limit {
tcx.sess.fatal(
&format!("overflow representing the type `{}`", ty));
}
tcx.layout_depth.set(depth+1);
let layout = Layout::compute_uncached(tcx, param_env, ty);
tcx.layout_depth.set(depth);
layout
}
pub fn provide(providers: &mut ty::maps::Providers) {
*providers = ty::maps::Providers {
layout_raw,
..*providers
};
}
impl<'a, 'tcx> Layout {
pub fn compute_uncached(tcx: TyCtxt<'a, 'tcx, 'tcx>,
param_env: ty::ParamEnv<'tcx>,
ty: Ty<'tcx>)
-> Result<&'tcx Layout, LayoutError<'tcx>> {
fn compute_uncached(tcx: TyCtxt<'a, 'tcx, 'tcx>,
param_env: ty::ParamEnv<'tcx>,
ty: Ty<'tcx>)
-> Result<&'tcx Layout, LayoutError<'tcx>> {
let success = |layout| Ok(tcx.intern_layout(layout));
let dl = &tcx.data_layout;
let cx = (tcx, param_env);
let dl = cx.data_layout();
assert!(!ty.has_infer_types());
let ptr_layout = |pointee: Ty<'tcx>| {
let non_zero = !ty.is_unsafe_ptr();
let pointee = tcx.normalize_associated_type_in_env(&pointee, param_env);
if pointee.is_sized(tcx, param_env, DUMMY_SP) {
Ok(Scalar { value: Pointer, non_zero: non_zero })
Ok(Scalar { value: Pointer, non_zero })
} else {
let unsized_part = tcx.struct_tail(pointee);
match unsized_part.sty {
ty::TySlice(_) | ty::TyStr => Ok(FatPointer {
metadata: Int(dl.ptr_sized_integer()),
non_zero: non_zero
}),
ty::TyDynamic(..) => Ok(FatPointer { metadata: Pointer, non_zero: non_zero }),
ty::TyForeign(..) => Ok(Scalar { value: Pointer, non_zero: non_zero }),
_ => Err(LayoutError::Unknown(unsized_part)),
}
let metadata = match unsized_part.sty {
ty::TyForeign(..) => return Ok(Scalar { value: Pointer, non_zero }),
ty::TySlice(_) | ty::TyStr => {
Int(dl.ptr_sized_integer())
}
ty::TyDynamic(..) => Pointer,
_ => return Err(LayoutError::Unknown(unsized_part))
};
Ok(FatPointer { metadata, non_zero })
}
};
@ -1194,11 +1182,10 @@ impl<'a, 'tcx> Layout {
ty::TyFnPtr(_) => Scalar { value: Pointer, non_zero: true },
// The never type.
ty::TyNever => Univariant {
variant: Struct::new(dl, &vec![], &ReprOptions::default(),
StructKind::AlwaysSizedUnivariant, ty)?,
non_zero: false
},
ty::TyNever => {
Univariant(Struct::new(dl, &[], &ReprOptions::default(),
StructKind::AlwaysSizedUnivariant, ty)?)
}
// Potentially-fat pointers.
ty::TyRef(_, ty::TypeAndMut { ty: pointee, .. }) |
@ -1218,7 +1205,7 @@ impl<'a, 'tcx> Layout {
}
}
let element = element.layout(tcx, param_env)?;
let element = cx.layout_of(element)?;
let element_size = element.size(dl);
let count = count.val.to_const_int().unwrap().to_u64().unwrap();
if element_size.checked_mul(count, dl).is_none() {
@ -1233,7 +1220,7 @@ impl<'a, 'tcx> Layout {
}
}
ty::TySlice(element) => {
let element = element.layout(tcx, param_env)?;
let element = cx.layout_of(element)?;
Array {
sized: false,
align: element.align(dl),
@ -1254,38 +1241,33 @@ impl<'a, 'tcx> Layout {
// Odd unit types.
ty::TyFnDef(..) => {
Univariant {
variant: Struct::new(dl, &vec![],
&ReprOptions::default(), StructKind::AlwaysSizedUnivariant, ty)?,
non_zero: false
}
Univariant(Struct::new(dl, &[], &ReprOptions::default(),
StructKind::AlwaysSizedUnivariant, ty)?)
}
ty::TyDynamic(..) | ty::TyForeign(..) => {
let mut unit = Struct::new(dl, &vec![], &ReprOptions::default(),
let mut unit = Struct::new(dl, &[], &ReprOptions::default(),
StructKind::AlwaysSizedUnivariant, ty)?;
unit.sized = false;
Univariant { variant: unit, non_zero: false }
Univariant(unit)
}
// Tuples, generators and closures.
ty::TyGenerator(def_id, ref substs, _) => {
let tys = substs.field_tys(def_id, tcx);
let st = Struct::new(dl,
&tys.map(|ty| ty.layout(tcx, param_env))
Univariant(Struct::new(dl,
&tys.map(|ty| cx.layout_of(ty))
.collect::<Result<Vec<_>, _>>()?,
&ReprOptions::default(),
StructKind::AlwaysSizedUnivariant, ty)?;
Univariant { variant: st, non_zero: false }
StructKind::AlwaysSizedUnivariant, ty)?)
}
ty::TyClosure(def_id, ref substs) => {
let tys = substs.upvar_tys(def_id, tcx);
let st = Struct::new(dl,
&tys.map(|ty| ty.layout(tcx, param_env))
Univariant(Struct::new(dl,
&tys.map(|ty| cx.layout_of(ty))
.collect::<Result<Vec<_>, _>>()?,
&ReprOptions::default(),
StructKind::AlwaysSizedUnivariant, ty)?;
Univariant { variant: st, non_zero: false }
StructKind::AlwaysSizedUnivariant, ty)?)
}
ty::TyTuple(tys, _) => {
@ -1295,17 +1277,16 @@ impl<'a, 'tcx> Layout {
StructKind::MaybeUnsizedUnivariant
};
let st = Struct::new(dl,
&tys.iter().map(|ty| ty.layout(tcx, param_env))
Univariant(Struct::new(dl,
&tys.iter().map(|ty| cx.layout_of(ty))
.collect::<Result<Vec<_>, _>>()?,
&ReprOptions::default(), kind, ty)?;
Univariant { variant: st, non_zero: false }
&ReprOptions::default(), kind, ty)?)
}
// SIMD vector types.
ty::TyAdt(def, ..) if def.repr.simd() => {
let element = ty.simd_type(tcx);
match *element.layout(tcx, param_env)? {
match *cx.layout_of(element)? {
Scalar { value, .. } => {
return success(Vector {
element: value,
@ -1326,11 +1307,8 @@ impl<'a, 'tcx> Layout {
// Uninhabitable; represent as unit
// (Typechecking will reject discriminant-sizing attrs.)
return success(Univariant {
variant: Struct::new(dl, &vec![],
&def.repr, StructKind::AlwaysSizedUnivariant, ty)?,
non_zero: false
});
return success(Univariant(Struct::new(dl, &[],
&def.repr, StructKind::AlwaysSizedUnivariant, ty)?));
}
if def.is_enum() && def.variants.iter().all(|v| v.fields.is_empty()) {
@ -1376,17 +1354,14 @@ impl<'a, 'tcx> Layout {
};
let fields = def.variants[0].fields.iter().map(|field| {
field.ty(tcx, substs).layout(tcx, param_env)
cx.layout_of(field.ty(tcx, substs))
}).collect::<Result<Vec<_>, _>>()?;
let layout = if def.is_union() {
let mut un = Union::new(dl, &def.repr);
un.extend(dl, fields.iter().map(|&f| Ok(f)), ty)?;
UntaggedUnion { variants: un }
un.extend(dl, fields.iter().map(|&f| Ok(f.layout)), ty)?;
UntaggedUnion(un)
} else {
let st = Struct::new(dl, &fields, &def.repr,
kind, ty)?;
let non_zero = Some(def.did) == tcx.lang_items().non_zero();
Univariant { variant: st, non_zero: non_zero }
Univariant(Struct::new(dl, &fields, &def.repr, kind, ty)?)
};
return success(layout);
}
@ -1403,28 +1378,41 @@ impl<'a, 'tcx> Layout {
// Cache the substituted and normalized variant field types.
let variants = def.variants.iter().map(|v| {
v.fields.iter().map(|field| field.ty(tcx, substs)).collect::<Vec<_>>()
}).collect::<Vec<_>>();
v.fields.iter().map(|field| {
cx.layout_of(field.ty(tcx, substs))
}).collect::<Result<Vec<_>, _>>()
}).collect::<Result<Vec<_>, _>>()?;
if variants.len() == 2 && !def.repr.inhibit_enum_layout_opt() {
// Nullable pointer optimization
let st0 = Struct::new(dl, &variants[0],
&def.repr, StructKind::AlwaysSizedUnivariant, ty)?;
let st1 = Struct::new(dl, &variants[1],
&def.repr, StructKind::AlwaysSizedUnivariant, ty)?;
let mut choice = None;
for discr in 0..2 {
let other_fields = variants[1 - discr].iter().map(|ty| {
ty.layout(tcx, param_env)
});
if !Struct::would_be_zero_sized(dl, other_fields)? {
let (st, other) = if discr == 0 {
(&st0, &st1)
} else {
(&st1, &st0)
};
if other.stride().bytes() > 0 {
continue;
}
let st = Struct::new(dl,
&variants[discr].iter().map(|ty| ty.layout(tcx, param_env))
.collect::<Result<Vec<_>, _>>()?,
&def.repr, StructKind::AlwaysSizedUnivariant, ty)?;
let field = st.non_zero_field(tcx, param_env,
variants[discr].iter().cloned())?;
let (offset, primitive) = if let Some(f) = field { f }
else { continue };
variants[discr].iter().map(|&f| Ok(f)))?;
if let Some((offset, primitive)) = field {
choice = Some((discr, offset, primitive));
break;
}
}
if let Some((discr, offset, primitive)) = choice {
// HACK(eddyb) work around not being able to move
// out of arrays with just the indexing operator.
let st = if discr == 0 { st0 } else { st1 };
// FIXME(eddyb) should take advantage of a newtype.
if offset.bytes() == 0 && primitive.size(dl) == st.stride() &&
@ -1457,11 +1445,7 @@ impl<'a, 'tcx> Layout {
// Create the set of structs that represent each variant.
let mut variants = variants.into_iter().map(|fields| {
let fields = fields.into_iter().map(|field| {
field.layout(tcx, param_env)
}).collect::<Result<Vec<_>, _>>()?;
let st = Struct::new(dl,
&fields,
let st = Struct::new(dl, &fields,
&def.repr, StructKind::EnumVariant(min_ity), ty)?;
// Find the first field we can't move later
// to make room for a larger discriminant.
@ -1552,7 +1536,7 @@ impl<'a, 'tcx> Layout {
if ty == normalized {
return Err(LayoutError::Unknown(ty));
}
return normalized.layout(tcx, param_env);
return Ok(cx.layout_of(normalized)?.layout);
}
ty::TyParam(_) => {
return Err(LayoutError::Unknown(ty));
@ -1574,7 +1558,7 @@ impl<'a, 'tcx> Layout {
StructWrappedNullablePointer {..} => false,
Array { sized, .. } |
Univariant { variant: Struct { sized, .. }, .. } => !sized
Univariant(Struct { sized, .. }) => !sized
}
}
@ -1612,9 +1596,9 @@ impl<'a, 'tcx> Layout {
CEnum { discr, .. } => Int(discr).size(dl),
General { size, .. } => size,
UntaggedUnion { ref variants } => variants.stride(),
UntaggedUnion(ref un) => un.stride(),
Univariant { ref variant, .. } |
Univariant(ref variant) |
StructWrappedNullablePointer { nonnull: ref variant, .. } => {
variant.stride()
}
@ -1646,9 +1630,9 @@ impl<'a, 'tcx> Layout {
CEnum { discr, .. } => Int(discr).align(dl),
Array { align, .. } | General { align, .. } => align,
UntaggedUnion { ref variants } => variants.align,
UntaggedUnion(ref un) => un.align,
Univariant { ref variant, .. } |
Univariant(ref variant) |
StructWrappedNullablePointer { nonnull: ref variant, .. } => {
variant.align
}
@ -1663,7 +1647,7 @@ impl<'a, 'tcx> Layout {
pub fn primitive_align<C: HasDataLayout>(&self, cx: C) -> Align {
match *self {
Array { primitive_align, .. } | General { primitive_align, .. } => primitive_align,
Univariant { ref variant, .. } |
Univariant(ref variant) |
StructWrappedNullablePointer { nonnull: ref variant, .. } => {
variant.primitive_align
},
@ -1682,7 +1666,7 @@ impl<'a, 'tcx> Layout {
match *self {
Scalar { .. } |
CEnum { .. } |
UntaggedUnion { .. } |
UntaggedUnion(_) |
RawNullablePointer { .. } => {
Size::from_bytes(0)
}
@ -1710,7 +1694,7 @@ impl<'a, 'tcx> Layout {
}
}
Univariant { ref variant, .. } => variant.offsets[i],
Univariant(ref variant) => variant.offsets[i],
General { ref variants, .. } => {
let v = variant_index.expect("variant index required");
@ -1730,10 +1714,10 @@ impl<'a, 'tcx> Layout {
/// This is invoked by the `layout_raw` query to record the final
/// layout of each type.
#[inline]
pub fn record_layout_for_printing(tcx: TyCtxt<'a, 'tcx, 'tcx>,
ty: Ty<'tcx>,
param_env: ty::ParamEnv<'tcx>,
layout: &Layout) {
fn record_layout_for_printing(tcx: TyCtxt<'a, 'tcx, 'tcx>,
ty: Ty<'tcx>,
param_env: ty::ParamEnv<'tcx>,
layout: &Layout) {
// 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
@ -1788,8 +1772,7 @@ impl<'a, 'tcx> Layout {
let adt_kind = adt_def.adt_kind();
let build_field_info = |(field_name, field_ty): (ast::Name, Ty<'tcx>), offset: &Size| {
let layout = field_ty.layout(tcx, param_env);
match layout {
match (tcx, param_env).layout_of(field_ty) {
Err(_) => bug!("no layout found for field {} type: `{:?}`", field_name, field_ty),
Ok(field_layout) => {
session::FieldInfo {
@ -1859,7 +1842,7 @@ impl<'a, 'tcx> Layout {
record(adt_kind.into(), None,
vec![build_primitive_info(variant_def.name, &discr)]);
}
Layout::Univariant { variant: ref variant_layout, non_zero: _ } => {
Layout::Univariant(ref variant_layout) => {
let variant_names = || {
adt_def.variants.iter().map(|v|format!("{}", v.name)).collect::<Vec<_>>()
};
@ -1905,9 +1888,8 @@ impl<'a, 'tcx> Layout {
record(adt_kind.into(), Some(discr.size()), variant_infos);
}
Layout::UntaggedUnion { ref variants } => {
debug!("print-type-size t: `{:?}` adt union variants {:?}",
ty, variants);
Layout::UntaggedUnion(ref un) => {
debug!("print-type-size t: `{:?}` adt union {:?}", ty, un);
// layout does not currently store info about each
// variant...
record(adt_kind.into(), None, Vec::new());
@ -1966,7 +1948,7 @@ impl<'a, 'tcx> SizeSkeleton<'tcx> {
assert!(!ty.has_infer_types());
// First try computing a static layout.
let err = match ty.layout(tcx, param_env) {
let err = match (tcx, param_env).layout_of(ty) {
Ok(layout) => {
return Ok(SizeSkeleton::Known(layout.size(tcx)));
}
@ -2141,15 +2123,29 @@ pub trait LayoutOf<T> {
impl<'a, 'tcx> LayoutOf<Ty<'tcx>> for (TyCtxt<'a, 'tcx, 'tcx>, ty::ParamEnv<'tcx>) {
type FullLayout = Result<FullLayout<'tcx>, 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::FullLayout {
let (tcx, param_env) = self;
let ty = tcx.normalize_associated_type_in_env(&ty, param_env);
let ty = tcx.normalize_associated_type_in_env(&ty, param_env.reveal_all());
let layout = tcx.layout_raw(param_env.reveal_all().and(ty));
// NB: This recording is normally disabled; when enabled, it
// can however trigger recursive invocations of `layout()`.
// Therefore, we execute it *after* the main query has
// 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)
if let Ok(l) = layout {
Layout::record_layout_for_printing(tcx, ty, param_env, l);
}
Ok(FullLayout {
ty,
variant_index: None,
layout: ty.layout(tcx, param_env)?,
layout: layout?,
})
}
}
@ -2204,7 +2200,7 @@ impl<'a, 'tcx> FullLayout<'tcx> {
// Handled above (the TyAdt case).
CEnum { .. } |
General { .. } |
UntaggedUnion { .. } |
UntaggedUnion(_) |
RawNullablePointer { .. } |
StructWrappedNullablePointer { .. } => bug!(),
@ -2217,7 +2213,7 @@ impl<'a, 'tcx> FullLayout<'tcx> {
usize_count
}
Univariant { ref variant, .. } => variant.offsets.len(),
Univariant(ref variant) => variant.offsets.len(),
}
}
@ -2356,12 +2352,11 @@ impl<'gcx> HashStable<StableHashingContext<'gcx>> for Layout
min.hash_stable(hcx, hasher);
max.hash_stable(hcx, hasher);
}
Univariant { ref variant, non_zero } => {
Univariant(ref variant) => {
variant.hash_stable(hcx, hasher);
non_zero.hash_stable(hcx, hasher);
}
UntaggedUnion { ref variants } => {
variants.hash_stable(hcx, hasher);
UntaggedUnion(ref un) => {
un.hash_stable(hcx, hasher);
}
General { discr, ref variants, size, align, primitive_align } => {
discr.hash_stable(hcx, hasher);

View file

@ -2617,9 +2617,10 @@ fn original_crate_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
}
pub fn provide(providers: &mut ty::maps::Providers) {
util::provide(providers);
context::provide(providers);
erase_regions::provide(providers);
layout::provide(providers);
util::provide(providers);
*providers = ty::maps::Providers {
associated_item,
associated_item_def_ids,

View file

@ -19,7 +19,6 @@ use middle::const_val::ConstVal;
use traits::{self, Reveal};
use ty::{self, Ty, TyCtxt, TypeFoldable};
use ty::fold::TypeVisitor;
use ty::layout::{Layout, LayoutError};
use ty::subst::{Subst, Kind};
use ty::TypeVariants::*;
use util::common::ErrorReported;
@ -852,30 +851,6 @@ impl<'a, 'tcx> ty::TyS<'tcx> {
tcx.needs_drop_raw(param_env.and(self))
}
/// Computes the layout of a type. Note that this implicitly
/// executes in "reveal all" mode.
#[inline]
pub fn layout<'lcx>(&'tcx self,
tcx: TyCtxt<'a, 'tcx, 'tcx>,
param_env: ty::ParamEnv<'tcx>)
-> Result<&'tcx Layout, LayoutError<'tcx>> {
let ty = tcx.erase_regions(&self);
let layout = tcx.layout_raw(param_env.reveal_all().and(ty));
// NB: This recording is normally disabled; when enabled, it
// can however trigger recursive invocations of `layout()`.
// Therefore, we execute it *after* the main query has
// 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)
if let Ok(l) = layout {
Layout::record_layout_for_printing(tcx, ty, param_env, l);
}
layout
}
/// Check whether a type is representable. This means it cannot contain unboxed
/// structural recursion. This check is needed for structs and enums.
pub fn is_representable(&'tcx self,
@ -1184,26 +1159,6 @@ fn needs_drop_raw<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
}
}
fn layout_raw<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>)
-> Result<&'tcx Layout, LayoutError<'tcx>>
{
let (param_env, ty) = query.into_parts();
let rec_limit = tcx.sess.recursion_limit.get();
let depth = tcx.layout_depth.get();
if depth > rec_limit {
tcx.sess.fatal(
&format!("overflow representing the type `{}`", ty));
}
tcx.layout_depth.set(depth+1);
let layout = Layout::compute_uncached(tcx, param_env, ty);
tcx.layout_depth.set(depth);
layout
}
pub enum ExplicitSelf<'tcx> {
ByValue,
ByReference(ty::Region<'tcx>, hir::Mutability),
@ -1262,7 +1217,6 @@ pub fn provide(providers: &mut ty::maps::Providers) {
is_sized_raw,
is_freeze_raw,
needs_drop_raw,
layout_raw,
..*providers
};
}

View file

@ -13,7 +13,7 @@
use rustc::hir::def_id::DefId;
use rustc::ty::subst::Substs;
use rustc::ty::{self, AdtKind, Ty, TyCtxt};
use rustc::ty::layout::{Layout, Primitive};
use rustc::ty::layout::{Layout, LayoutOf, Primitive};
use middle::const_val::ConstVal;
use rustc_const_eval::ConstContext;
use util::nodemap::FxHashSet;
@ -748,9 +748,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for VariantSizeDifferences {
// sizes only make sense for non-generic types
let item_def_id = cx.tcx.hir.local_def_id(it.id);
let t = cx.tcx.type_of(item_def_id);
let param_env = cx.param_env.reveal_all();
let ty = cx.tcx.erase_regions(&t);
let layout = ty.layout(cx.tcx, param_env).unwrap_or_else(|e| {
let layout = cx.layout_of(ty).unwrap_or_else(|e| {
bug!("failed to get layout for `{}`: {}", t, e)
});

View file

@ -19,6 +19,7 @@ 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;
@ -625,9 +626,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<u64> {
ty.layout(tcx, param_env).ok().map(|layout| {
layout.size(&tcx.data_layout).bytes()
})
(tcx, param_env).layout_of(ty).ok().map(|layout| layout.size(tcx).bytes())
}
fn subst_and_normalize<'a, 'tcx: 'a>(

View file

@ -330,7 +330,7 @@ impl<'tcx> LayoutExt<'tcx> for FullLayout<'tcx> {
}
}
Layout::Univariant { ref variant, .. } => {
Layout::Univariant(ref variant) => {
let mut unaligned_offset = Size::from_bytes(0);
let mut result = None;

View file

@ -74,7 +74,7 @@ pub fn finish_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
layout::Univariant { ..}
| layout::StructWrappedNullablePointer { .. } => {
let (variant_layout, variant) = match *l {
layout::Univariant { ref variant, .. } => {
layout::Univariant(ref variant) => {
let is_enum = if let ty::TyAdt(def, _) = t.sty {
def.is_enum()
} else {
@ -123,7 +123,7 @@ fn generic_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
}
}
}
layout::Univariant { ref variant, .. } => {
layout::Univariant(ref variant) => {
match name {
None => {
Type::struct_(cx, &struct_llfields(cx, l, &variant),
@ -134,16 +134,16 @@ fn generic_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
}
}
}
layout::UntaggedUnion { ref variants, .. }=> {
layout::UntaggedUnion(ref un) => {
// Use alignment-sized ints to fill all the union storage.
let fill = union_fill(cx, variants.stride(), variants.align);
let fill = union_fill(cx, un.stride(), un.align);
match name {
None => {
Type::struct_(cx, &[fill], variants.packed)
Type::struct_(cx, &[fill], un.packed)
}
Some(name) => {
let mut llty = Type::named_struct(cx, name);
llty.set_struct_body(&[fill], variants.packed);
llty.set_struct_body(&[fill], un.packed);
llty
}
}

View file

@ -101,7 +101,7 @@ fn classify_arg<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, arg: &ArgType<'tcx>)
}
}
Layout::Univariant { ref variant, .. } => {
Layout::Univariant(ref variant) => {
for i in 0..layout.field_count() {
let field_off = off + variant.offsets[i];
classify(ccx, layout.field(ccx, i), cls, field_off)?;

View file

@ -74,7 +74,7 @@ pub fn type_is_imm_pair<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ty: Ty<'tcx>)
let layout = ccx.layout_of(ty);
match *layout {
Layout::FatPointer { .. } => true,
Layout::Univariant { ref variant, .. } => {
Layout::Univariant(ref variant) => {
// There must be only 2 fields.
if variant.offsets.len() != 2 {
return false;

View file

@ -942,7 +942,7 @@ impl<'tcx> StructMemberDescriptionFactory<'tcx> {
let tmp;
let offsets = match *layout {
layout::Univariant { ref variant, .. } => &variant.offsets,
layout::Univariant(ref variant) => &variant.offsets,
layout::Vector { element, count } => {
let element_size = element.size(cx).bytes();
tmp = (0..count).
@ -1022,7 +1022,7 @@ impl<'tcx> TupleMemberDescriptionFactory<'tcx> {
fn create_member_descriptions<'a>(&self, cx: &CrateContext<'a, 'tcx>)
-> Vec<MemberDescription> {
let layout = cx.layout_of(self.ty);
let offsets = if let layout::Univariant { ref variant, .. } = *layout {
let offsets = if let layout::Univariant(ref variant) = *layout {
&variant.offsets
} else {
bug!("{} is not a tuple", self.ty);
@ -1184,7 +1184,7 @@ impl<'tcx> EnumMemberDescriptionFactory<'tcx> {
}
}).collect()
},
layout::Univariant{ ref variant, .. } => {
layout::Univariant(ref variant) => {
assert!(adt.variants.len() <= 1);
if adt.variants.is_empty() {

View file

@ -59,7 +59,7 @@ pub fn size_and_align_of_dst<'a, 'tcx>(bcx: &Builder<'a, 'tcx>, t: Ty<'tcx>, inf
debug!("DST {} layout: {:?}", t, layout);
let (sized_size, sized_align) = match *layout {
ty::layout::Layout::Univariant { ref variant, .. } => {
ty::layout::Layout::Univariant(ref variant) => {
(variant.offsets.last().map_or(0, |o| o.bytes()), variant.align.abi())
}
_ => {

View file

@ -1111,16 +1111,16 @@ fn trans_const_adt<'a, 'tcx>(
build_const_struct(ccx, l, &variant, vals,
Some(Const::new(lldiscr, d.to_ty(ccx.tcx(), false))))
}
layout::UntaggedUnion { ref variants, .. }=> {
layout::UntaggedUnion(ref un) => {
assert_eq!(variant_index, 0);
let contents = [
vals[0].llval,
padding(ccx, variants.stride() - ccx.size_of(vals[0].ty))
padding(ccx, un.stride() - ccx.size_of(vals[0].ty))
];
Const::new(C_struct(ccx, &contents, variants.packed), t)
Const::new(C_struct(ccx, &contents, un.packed), t)
}
layout::Univariant { ref variant, .. } => {
layout::Univariant(ref variant) => {
assert_eq!(variant_index, 0);
build_const_struct(ccx, l, &variant, vals, None)
}

View file

@ -58,8 +58,8 @@ impl ops::BitOr for Alignment {
impl<'a> From<&'a Layout> for Alignment {
fn from(layout: &Layout) -> Self {
let (packed, align) = match *layout {
Layout::UntaggedUnion { ref variants } => (variants.packed, variants.align),
Layout::Univariant { ref variant, .. } => (variant.packed, variant.align),
Layout::UntaggedUnion(ref un) => (un.packed, un.align),
Layout::Univariant(ref variant) => (variant.packed, variant.align),
_ => return Alignment::AbiAligned
};
if packed {
@ -250,7 +250,7 @@ impl<'a, 'tcx> LvalueRef<'tcx> {
// Check whether the variant being used is packed, if applicable.
let is_packed = match (&*l, l.variant_index) {
(&layout::Univariant { ref variant, .. }, _) => variant.packed,
(&layout::Univariant(ref variant), _) => variant.packed,
(&layout::StructWrappedNullablePointer { ref nonnull, .. }, _) => nonnull.packed,
(&layout::General { ref variants, .. }, Some(v)) => variants[v].packed,
_ => return simple()

View file

@ -577,7 +577,7 @@ fn arg_local_refs<'a, 'tcx>(bcx: &Builder<'a, 'tcx>,
let layout = bcx.ccx.layout_of(closure_ty);
let offsets = match *layout {
layout::Univariant { ref variant, .. } => &variant.offsets[..],
layout::Univariant(ref variant) => &variant.offsets[..],
_ => bug!("Closures are only supposed to be Univariant")
};

View file

@ -254,7 +254,7 @@ impl<'tcx> LayoutLlvmExt for FullLayout<'tcx> {
adt::memory_index_to_gep(index as u64)
}
Layout::Univariant { ref variant, .. } => {
Layout::Univariant(ref variant) => {
adt::memory_index_to_gep(variant.memory_index[index] as u64)
}

View file

@ -8,7 +8,10 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// error-pattern: overflow representing the type
// error-pattern: unsupported cyclic reference between types/traits detected
// note-pattern: the cycle begins when computing layout of
// note-pattern: ...which then requires computing layout of
// note-pattern: ...which then again requires computing layout of
trait Mirror { type It: ?Sized; }

View file

@ -1,9 +0,0 @@
error[E0391]: unsupported cyclic reference between types/traits detected
|
note: the cycle begins when computing layout of `S`...
note: ...which then requires computing layout of `std::option::Option<<S as Mirror>::It>`...
note: ...which then requires computing layout of `<S as Mirror>::It`...
= note: ...which then again requires computing layout of `S`, completing the cycle.
error: aborting due to previous error

View file

@ -26,7 +26,7 @@
miri = "Broken"
# ping @Manishearth @llogiq @mcarton @oli-obk
clippy = "Testing"
clippy = "Broken"
# ping @nrc
rls = "Testing"