rustc: don't special-case Box<T> as having a pointer layout.
This commit is contained in:
parent
18ecc564f2
commit
fa67abd127
3 changed files with 98 additions and 109 deletions
|
@ -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> {
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 => {
|
||||
|
@ -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.
|
||||
|
@ -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) => {
|
||||
|
@ -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 |
|
||||
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
@ -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, .. } => {
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue