Skip to content

Commit

Permalink
rustc: don't special-case Box<T> as having a pointer layout.
Browse files Browse the repository at this point in the history
  • Loading branch information
eddyb committed Nov 19, 2017
1 parent 18ecc56 commit fa67abd
Show file tree
Hide file tree
Showing 3 changed files with 98 additions and 109 deletions.
18 changes: 14 additions & 4 deletions src/liballoc/boxed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ impl<T> Place<T> for IntermediateBox<T> {
unsafe fn finalize<T>(b: IntermediateBox<T>) -> Box<T> {
let p = b.ptr as *mut T;
mem::forget(b);
mem::transmute(p)
Box::from_raw(p)
}

fn make_place<T>() -> IntermediateBox<T> {
Expand Down Expand Up @@ -300,7 +300,10 @@ impl<T: ?Sized> Box<T> {
issue = "27730")]
#[inline]
pub unsafe fn from_unique(u: Unique<T>) -> Self {
mem::transmute(u)
#[cfg(stage0)]
return mem::transmute(u);
#[cfg(not(stage0))]
return Box(u);
}

/// Consumes the `Box`, returning the wrapped raw pointer.
Expand Down Expand Up @@ -362,7 +365,14 @@ impl<T: ?Sized> Box<T> {
issue = "27730")]
#[inline]
pub fn into_unique(b: Box<T>) -> Unique<T> {
unsafe { mem::transmute(b) }
#[cfg(stage0)]
return unsafe { mem::transmute(b) };
#[cfg(not(stage0))]
return {
let unique = b.0;
mem::forget(b);
unique
};
}
}

Expand Down Expand Up @@ -627,7 +637,7 @@ impl Box<Any + Send> {
pub fn downcast<T: Any>(self) -> Result<Box<T>, Box<Any + Send>> {
<Box<Any>>::downcast(self).map_err(|s| unsafe {
// reapply the Send marker
mem::transmute::<Box<Any>, Box<Any + Send>>(s)
Box::from_raw(Box::into_raw(s) as *mut (Any + Send))
})
}
}
Expand Down
168 changes: 73 additions & 95 deletions src/librustc/ty/layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1152,37 +1152,6 @@ impl<'a, 'tcx> CachedLayout {
};
assert!(!ty.has_infer_types());

let ptr_layout = |pointee: Ty<'tcx>| {
let mut data_ptr = scalar_unit(Pointer);
if !ty.is_unsafe_ptr() {
data_ptr.valid_range.start = 1;
}

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(CachedLayout::scalar(cx, data_ptr)));
}

let unsized_part = tcx.struct_tail(pointee);
let metadata = match unsized_part.sty {
ty::TyForeign(..) => {
return Ok(tcx.intern_layout(CachedLayout::scalar(cx, data_ptr)));
}
ty::TySlice(_) | ty::TyStr => {
scalar_unit(Int(dl.ptr_sized_integer(), false))
}
ty::TyDynamic(..) => {
let mut vtable = scalar_unit(Pointer);
vtable.valid_range.start = 1;
vtable
}
_ => return Err(LayoutError::Unknown(unsized_part))
};

// Effectively a (ptr, meta) tuple.
Ok(tcx.intern_layout(scalar_pair(data_ptr, metadata)))
};

Ok(match ty.sty {
// Basic scalars.
ty::TyBool => {
Expand Down Expand Up @@ -1219,10 +1188,34 @@ impl<'a, 'tcx> CachedLayout {
// Potentially-fat pointers.
ty::TyRef(_, ty::TypeAndMut { ty: pointee, .. }) |
ty::TyRawPtr(ty::TypeAndMut { ty: pointee, .. }) => {
ptr_layout(pointee)?
}
ty::TyAdt(def, _) if def.is_box() => {
ptr_layout(ty.boxed_ty())?
let mut data_ptr = scalar_unit(Pointer);
if !ty.is_unsafe_ptr() {
data_ptr.valid_range.start = 1;
}

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(CachedLayout::scalar(cx, data_ptr)));
}

let unsized_part = tcx.struct_tail(pointee);
let metadata = match unsized_part.sty {
ty::TyForeign(..) => {
return Ok(tcx.intern_layout(CachedLayout::scalar(cx, data_ptr)));
}
ty::TySlice(_) | ty::TyStr => {
scalar_unit(Int(dl.ptr_sized_integer(), false))
}
ty::TyDynamic(..) => {
let mut vtable = scalar_unit(Pointer);
vtable.valid_range.start = 1;
vtable
}
_ => return Err(LayoutError::Unknown(unsized_part))
};

// Effectively a (ptr, meta) tuple.
tcx.intern_layout(scalar_pair(data_ptr, metadata))
}

// Arrays and slices.
Expand Down Expand Up @@ -1861,32 +1854,25 @@ impl<'a, 'tcx> SizeSkeleton<'tcx> {
Err(err) => err
};

let ptr_skeleton = |pointee: Ty<'tcx>| {
let non_zero = !ty.is_unsafe_ptr();
let tail = tcx.struct_tail(pointee);
match tail.sty {
ty::TyParam(_) | ty::TyProjection(_) => {
assert!(tail.has_param_types() || tail.has_self_ty());
Ok(SizeSkeleton::Pointer {
non_zero,
tail: tcx.erase_regions(&tail)
})
}
_ => {
bug!("SizeSkeleton::compute({}): layout errored ({}), yet \
tail `{}` is not a type parameter or a projection",
ty, err, tail)
}
}
};

match ty.sty {
ty::TyRef(_, ty::TypeAndMut { ty: pointee, .. }) |
ty::TyRawPtr(ty::TypeAndMut { ty: pointee, .. }) => {
ptr_skeleton(pointee)
}
ty::TyAdt(def, _) if def.is_box() => {
ptr_skeleton(ty.boxed_ty())
let non_zero = !ty.is_unsafe_ptr();
let tail = tcx.struct_tail(pointee);
match tail.sty {
ty::TyParam(_) | ty::TyProjection(_) => {
assert!(tail.has_param_types() || tail.has_self_ty());
Ok(SizeSkeleton::Pointer {
non_zero,
tail: tcx.erase_regions(&tail)
})
}
_ => {
bug!("SizeSkeleton::compute({}): layout errored ({}), yet \
tail `{}` is not a type parameter or a projection",
ty, err, tail)
}
}
}

ty::TyAdt(def, substs) => {
Expand Down Expand Up @@ -2148,39 +2134,6 @@ impl<'a, 'tcx> TyLayout<'tcx> {
C::TyLayout: MaybeResult<TyLayout<'tcx>>
{
let tcx = cx.tcx();
let ptr_field_layout = |pointee: Ty<'tcx>| {
assert!(i < 2);

// Reuse the fat *T type as its own thin pointer data field.
// This provides information about e.g. DST struct pointees
// (which may have no non-DST form), and will work as long
// as the `Abi` or `FieldPlacement` is checked by users.
if i == 0 {
let nil = tcx.mk_nil();
let ptr_ty = if self.ty.is_unsafe_ptr() {
tcx.mk_mut_ptr(nil)
} else {
tcx.mk_mut_ref(tcx.types.re_static, nil)
};
return cx.layout_of(ptr_ty).map_same(|mut ptr_layout| {
ptr_layout.ty = self.ty;
ptr_layout
});
}

let meta_ty = match tcx.struct_tail(pointee).sty {
ty::TySlice(_) |
ty::TyStr => tcx.types.usize,
ty::TyDynamic(..) => {
// FIXME(eddyb) use an usize/fn() array with
// the correct number of vtables slots.
tcx.mk_imm_ref(tcx.types.re_static, tcx.mk_nil())
}
_ => bug!("TyLayout::field_type({:?}): not applicable", self)
};
cx.layout_of(meta_ty)
};

cx.layout_of(match self.ty.sty {
ty::TyBool |
ty::TyChar |
Expand All @@ -2198,10 +2151,35 @@ impl<'a, 'tcx> TyLayout<'tcx> {
// Potentially-fat pointers.
ty::TyRef(_, ty::TypeAndMut { ty: pointee, .. }) |
ty::TyRawPtr(ty::TypeAndMut { ty: pointee, .. }) => {
return ptr_field_layout(pointee);
}
ty::TyAdt(def, _) if def.is_box() => {
return ptr_field_layout(self.ty.boxed_ty());
assert!(i < 2);

// Reuse the fat *T type as its own thin pointer data field.
// This provides information about e.g. DST struct pointees
// (which may have no non-DST form), and will work as long
// as the `Abi` or `FieldPlacement` is checked by users.
if i == 0 {
let nil = tcx.mk_nil();
let ptr_ty = if self.ty.is_unsafe_ptr() {
tcx.mk_mut_ptr(nil)
} else {
tcx.mk_mut_ref(tcx.types.re_static, nil)
};
return cx.layout_of(ptr_ty).map_same(|mut ptr_layout| {
ptr_layout.ty = self.ty;
ptr_layout
});
}

match tcx.struct_tail(pointee).sty {
ty::TySlice(_) |
ty::TyStr => tcx.types.usize,
ty::TyDynamic(..) => {
// FIXME(eddyb) use an usize/fn() array with
// the correct number of vtables slots.
tcx.mk_imm_ref(tcx.types.re_static, tcx.mk_nil())
}
_ => bug!("TyLayout::field_type({:?}): not applicable", self)
}
}

// Arrays and slices.
Expand Down
21 changes: 11 additions & 10 deletions src/librustc_trans/type_of.rs
Original file line number Diff line number Diff line change
Expand Up @@ -321,7 +321,8 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyLayout<'tcx> {
return self.field(ccx, index).llvm_type(ccx);
}
ty::TyAdt(def, _) if def.is_box() => {
return self.field(ccx, index).llvm_type(ccx);
let ptr_ty = ccx.tcx().mk_mut_ptr(self.ty.boxed_ty());
return ccx.layout_of(ptr_ty).scalar_pair_element_llvm_type(ccx, index);
}
_ => {}
}
Expand Down Expand Up @@ -438,15 +439,6 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyLayout<'tcx> {
});
}

ty::TyAdt(def, _) if def.is_box() && offset.bytes() == 0 => {
let (size, align) = ccx.size_and_align_of(self.ty.boxed_ty());
result = Some(PointeeInfo {
size,
align,
safe: Some(PointerKind::UniqueOwned)
});
}

_ => {
let mut data_variant = match self.variants {
layout::Variants::NicheFilling { dataful_variant, .. } => {
Expand Down Expand Up @@ -491,6 +483,15 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyLayout<'tcx> {
}
}
}

// FIXME(eddyb) This should be for `ptr::Unique<T>`, not `Box<T>`.
if let Some(ref mut pointee) = result {
if let ty::TyAdt(def, _) = self.ty.sty {
if def.is_box() && offset.bytes() == 0 {
pointee.safe = Some(PointerKind::UniqueOwned);
}
}
}
}
}

Expand Down

0 comments on commit fa67abd

Please sign in to comment.