mirror of https://github.com/rust-lang/rust.git
rewrite layout to take a (param-env, ty) pair instead of infcx
This commit is contained in:
parent
6c4b961eff
commit
541523d10d
|
@ -112,6 +112,7 @@ pub enum DepNode<D: Clone + Debug> {
|
|||
IsSized(D),
|
||||
IsFreeze(D),
|
||||
NeedsDrop(D),
|
||||
Layout(D),
|
||||
|
||||
// The set of impls for a given trait. Ultimately, it would be
|
||||
// nice to get more fine-grained here (e.g., to include a
|
||||
|
@ -241,6 +242,7 @@ impl<D: Clone + Debug> DepNode<D> {
|
|||
IsSized(ref d) => op(d).map(IsSized),
|
||||
IsFreeze(ref d) => op(d).map(IsFreeze),
|
||||
NeedsDrop(ref d) => op(d).map(NeedsDrop),
|
||||
Layout(ref d) => op(d).map(Layout),
|
||||
Hir(ref d) => op(d).map(Hir),
|
||||
HirBody(ref d) => op(d).map(HirBody),
|
||||
MetaData(ref d) => op(d).map(MetaData),
|
||||
|
|
|
@ -10,7 +10,6 @@
|
|||
|
||||
use hir::def::Def;
|
||||
use hir::def_id::DefId;
|
||||
use infer::InferCtxt;
|
||||
use ty::{self, Ty, TyCtxt};
|
||||
use ty::layout::{LayoutError, Pointer, SizeSkeleton};
|
||||
|
||||
|
@ -30,8 +29,10 @@ struct ItemVisitor<'a, 'tcx: 'a> {
|
|||
tcx: TyCtxt<'a, 'tcx, 'tcx>
|
||||
}
|
||||
|
||||
struct ExprVisitor<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
|
||||
infcx: &'a InferCtxt<'a, 'gcx, 'tcx>
|
||||
struct ExprVisitor<'a, 'tcx: 'a> {
|
||||
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
tables: &'tcx ty::TypeckTables<'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
}
|
||||
|
||||
/// If the type is `Option<T>`, it will return `T`, otherwise
|
||||
|
@ -63,18 +64,18 @@ fn unpack_option_like<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||
ty
|
||||
}
|
||||
|
||||
impl<'a, 'gcx, 'tcx> ExprVisitor<'a, 'gcx, 'tcx> {
|
||||
impl<'a, 'tcx> ExprVisitor<'a, 'tcx> {
|
||||
fn def_id_is_transmute(&self, def_id: DefId) -> bool {
|
||||
let intrinsic = match self.infcx.tcx.type_of(def_id).sty {
|
||||
let intrinsic = match self.tcx.type_of(def_id).sty {
|
||||
ty::TyFnDef(.., bfty) => bfty.abi() == RustIntrinsic,
|
||||
_ => return false
|
||||
};
|
||||
intrinsic && self.infcx.tcx.item_name(def_id) == "transmute"
|
||||
intrinsic && self.tcx.item_name(def_id) == "transmute"
|
||||
}
|
||||
|
||||
fn check_transmute(&self, span: Span, from: Ty<'gcx>, to: Ty<'gcx>) {
|
||||
let sk_from = SizeSkeleton::compute(from, self.infcx);
|
||||
let sk_to = SizeSkeleton::compute(to, self.infcx);
|
||||
fn check_transmute(&self, span: Span, from: Ty<'tcx>, to: Ty<'tcx>) {
|
||||
let sk_from = SizeSkeleton::compute(from, self.tcx, self.param_env);
|
||||
let sk_to = SizeSkeleton::compute(to, self.tcx, self.param_env);
|
||||
|
||||
// Check for same size using the skeletons.
|
||||
if let (Ok(sk_from), Ok(sk_to)) = (sk_from, sk_to) {
|
||||
|
@ -84,11 +85,11 @@ impl<'a, 'gcx, 'tcx> ExprVisitor<'a, 'gcx, 'tcx> {
|
|||
|
||||
// Special-case transmutting from `typeof(function)` and
|
||||
// `Option<typeof(function)>` to present a clearer error.
|
||||
let from = unpack_option_like(self.infcx.tcx.global_tcx(), from);
|
||||
let from = unpack_option_like(self.tcx.global_tcx(), from);
|
||||
match (&from.sty, sk_to) {
|
||||
(&ty::TyFnDef(..), SizeSkeleton::Known(size_to))
|
||||
if size_to == Pointer.size(self.infcx) => {
|
||||
struct_span_err!(self.infcx.tcx.sess, span, E0591,
|
||||
if size_to == Pointer.size(self.tcx) => {
|
||||
struct_span_err!(self.tcx.sess, span, E0591,
|
||||
"`{}` is zero-sized and can't be transmuted to `{}`",
|
||||
from, to)
|
||||
.span_note(span, "cast with `as` to a pointer instead")
|
||||
|
@ -100,7 +101,7 @@ impl<'a, 'gcx, 'tcx> ExprVisitor<'a, 'gcx, 'tcx> {
|
|||
}
|
||||
|
||||
// Try to display a sensible error with as much information as possible.
|
||||
let skeleton_string = |ty: Ty<'gcx>, sk| {
|
||||
let skeleton_string = |ty: Ty<'tcx>, sk| {
|
||||
match sk {
|
||||
Ok(SizeSkeleton::Known(size)) => {
|
||||
format!("{} bits", size.bits())
|
||||
|
@ -119,7 +120,7 @@ impl<'a, 'gcx, 'tcx> ExprVisitor<'a, 'gcx, 'tcx> {
|
|||
}
|
||||
};
|
||||
|
||||
struct_span_err!(self.infcx.tcx.sess, span, E0512,
|
||||
struct_span_err!(self.tcx.sess, span, E0512,
|
||||
"transmute called with differently sized types: \
|
||||
{} ({}) to {} ({})",
|
||||
from, skeleton_string(from, sk_from),
|
||||
|
@ -138,32 +139,30 @@ impl<'a, 'tcx> Visitor<'tcx> for ItemVisitor<'a, 'tcx> {
|
|||
}
|
||||
|
||||
fn visit_nested_body(&mut self, body_id: hir::BodyId) {
|
||||
let owner_def_id = self.tcx.hir.body_owner_def_id(body_id);
|
||||
let body = self.tcx.hir.body(body_id);
|
||||
self.tcx.infer_ctxt(body_id).enter(|infcx| {
|
||||
let mut visitor = ExprVisitor {
|
||||
infcx: &infcx
|
||||
};
|
||||
visitor.visit_body(body);
|
||||
});
|
||||
let param_env = self.tcx.param_env(owner_def_id);
|
||||
let tables = self.tcx.typeck_tables_of(owner_def_id);
|
||||
ExprVisitor { tcx: self.tcx, param_env, tables }.visit_body(body);
|
||||
self.visit_body(body);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'gcx, 'tcx> Visitor<'gcx> for ExprVisitor<'a, 'gcx, 'tcx> {
|
||||
fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'gcx> {
|
||||
impl<'a, 'tcx> Visitor<'tcx> for ExprVisitor<'a, 'tcx> {
|
||||
fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
|
||||
NestedVisitorMap::None
|
||||
}
|
||||
|
||||
fn visit_expr(&mut self, expr: &'gcx hir::Expr) {
|
||||
fn visit_expr(&mut self, expr: &'tcx hir::Expr) {
|
||||
let def = if let hir::ExprPath(ref qpath) = expr.node {
|
||||
self.infcx.tables.borrow().qpath_def(qpath, expr.id)
|
||||
self.tables.qpath_def(qpath, expr.id)
|
||||
} else {
|
||||
Def::Err
|
||||
};
|
||||
match def {
|
||||
Def::Fn(did) if self.def_id_is_transmute(did) => {
|
||||
let typ = self.infcx.tables.borrow().node_id_to_type(expr.id);
|
||||
let typ = self.infcx.tcx.lift_to_global(&typ).unwrap();
|
||||
let typ = self.tables.node_id_to_type(expr.id);
|
||||
let typ = self.tcx.lift_to_global(&typ).unwrap();
|
||||
match typ.sty {
|
||||
ty::TyFnDef(.., sig) if sig.abi() == RustIntrinsic => {
|
||||
let from = sig.inputs().skip_binder()[0];
|
||||
|
|
|
@ -12,9 +12,7 @@ pub use self::Integer::*;
|
|||
pub use self::Layout::*;
|
||||
pub use self::Primitive::*;
|
||||
|
||||
use infer::InferCtxt;
|
||||
use session::Session;
|
||||
use traits;
|
||||
use ty::{self, Ty, TyCtxt, TypeFoldable, ReprOptions, ReprFlags};
|
||||
|
||||
use syntax::ast::{FloatTy, IntTy, UintTy};
|
||||
|
@ -212,6 +210,12 @@ impl<'a> HasDataLayout for &'a TargetDataLayout {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> HasDataLayout for TyCtxt<'a, 'tcx, 'tcx> {
|
||||
fn data_layout(&self) -> &TargetDataLayout {
|
||||
&self.data_layout
|
||||
}
|
||||
}
|
||||
|
||||
/// Endianness of the target, which must match cfg(target-endian).
|
||||
#[derive(Copy, Clone)]
|
||||
pub enum Endian {
|
||||
|
@ -457,8 +461,12 @@ impl Integer {
|
|||
/// signed discriminant range and #[repr] attribute.
|
||||
/// N.B.: u64 values above i64::MAX will be treated as signed, but
|
||||
/// that shouldn't affect anything, other than maybe debuginfo.
|
||||
fn repr_discr(tcx: TyCtxt, ty: Ty, repr: &ReprOptions, min: i64, max: i64)
|
||||
-> (Integer, bool) {
|
||||
fn repr_discr<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
ty: Ty<'tcx>,
|
||||
repr: &ReprOptions,
|
||||
min: i64,
|
||||
max: i64)
|
||||
-> (Integer, bool) {
|
||||
// Theoretically, negative values could be larger in unsigned representation
|
||||
// than the unsigned representation of the signed minimum. However, if there
|
||||
// are any negative values, the only valid unsigned representation is u64
|
||||
|
@ -583,10 +591,13 @@ enum StructKind {
|
|||
EnumVariant,
|
||||
}
|
||||
|
||||
impl<'a, 'gcx, 'tcx> Struct {
|
||||
fn new(dl: &TargetDataLayout, fields: &Vec<&'a Layout>,
|
||||
repr: &ReprOptions, kind: StructKind,
|
||||
scapegoat: Ty<'gcx>) -> Result<Struct, LayoutError<'gcx>> {
|
||||
impl<'a, 'tcx> Struct {
|
||||
fn new(dl: &TargetDataLayout,
|
||||
fields: &Vec<&'a Layout>,
|
||||
repr: &ReprOptions,
|
||||
kind: StructKind,
|
||||
scapegoat: Ty<'tcx>)
|
||||
-> Result<Struct, LayoutError<'tcx>> {
|
||||
if repr.packed() && repr.align > 0 {
|
||||
bug!("Struct cannot be packed and aligned");
|
||||
}
|
||||
|
@ -723,8 +734,8 @@ impl<'a, 'gcx, 'tcx> Struct {
|
|||
|
||||
/// Determine whether a structure would be zero-sized, given its fields.
|
||||
fn would_be_zero_sized<I>(dl: &TargetDataLayout, fields: I)
|
||||
-> Result<bool, LayoutError<'gcx>>
|
||||
where I: Iterator<Item=Result<&'a Layout, LayoutError<'gcx>>> {
|
||||
-> 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 {
|
||||
|
@ -764,11 +775,11 @@ impl<'a, 'gcx, 'tcx> Struct {
|
|||
/// The tuple is `(path, source_path)`,
|
||||
/// where `path` is in memory order and `source_path` in source order.
|
||||
// FIXME(eddyb) track value ranges and traverse already optimized enums.
|
||||
fn non_zero_field_in_type(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
|
||||
ty: Ty<'gcx>)
|
||||
-> Result<Option<(FieldPath, FieldPath)>, LayoutError<'gcx>> {
|
||||
let tcx = infcx.tcx.global_tcx();
|
||||
match (ty.layout(infcx)?, &ty.sty) {
|
||||
fn non_zero_field_in_type(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
ty: Ty<'tcx>)
|
||||
-> Result<Option<(FieldPath, FieldPath)>, LayoutError<'tcx>> {
|
||||
match (ty.layout(tcx, param_env)?, &ty.sty) {
|
||||
(&Scalar { non_zero: true, .. }, _) |
|
||||
(&CEnum { non_zero: true, .. }, _) => Ok(Some((vec![], vec![]))),
|
||||
(&FatPointer { non_zero: true, .. }, _) => {
|
||||
|
@ -779,7 +790,7 @@ impl<'a, 'gcx, 'tcx> Struct {
|
|||
(&Univariant { non_zero: true, .. }, &ty::TyAdt(def, substs)) => {
|
||||
let fields = &def.struct_variant().fields;
|
||||
assert_eq!(fields.len(), 1);
|
||||
match *fields[0].ty(tcx, substs).layout(infcx)? {
|
||||
match *fields[0].ty(tcx, substs).layout(tcx, param_env)? {
|
||||
// FIXME(eddyb) also allow floating-point types here.
|
||||
Scalar { value: Int(_), non_zero: false } |
|
||||
Scalar { value: Pointer, non_zero: false } => {
|
||||
|
@ -796,37 +807,49 @@ impl<'a, 'gcx, 'tcx> Struct {
|
|||
// 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() => {
|
||||
Struct::non_zero_field_paths(infcx, def.struct_variant().fields
|
||||
.iter().map(|field| {
|
||||
field.ty(tcx, substs)
|
||||
}),
|
||||
Some(&variant.memory_index[..]))
|
||||
Struct::non_zero_field_paths(
|
||||
tcx,
|
||||
param_env,
|
||||
def.struct_variant().fields.iter().map(|field| {
|
||||
field.ty(tcx, substs)
|
||||
}),
|
||||
Some(&variant.memory_index[..]))
|
||||
}
|
||||
|
||||
// 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);
|
||||
Struct::non_zero_field_paths(infcx, upvar_tys,
|
||||
Struct::non_zero_field_paths(
|
||||
tcx,
|
||||
param_env,
|
||||
upvar_tys,
|
||||
Some(&variant.memory_index[..]))
|
||||
}
|
||||
// Can we use one of the fields in this tuple?
|
||||
(&Univariant { ref variant, .. }, &ty::TyTuple(tys, _)) => {
|
||||
Struct::non_zero_field_paths(infcx, tys.iter().cloned(),
|
||||
Struct::non_zero_field_paths(
|
||||
tcx,
|
||||
param_env,
|
||||
tys.iter().cloned(),
|
||||
Some(&variant.memory_index[..]))
|
||||
}
|
||||
|
||||
// Is this a fixed-size array of something non-zero
|
||||
// with at least one element?
|
||||
(_, &ty::TyArray(ety, d)) if d > 0 => {
|
||||
Struct::non_zero_field_paths(infcx, Some(ety).into_iter(), None)
|
||||
Struct::non_zero_field_paths(
|
||||
tcx,
|
||||
param_env,
|
||||
Some(ety).into_iter(),
|
||||
None)
|
||||
}
|
||||
|
||||
(_, &ty::TyProjection(_)) | (_, &ty::TyAnon(..)) => {
|
||||
let normalized = infcx.normalize_projections(ty);
|
||||
let normalized = tcx.normalize_associated_type_in_env(&ty, param_env);
|
||||
if ty == normalized {
|
||||
return Ok(None);
|
||||
}
|
||||
return Struct::non_zero_field_in_type(infcx, normalized);
|
||||
return Struct::non_zero_field_in_type(tcx, param_env, normalized);
|
||||
}
|
||||
|
||||
// Anything else is not a non-zero type.
|
||||
|
@ -838,13 +861,15 @@ impl<'a, 'gcx, 'tcx> Struct {
|
|||
/// the given set of fields and recursing through aggregates.
|
||||
/// Returns Some((path, source_path)) on success.
|
||||
/// `path` is translated to memory order. `source_path` is not.
|
||||
fn non_zero_field_paths<I>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
|
||||
fields: I,
|
||||
permutation: Option<&[u32]>)
|
||||
-> Result<Option<(FieldPath, FieldPath)>, LayoutError<'gcx>>
|
||||
where I: Iterator<Item=Ty<'gcx>> {
|
||||
fn non_zero_field_paths<I>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
fields: I,
|
||||
permutation: Option<&[u32]>)
|
||||
-> Result<Option<(FieldPath, FieldPath)>, LayoutError<'tcx>>
|
||||
where I: Iterator<Item=Ty<'tcx>> {
|
||||
for (i, ty) in fields.enumerate() {
|
||||
if let Some((mut path, mut source_path)) = Struct::non_zero_field_in_type(infcx, ty)? {
|
||||
let r = Struct::non_zero_field_in_type(tcx, param_env, ty)?;
|
||||
if let Some((mut path, mut source_path)) = r {
|
||||
source_path.push(i as u32);
|
||||
let index = if let Some(p) = permutation {
|
||||
p[i] as usize
|
||||
|
@ -881,7 +906,7 @@ pub struct Union {
|
|||
pub packed: bool,
|
||||
}
|
||||
|
||||
impl<'a, 'gcx, 'tcx> Union {
|
||||
impl<'a, 'tcx> Union {
|
||||
fn new(dl: &TargetDataLayout, packed: bool) -> Union {
|
||||
let align = if packed { dl.i8_align } else { dl.aggregate_align };
|
||||
Union {
|
||||
|
@ -895,9 +920,9 @@ impl<'a, 'gcx, 'tcx> Union {
|
|||
/// Extend the Struct with more fields.
|
||||
fn extend<I>(&mut self, dl: &TargetDataLayout,
|
||||
fields: I,
|
||||
scapegoat: Ty<'gcx>)
|
||||
-> Result<(), LayoutError<'gcx>>
|
||||
where I: Iterator<Item=Result<&'a Layout, LayoutError<'gcx>>> {
|
||||
scapegoat: Ty<'tcx>)
|
||||
-> Result<(), LayoutError<'tcx>>
|
||||
where I: Iterator<Item=Result<&'a Layout, LayoutError<'tcx>>> {
|
||||
for (index, field) in fields.enumerate() {
|
||||
let field = field?;
|
||||
if field.is_unsized() {
|
||||
|
@ -1067,19 +1092,19 @@ impl<'tcx> fmt::Display for LayoutError<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, 'gcx, 'tcx> Layout {
|
||||
pub fn compute_uncached(ty: Ty<'gcx>,
|
||||
infcx: &InferCtxt<'a, 'gcx, 'tcx>)
|
||||
-> Result<&'gcx Layout, LayoutError<'gcx>> {
|
||||
let tcx = infcx.tcx.global_tcx();
|
||||
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>> {
|
||||
let success = |layout| Ok(tcx.intern_layout(layout));
|
||||
let dl = &tcx.data_layout;
|
||||
assert!(!ty.has_infer_types());
|
||||
|
||||
let ptr_layout = |pointee: Ty<'gcx>| {
|
||||
let ptr_layout = |pointee: Ty<'tcx>| {
|
||||
let non_zero = !ty.is_unsafe_ptr();
|
||||
let pointee = infcx.normalize_projections(pointee);
|
||||
if pointee.is_sized(tcx, infcx.param_env, DUMMY_SP) {
|
||||
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 })
|
||||
} else {
|
||||
let unsized_part = tcx.struct_tail(pointee);
|
||||
|
@ -1132,7 +1157,7 @@ impl<'a, 'gcx, 'tcx> Layout {
|
|||
|
||||
// Arrays and slices.
|
||||
ty::TyArray(element, count) => {
|
||||
let element = element.layout(infcx)?;
|
||||
let element = element.layout(tcx, param_env)?;
|
||||
let element_size = element.size(dl);
|
||||
// FIXME(eddyb) Don't use host `usize` for array lengths.
|
||||
let usize_count: usize = count;
|
||||
|
@ -1149,7 +1174,7 @@ impl<'a, 'gcx, 'tcx> Layout {
|
|||
}
|
||||
}
|
||||
ty::TySlice(element) => {
|
||||
let element = element.layout(infcx)?;
|
||||
let element = element.layout(tcx, param_env)?;
|
||||
Array {
|
||||
sized: false,
|
||||
align: element.align(dl),
|
||||
|
@ -1187,7 +1212,7 @@ impl<'a, 'gcx, 'tcx> Layout {
|
|||
ty::TyClosure(def_id, ref substs) => {
|
||||
let tys = substs.upvar_tys(def_id, tcx);
|
||||
let st = Struct::new(dl,
|
||||
&tys.map(|ty| ty.layout(infcx))
|
||||
&tys.map(|ty| ty.layout(tcx, param_env))
|
||||
.collect::<Result<Vec<_>, _>>()?,
|
||||
&ReprOptions::default(),
|
||||
StructKind::AlwaysSizedUnivariant, ty)?;
|
||||
|
@ -1198,7 +1223,7 @@ impl<'a, 'gcx, 'tcx> Layout {
|
|||
// FIXME(camlorn): if we ever allow unsized tuples, this needs to be checked.
|
||||
// See the univariant case below to learn how.
|
||||
let st = Struct::new(dl,
|
||||
&tys.iter().map(|ty| ty.layout(infcx))
|
||||
&tys.iter().map(|ty| ty.layout(tcx, param_env))
|
||||
.collect::<Result<Vec<_>, _>>()?,
|
||||
&ReprOptions::default(), StructKind::AlwaysSizedUnivariant, ty)?;
|
||||
Univariant { variant: st, non_zero: false }
|
||||
|
@ -1207,7 +1232,7 @@ impl<'a, 'gcx, 'tcx> Layout {
|
|||
// SIMD vector types.
|
||||
ty::TyAdt(def, ..) if def.repr.simd() => {
|
||||
let element = ty.simd_type(tcx);
|
||||
match *element.layout(infcx)? {
|
||||
match *element.layout(tcx, param_env)? {
|
||||
Scalar { value, .. } => {
|
||||
return success(Vector {
|
||||
element: value,
|
||||
|
@ -1278,7 +1303,7 @@ impl<'a, 'gcx, 'tcx> Layout {
|
|||
};
|
||||
|
||||
let fields = def.variants[0].fields.iter().map(|field| {
|
||||
field.ty(tcx, substs).layout(infcx)
|
||||
field.ty(tcx, substs).layout(tcx, param_env)
|
||||
}).collect::<Result<Vec<_>, _>>()?;
|
||||
let layout = if def.is_union() {
|
||||
let mut un = Union::new(dl, def.repr.packed());
|
||||
|
@ -1312,20 +1337,21 @@ impl<'a, 'gcx, 'tcx> Layout {
|
|||
// Nullable pointer optimization
|
||||
for discr in 0..2 {
|
||||
let other_fields = variants[1 - discr].iter().map(|ty| {
|
||||
ty.layout(infcx)
|
||||
ty.layout(tcx, param_env)
|
||||
});
|
||||
if !Struct::would_be_zero_sized(dl, other_fields)? {
|
||||
continue;
|
||||
}
|
||||
let paths = Struct::non_zero_field_paths(infcx,
|
||||
variants[discr].iter().cloned(),
|
||||
None)?;
|
||||
let paths = Struct::non_zero_field_paths(tcx,
|
||||
param_env,
|
||||
variants[discr].iter().cloned(),
|
||||
None)?;
|
||||
let (mut path, mut path_source) = if let Some(p) = paths { p }
|
||||
else { continue };
|
||||
|
||||
// FIXME(eddyb) should take advantage of a newtype.
|
||||
if path == &[0] && variants[discr].len() == 1 {
|
||||
let value = match *variants[discr][0].layout(infcx)? {
|
||||
let value = match *variants[discr][0].layout(tcx, param_env)? {
|
||||
Scalar { value, .. } => value,
|
||||
CEnum { discr, .. } => Int(discr),
|
||||
_ => bug!("Layout::compute: `{}`'s non-zero \
|
||||
|
@ -1339,7 +1365,7 @@ impl<'a, 'gcx, 'tcx> Layout {
|
|||
}
|
||||
|
||||
let st = Struct::new(dl,
|
||||
&variants[discr].iter().map(|ty| ty.layout(infcx))
|
||||
&variants[discr].iter().map(|ty| ty.layout(tcx, param_env))
|
||||
.collect::<Result<Vec<_>, _>>()?,
|
||||
&def.repr, StructKind::AlwaysSizedUnivariant, ty)?;
|
||||
|
||||
|
@ -1377,7 +1403,7 @@ impl<'a, 'gcx, 'tcx> Layout {
|
|||
let discr = Scalar { value: Int(min_ity), non_zero: false };
|
||||
let mut variants = variants.into_iter().map(|fields| {
|
||||
let mut fields = fields.into_iter().map(|field| {
|
||||
field.layout(infcx)
|
||||
field.layout(tcx, param_env)
|
||||
}).collect::<Result<Vec<_>, _>>()?;
|
||||
fields.insert(0, &discr);
|
||||
let st = Struct::new(dl,
|
||||
|
@ -1470,11 +1496,11 @@ impl<'a, 'gcx, 'tcx> Layout {
|
|||
|
||||
// Types with no meaningful known layout.
|
||||
ty::TyProjection(_) | ty::TyAnon(..) => {
|
||||
let normalized = infcx.normalize_projections(ty);
|
||||
let normalized = tcx.normalize_associated_type_in_env(&ty, param_env);
|
||||
if ty == normalized {
|
||||
return Err(LayoutError::Unknown(ty));
|
||||
}
|
||||
return normalized.layout(infcx);
|
||||
return normalized.layout(tcx, param_env);
|
||||
}
|
||||
ty::TyParam(_) => {
|
||||
return Err(LayoutError::Unknown(ty));
|
||||
|
@ -1686,21 +1712,22 @@ pub enum SizeSkeleton<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, 'gcx, 'tcx> SizeSkeleton<'gcx> {
|
||||
pub fn compute(ty: Ty<'gcx>, infcx: &InferCtxt<'a, 'gcx, 'tcx>)
|
||||
-> Result<SizeSkeleton<'gcx>, LayoutError<'gcx>> {
|
||||
let tcx = infcx.tcx.global_tcx();
|
||||
impl<'a, 'tcx> SizeSkeleton<'tcx> {
|
||||
pub fn compute(ty: Ty<'tcx>,
|
||||
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>)
|
||||
-> Result<SizeSkeleton<'tcx>, LayoutError<'tcx>> {
|
||||
assert!(!ty.has_infer_types());
|
||||
|
||||
// First try computing a static layout.
|
||||
let err = match ty.layout(infcx) {
|
||||
let err = match ty.layout(tcx, param_env) {
|
||||
Ok(layout) => {
|
||||
return Ok(SizeSkeleton::Known(layout.size(tcx)));
|
||||
}
|
||||
Err(err) => err
|
||||
};
|
||||
|
||||
let ptr_skeleton = |pointee: Ty<'gcx>| {
|
||||
let ptr_skeleton = |pointee: Ty<'tcx>| {
|
||||
let non_zero = !ty.is_unsafe_ptr();
|
||||
let tail = tcx.struct_tail(pointee);
|
||||
match tail.sty {
|
||||
|
@ -1737,7 +1764,7 @@ impl<'a, 'gcx, 'tcx> SizeSkeleton<'gcx> {
|
|||
// Get a zero-sized variant or a pointer newtype.
|
||||
let zero_or_ptr_variant = |i: usize| {
|
||||
let fields = def.variants[i].fields.iter().map(|field| {
|
||||
SizeSkeleton::compute(field.ty(tcx, substs), infcx)
|
||||
SizeSkeleton::compute(field.ty(tcx, substs), tcx, param_env)
|
||||
});
|
||||
let mut ptr = None;
|
||||
for field in fields {
|
||||
|
@ -1788,11 +1815,11 @@ impl<'a, 'gcx, 'tcx> SizeSkeleton<'gcx> {
|
|||
}
|
||||
|
||||
ty::TyProjection(_) | ty::TyAnon(..) => {
|
||||
let normalized = infcx.normalize_projections(ty);
|
||||
let normalized = tcx.normalize_associated_type_in_env(&ty, param_env);
|
||||
if ty == normalized {
|
||||
Err(err)
|
||||
} else {
|
||||
SizeSkeleton::compute(normalized, infcx)
|
||||
SizeSkeleton::compute(normalized, tcx, param_env)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1826,71 +1853,53 @@ impl<'tcx> Deref for TyLayout<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
pub trait HasTyCtxt<'tcx>: HasDataLayout {
|
||||
pub trait LayoutTyper<'tcx>: HasDataLayout {
|
||||
type TyLayout;
|
||||
|
||||
fn tcx<'a>(&'a self) -> TyCtxt<'a, 'tcx, 'tcx>;
|
||||
fn layout_of(self, ty: Ty<'tcx>) -> Self::TyLayout;
|
||||
fn normalize_projections(self, ty: Ty<'tcx>) -> Ty<'tcx>;
|
||||
}
|
||||
|
||||
impl<'a, 'gcx, 'tcx> HasDataLayout for TyCtxt<'a, 'gcx, 'tcx> {
|
||||
fn data_layout(&self) -> &TargetDataLayout {
|
||||
&self.data_layout
|
||||
/// Combines a tcx with the parameter environment so that you can
|
||||
/// compute layout operations.
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct LayoutCx<'a, 'tcx: 'a> {
|
||||
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> LayoutCx<'a, 'tcx> {
|
||||
pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>, param_env: ty::ParamEnv<'tcx>) -> Self {
|
||||
LayoutCx { tcx, param_env }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'gcx, 'tcx> HasTyCtxt<'gcx> for TyCtxt<'a, 'gcx, 'tcx> {
|
||||
fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'gcx> {
|
||||
self.global_tcx()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'gcx, 'tcx> HasDataLayout for &'a InferCtxt<'a, 'gcx, 'tcx> {
|
||||
impl<'a, 'tcx> HasDataLayout for LayoutCx<'a, 'tcx> {
|
||||
fn data_layout(&self) -> &TargetDataLayout {
|
||||
&self.tcx.data_layout
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'gcx, 'tcx> HasTyCtxt<'gcx> for &'a InferCtxt<'a, 'gcx, 'tcx> {
|
||||
fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'gcx> {
|
||||
self.tcx.global_tcx()
|
||||
impl<'a, 'tcx> LayoutTyper<'tcx> for LayoutCx<'a, 'tcx> {
|
||||
type TyLayout = Result<TyLayout<'tcx>, LayoutError<'tcx>>;
|
||||
|
||||
fn tcx<'b>(&'b self) -> TyCtxt<'b, 'tcx, 'tcx> {
|
||||
self.tcx
|
||||
}
|
||||
}
|
||||
|
||||
pub trait LayoutTyper<'tcx>: HasTyCtxt<'tcx> {
|
||||
type TyLayout;
|
||||
|
||||
fn layout_of(self, ty: Ty<'tcx>) -> Self::TyLayout;
|
||||
fn normalize_projections(self, ty: Ty<'tcx>) -> Ty<'tcx>;
|
||||
}
|
||||
|
||||
impl<'a, 'gcx, 'tcx> LayoutTyper<'gcx> for &'a InferCtxt<'a, 'gcx, 'tcx> {
|
||||
type TyLayout = Result<TyLayout<'gcx>, LayoutError<'gcx>>;
|
||||
|
||||
fn layout_of(self, ty: Ty<'gcx>) -> Self::TyLayout {
|
||||
fn layout_of(self, ty: Ty<'tcx>) -> Self::TyLayout {
|
||||
let ty = self.normalize_projections(ty);
|
||||
|
||||
Ok(TyLayout {
|
||||
ty: ty,
|
||||
layout: ty.layout(self)?,
|
||||
layout: ty.layout(self.tcx, self.param_env)?,
|
||||
variant_index: None
|
||||
})
|
||||
}
|
||||
|
||||
fn normalize_projections(self, ty: Ty<'gcx>) -> Ty<'gcx> {
|
||||
if !ty.has_projection_types() {
|
||||
return ty;
|
||||
}
|
||||
|
||||
let mut selcx = traits::SelectionContext::new(self);
|
||||
let cause = traits::ObligationCause::dummy();
|
||||
let traits::Normalized { value: result, obligations } =
|
||||
traits::normalize(&mut selcx, cause, &ty);
|
||||
|
||||
let mut fulfill_cx = traits::FulfillmentContext::new();
|
||||
|
||||
for obligation in obligations {
|
||||
fulfill_cx.register_predicate_obligation(self, obligation);
|
||||
}
|
||||
|
||||
self.drain_fulfillment_cx_or_panic(DUMMY_SP, &mut fulfill_cx, &result)
|
||||
fn normalize_projections(self, ty: Ty<'tcx>) -> Ty<'tcx> {
|
||||
self.tcx.normalize_associated_type_in_env(&ty, self.param_env)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1943,7 +1952,7 @@ impl<'a, 'tcx> TyLayout<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn field_type<C: HasTyCtxt<'tcx>>(&self, cx: C, i: usize) -> Ty<'tcx> {
|
||||
pub fn field_type<C: LayoutTyper<'tcx>>(&self, cx: C, i: usize) -> Ty<'tcx> {
|
||||
let tcx = cx.tcx();
|
||||
|
||||
let ptr_field_type = |pointee: Ty<'tcx>| {
|
||||
|
@ -2014,7 +2023,10 @@ impl<'a, 'tcx> TyLayout<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn field<C: LayoutTyper<'tcx>>(&self, cx: C, i: usize) -> C::TyLayout {
|
||||
pub fn field<C: LayoutTyper<'tcx>>(&self,
|
||||
cx: C,
|
||||
i: usize)
|
||||
-> C::TyLayout {
|
||||
cx.layout_of(cx.normalize_projections(self.field_type(cx, i)))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@ use mir::transform::{MirSuite, MirPassIndex};
|
|||
use session::CompileResult;
|
||||
use traits::specialization_graph;
|
||||
use ty::{self, CrateInherentImpls, Ty, TyCtxt};
|
||||
use ty::layout::{Layout, LayoutError};
|
||||
use ty::item_path;
|
||||
use ty::steal::Steal;
|
||||
use ty::subst::Substs;
|
||||
|
@ -293,6 +294,12 @@ impl<'tcx> QueryDescription for queries::needs_drop_raw<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'tcx> QueryDescription for queries::layout_raw<'tcx> {
|
||||
fn describe(_tcx: TyCtxt, env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> String {
|
||||
format!("computing layout of `{}`", env.value)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> QueryDescription for queries::super_predicates_of<'tcx> {
|
||||
fn describe(tcx: TyCtxt, def_id: DefId) -> String {
|
||||
format!("computing the supertraits of `{}`",
|
||||
|
@ -920,6 +927,8 @@ define_maps! { <'tcx>
|
|||
[] is_sized_raw: is_sized_dep_node(ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool,
|
||||
[] is_freeze_raw: is_freeze_dep_node(ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool,
|
||||
[] needs_drop_raw: needs_drop_dep_node(ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool,
|
||||
[] layout_raw: layout_dep_node(ty::ParamEnvAnd<'tcx, Ty<'tcx>>)
|
||||
-> Result<&'tcx Layout, LayoutError<'tcx>>,
|
||||
}
|
||||
|
||||
fn coherent_trait_dep_node((_, def_id): (CrateNum, DefId)) -> DepNode<DefId> {
|
||||
|
@ -987,3 +996,9 @@ fn needs_drop_dep_node<'tcx>(key: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> DepNode<De
|
|||
.unwrap_or(DefId::local(CRATE_DEF_INDEX));
|
||||
DepNode::NeedsDrop(def_id)
|
||||
}
|
||||
|
||||
fn layout_dep_node<'tcx>(key: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> DepNode<DefId> {
|
||||
let def_id = ty::item_path::characteristic_def_id_of_type(key.value)
|
||||
.unwrap_or(DefId::local(CRATE_DEF_INDEX));
|
||||
DepNode::Layout(def_id)
|
||||
}
|
||||
|
|
|
@ -12,7 +12,6 @@
|
|||
|
||||
use hir::def_id::{DefId, LOCAL_CRATE};
|
||||
use hir::map::DefPathData;
|
||||
use infer::InferCtxt;
|
||||
use ich::{StableHashingContext, NodeIdHashingMode};
|
||||
use traits::{self, Reveal};
|
||||
use ty::{self, Ty, TyCtxt, TypeFoldable};
|
||||
|
@ -791,35 +790,17 @@ 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, infcx: &InferCtxt<'a, 'tcx, 'lcx>)
|
||||
pub fn layout<'lcx>(&'tcx self,
|
||||
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>)
|
||||
-> Result<&'tcx Layout, LayoutError<'tcx>> {
|
||||
let tcx = infcx.tcx.global_tcx();
|
||||
let can_cache = !self.has_param_types() && !self.has_self_ty();
|
||||
if can_cache {
|
||||
if let Some(&cached) = tcx.layout_cache.borrow().get(&self) {
|
||||
return Ok(cached);
|
||||
}
|
||||
}
|
||||
|
||||
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 `{}`", self));
|
||||
}
|
||||
|
||||
tcx.layout_depth.set(depth+1);
|
||||
let layout = Layout::compute_uncached(self, infcx);
|
||||
tcx.layout_depth.set(depth);
|
||||
let layout = layout?;
|
||||
if can_cache {
|
||||
tcx.layout_cache.borrow_mut().insert(self, layout);
|
||||
}
|
||||
Ok(layout)
|
||||
let ty = tcx.erase_regions(&self);
|
||||
tcx.layout_raw(param_env.reveal_all().and(ty))
|
||||
}
|
||||
|
||||
|
||||
/// 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,
|
||||
|
@ -1074,6 +1055,24 @@ 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 fn provide(providers: &mut ty::maps::Providers) {
|
||||
*providers = ty::maps::Providers {
|
||||
|
@ -1081,6 +1080,7 @@ pub fn provide(providers: &mut ty::maps::Providers) {
|
|||
is_sized_raw,
|
||||
is_freeze_raw,
|
||||
needs_drop_raw,
|
||||
layout_raw,
|
||||
..*providers
|
||||
};
|
||||
}
|
||||
|
|
|
@ -14,7 +14,6 @@ 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::traits::Reveal;
|
||||
use middle::const_val::ConstVal;
|
||||
use rustc_const_eval::ConstContext;
|
||||
use util::nodemap::FxHashSet;
|
||||
|
@ -724,12 +723,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for VariantSizeDifferences {
|
|||
if let hir::ItemEnum(ref enum_definition, ref gens) = it.node {
|
||||
if gens.ty_params.is_empty() {
|
||||
// sizes only make sense for non-generic types
|
||||
let t = cx.tcx.type_of(cx.tcx.hir.local_def_id(it.id));
|
||||
let layout = cx.tcx.infer_ctxt(Reveal::All).enter(|infcx| {
|
||||
let ty = cx.tcx.erase_regions(&t);
|
||||
ty.layout(&infcx).unwrap_or_else(|e| {
|
||||
bug!("failed to get layout for `{}`: {}", t, e)
|
||||
})
|
||||
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.tcx.param_env(item_def_id).reveal_all();
|
||||
let ty = cx.tcx.erase_regions(&t);
|
||||
let layout = ty.layout(cx.tcx, param_env).unwrap_or_else(|e| {
|
||||
bug!("failed to get layout for `{}`: {}", t, e)
|
||||
});
|
||||
|
||||
if let Layout::General { ref variants, ref size, discr, .. } = *layout {
|
||||
|
|
|
@ -547,10 +547,8 @@ 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> {
|
||||
tcx.infer_ctxt(param_env.reveal_all()).enter(|infcx| {
|
||||
ty.layout(&infcx).ok().map(|layout| {
|
||||
layout.size(&tcx.data_layout).bytes()
|
||||
})
|
||||
ty.layout(tcx, param_env).ok().map(|layout| {
|
||||
layout.size(&tcx.data_layout).bytes()
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -25,10 +25,10 @@ use type_::Type;
|
|||
use rustc_data_structures::base_n;
|
||||
use rustc::ty::subst::Substs;
|
||||
use rustc::ty::{self, Ty, TyCtxt};
|
||||
use rustc::ty::layout::{LayoutTyper, TyLayout};
|
||||
use rustc::session::config::{self, NoDebugInfo};
|
||||
use rustc::session::Session;
|
||||
use rustc::util::nodemap::{NodeSet, DefIdMap, FxHashMap};
|
||||
use rustc::ty::layout::{LayoutCx, LayoutError, LayoutTyper, TyLayout};
|
||||
use session::config::{self, NoDebugInfo};
|
||||
use session::Session;
|
||||
use util::nodemap::{NodeSet, DefIdMap, FxHashMap};
|
||||
|
||||
use std::ffi::{CStr, CString};
|
||||
use std::cell::{Cell, RefCell};
|
||||
|
@ -709,41 +709,27 @@ impl<'a, 'tcx> ty::layout::HasDataLayout for &'a SharedCrateContext<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> ty::layout::HasTyCtxt<'tcx> for &'a SharedCrateContext<'a, 'tcx> {
|
||||
fn tcx<'b>(&'b self) -> TyCtxt<'b, 'tcx, 'tcx> {
|
||||
self.tcx
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> ty::layout::HasDataLayout for &'a CrateContext<'a, 'tcx> {
|
||||
fn data_layout(&self) -> &ty::layout::TargetDataLayout {
|
||||
&self.shared.tcx.data_layout
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> ty::layout::HasTyCtxt<'tcx> for &'a CrateContext<'a, 'tcx> {
|
||||
fn tcx<'b>(&'b self) -> TyCtxt<'b, 'tcx, 'tcx> {
|
||||
self.shared.tcx
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> LayoutTyper<'tcx> for &'a SharedCrateContext<'a, 'tcx> {
|
||||
type TyLayout = TyLayout<'tcx>;
|
||||
|
||||
fn layout_of(self, ty: Ty<'tcx>) -> Self::TyLayout {
|
||||
if let Some(&layout) = self.tcx().layout_cache.borrow().get(&ty) {
|
||||
return TyLayout { ty: ty, layout: layout, variant_index: None };
|
||||
}
|
||||
fn tcx<'b>(&'b self) -> TyCtxt<'b, 'tcx, 'tcx> {
|
||||
self.tcx
|
||||
}
|
||||
|
||||
self.tcx().infer_ctxt(traits::Reveal::All).enter(|infcx| {
|
||||
infcx.layout_of(ty).unwrap_or_else(|e| {
|
||||
match e {
|
||||
ty::layout::LayoutError::SizeOverflow(_) =>
|
||||
self.sess().fatal(&e.to_string()),
|
||||
_ => bug!("failed to get layout for `{}`: {}", ty, e)
|
||||
}
|
||||
fn layout_of(self, ty: Ty<'tcx>) -> Self::TyLayout {
|
||||
let param_env = ty::ParamEnv::empty(traits::Reveal::All);
|
||||
LayoutCx::new(self.tcx, param_env)
|
||||
.layout_of(ty)
|
||||
.unwrap_or_else(|e| match e {
|
||||
LayoutError::SizeOverflow(_) => self.sess().fatal(&e.to_string()),
|
||||
_ => bug!("failed to get layout for `{}`: {}", ty, e)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
fn normalize_projections(self, ty: Ty<'tcx>) -> Ty<'tcx> {
|
||||
|
@ -754,6 +740,10 @@ impl<'a, 'tcx> LayoutTyper<'tcx> for &'a SharedCrateContext<'a, 'tcx> {
|
|||
impl<'a, 'tcx> LayoutTyper<'tcx> for &'a CrateContext<'a, 'tcx> {
|
||||
type TyLayout = TyLayout<'tcx>;
|
||||
|
||||
fn tcx<'b>(&'b self) -> TyCtxt<'b, 'tcx, 'tcx> {
|
||||
self.shared.tcx
|
||||
}
|
||||
|
||||
fn layout_of(self, ty: Ty<'tcx>) -> Self::TyLayout {
|
||||
self.shared.layout_of(ty)
|
||||
}
|
||||
|
|
|
@ -46,15 +46,13 @@ pub fn needs_drop_glue<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>, t: Ty<'tcx>
|
|||
ty::TyAdt(def, _) if def.is_box() => {
|
||||
let typ = t.boxed_ty();
|
||||
if !scx.type_needs_drop(typ) && scx.type_is_sized(typ) {
|
||||
scx.tcx().infer_ctxt(traits::Reveal::All).enter(|infcx| {
|
||||
let layout = t.layout(&infcx).unwrap();
|
||||
if layout.size(scx).bytes() == 0 {
|
||||
// `Box<ZeroSizeType>` does not allocate.
|
||||
false
|
||||
} else {
|
||||
true
|
||||
}
|
||||
})
|
||||
let layout = t.layout(scx.tcx(), ty::ParamEnv::empty(traits::Reveal::All)).unwrap();
|
||||
if layout.size(scx).bytes() == 0 {
|
||||
// `Box<ZeroSizeType>` does not allocate.
|
||||
false
|
||||
} else {
|
||||
true
|
||||
}
|
||||
} else {
|
||||
true
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue