Skip to content

Commit 2717e1e

Browse files
committed
rustc: don't special-case Box<T> as having a pointer layout.
1 parent b675a00 commit 2717e1e

File tree

3 files changed

+95
-106
lines changed

3 files changed

+95
-106
lines changed

src/liballoc/boxed.rs

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ impl<T> Place<T> for IntermediateBox<T> {
151151
unsafe fn finalize<T>(b: IntermediateBox<T>) -> Box<T> {
152152
let p = b.ptr as *mut T;
153153
mem::forget(b);
154-
mem::transmute(p)
154+
Box::from_raw(p)
155155
}
156156

157157
fn make_place<T>() -> IntermediateBox<T> {
@@ -300,7 +300,10 @@ impl<T: ?Sized> Box<T> {
300300
issue = "27730")]
301301
#[inline]
302302
pub unsafe fn from_unique(u: Unique<T>) -> Self {
303-
mem::transmute(u)
303+
#[cfg(stage0)]
304+
return mem::transmute(u);
305+
#[cfg(not(stage0))]
306+
return Box(u);
304307
}
305308

306309
/// Consumes the `Box`, returning the wrapped raw pointer.
@@ -362,7 +365,14 @@ impl<T: ?Sized> Box<T> {
362365
issue = "27730")]
363366
#[inline]
364367
pub fn into_unique(b: Box<T>) -> Unique<T> {
365-
unsafe { mem::transmute(b) }
368+
#[cfg(stage0)]
369+
return unsafe { mem::transmute(b) };
370+
#[cfg(not(stage0))]
371+
return {
372+
let unique = b.0;
373+
mem::forget(b);
374+
unique
375+
};
366376
}
367377
}
368378

@@ -627,7 +637,7 @@ impl Box<Any + Send> {
627637
pub fn downcast<T: Any>(self) -> Result<Box<T>, Box<Any + Send>> {
628638
<Box<Any>>::downcast(self).map_err(|s| unsafe {
629639
// reapply the Send marker
630-
mem::transmute::<Box<Any>, Box<Any + Send>>(s)
640+
Box::from_raw(Box::into_raw(s) as *mut (Any + Send))
631641
})
632642
}
633643
}

src/librustc/ty/layout.rs

Lines changed: 70 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -1141,34 +1141,6 @@ impl<'a, 'tcx> CachedLayout {
11411141
};
11421142
assert!(!ty.has_infer_types());
11431143

1144-
let ptr_layout = |pointee: Ty<'tcx>| {
1145-
let mut data_ptr = scalar_unit(Pointer);
1146-
if !ty.is_unsafe_ptr() {
1147-
data_ptr.valid_range.start = 1;
1148-
}
1149-
1150-
let pointee = tcx.normalize_associated_type_in_env(&pointee, param_env);
1151-
if pointee.is_sized(tcx, param_env, DUMMY_SP) {
1152-
return Ok(tcx.intern_layout(CachedLayout::scalar(cx, data_ptr)));
1153-
}
1154-
1155-
let unsized_part = tcx.struct_tail(pointee);
1156-
let metadata = match unsized_part.sty {
1157-
ty::TySlice(_) | ty::TyStr => {
1158-
scalar_unit(Int(dl.ptr_sized_integer(), false))
1159-
}
1160-
ty::TyDynamic(..) => {
1161-
let mut vtable = scalar_unit(Pointer);
1162-
vtable.valid_range.start = 1;
1163-
vtable
1164-
}
1165-
_ => return Err(LayoutError::Unknown(unsized_part))
1166-
};
1167-
1168-
// Effectively a (ptr, meta) tuple.
1169-
Ok(tcx.intern_layout(scalar_pair(data_ptr, metadata)))
1170-
};
1171-
11721144
Ok(match ty.sty {
11731145
// Basic scalars.
11741146
ty::TyBool => {
@@ -1205,10 +1177,31 @@ impl<'a, 'tcx> CachedLayout {
12051177
// Potentially-fat pointers.
12061178
ty::TyRef(_, ty::TypeAndMut { ty: pointee, .. }) |
12071179
ty::TyRawPtr(ty::TypeAndMut { ty: pointee, .. }) => {
1208-
ptr_layout(pointee)?
1209-
}
1210-
ty::TyAdt(def, _) if def.is_box() => {
1211-
ptr_layout(ty.boxed_ty())?
1180+
let mut data_ptr = scalar_unit(Pointer);
1181+
if !ty.is_unsafe_ptr() {
1182+
data_ptr.valid_range.start = 1;
1183+
}
1184+
1185+
let pointee = tcx.normalize_associated_type_in_env(&pointee, param_env);
1186+
if pointee.is_sized(tcx, param_env, DUMMY_SP) {
1187+
return Ok(tcx.intern_layout(CachedLayout::scalar(cx, data_ptr)));
1188+
}
1189+
1190+
let unsized_part = tcx.struct_tail(pointee);
1191+
let metadata = match unsized_part.sty {
1192+
ty::TySlice(_) | ty::TyStr => {
1193+
scalar_unit(Int(dl.ptr_sized_integer(), false))
1194+
}
1195+
ty::TyDynamic(..) => {
1196+
let mut vtable = scalar_unit(Pointer);
1197+
vtable.valid_range.start = 1;
1198+
vtable
1199+
}
1200+
_ => return Err(LayoutError::Unknown(unsized_part))
1201+
};
1202+
1203+
// Effectively a (ptr, meta) tuple.
1204+
tcx.intern_layout(scalar_pair(data_ptr, metadata))
12121205
}
12131206

12141207
// Arrays and slices.
@@ -1834,32 +1827,25 @@ impl<'a, 'tcx> SizeSkeleton<'tcx> {
18341827
Err(err) => err
18351828
};
18361829

1837-
let ptr_skeleton = |pointee: Ty<'tcx>| {
1838-
let non_zero = !ty.is_unsafe_ptr();
1839-
let tail = tcx.struct_tail(pointee);
1840-
match tail.sty {
1841-
ty::TyParam(_) | ty::TyProjection(_) => {
1842-
assert!(tail.has_param_types() || tail.has_self_ty());
1843-
Ok(SizeSkeleton::Pointer {
1844-
non_zero,
1845-
tail: tcx.erase_regions(&tail)
1846-
})
1847-
}
1848-
_ => {
1849-
bug!("SizeSkeleton::compute({}): layout errored ({}), yet \
1850-
tail `{}` is not a type parameter or a projection",
1851-
ty, err, tail)
1852-
}
1853-
}
1854-
};
1855-
18561830
match ty.sty {
18571831
ty::TyRef(_, ty::TypeAndMut { ty: pointee, .. }) |
18581832
ty::TyRawPtr(ty::TypeAndMut { ty: pointee, .. }) => {
1859-
ptr_skeleton(pointee)
1860-
}
1861-
ty::TyAdt(def, _) if def.is_box() => {
1862-
ptr_skeleton(ty.boxed_ty())
1833+
let non_zero = !ty.is_unsafe_ptr();
1834+
let tail = tcx.struct_tail(pointee);
1835+
match tail.sty {
1836+
ty::TyParam(_) | ty::TyProjection(_) => {
1837+
assert!(tail.has_param_types() || tail.has_self_ty());
1838+
Ok(SizeSkeleton::Pointer {
1839+
non_zero,
1840+
tail: tcx.erase_regions(&tail)
1841+
})
1842+
}
1843+
_ => {
1844+
bug!("SizeSkeleton::compute({}): layout errored ({}), yet \
1845+
tail `{}` is not a type parameter or a projection",
1846+
ty, err, tail)
1847+
}
1848+
}
18631849
}
18641850

18651851
ty::TyAdt(def, substs) => {
@@ -2116,39 +2102,6 @@ impl<'a, 'tcx> TyLayout<'tcx> {
21162102
C::TyLayout: MaybeResult<TyLayout<'tcx>>
21172103
{
21182104
let tcx = cx.tcx();
2119-
let ptr_field_layout = |pointee: Ty<'tcx>| {
2120-
assert!(i < 2);
2121-
2122-
// Reuse the fat *T type as its own thin pointer data field.
2123-
// This provides information about e.g. DST struct pointees
2124-
// (which may have no non-DST form), and will work as long
2125-
// as the `Abi` or `FieldPlacement` is checked by users.
2126-
if i == 0 {
2127-
let nil = tcx.mk_nil();
2128-
let ptr_ty = if self.ty.is_unsafe_ptr() {
2129-
tcx.mk_mut_ptr(nil)
2130-
} else {
2131-
tcx.mk_mut_ref(tcx.types.re_static, nil)
2132-
};
2133-
return cx.layout_of(ptr_ty).map_same(|mut ptr_layout| {
2134-
ptr_layout.ty = self.ty;
2135-
ptr_layout
2136-
});
2137-
}
2138-
2139-
let meta_ty = match tcx.struct_tail(pointee).sty {
2140-
ty::TySlice(_) |
2141-
ty::TyStr => tcx.types.usize,
2142-
ty::TyDynamic(..) => {
2143-
// FIXME(eddyb) use an usize/fn() array with
2144-
// the correct number of vtables slots.
2145-
tcx.mk_imm_ref(tcx.types.re_static, tcx.mk_nil())
2146-
}
2147-
_ => bug!("TyLayout::field_type({:?}): not applicable", self)
2148-
};
2149-
cx.layout_of(meta_ty)
2150-
};
2151-
21522105
cx.layout_of(match self.ty.sty {
21532106
ty::TyBool |
21542107
ty::TyChar |
@@ -2165,10 +2118,35 @@ impl<'a, 'tcx> TyLayout<'tcx> {
21652118
// Potentially-fat pointers.
21662119
ty::TyRef(_, ty::TypeAndMut { ty: pointee, .. }) |
21672120
ty::TyRawPtr(ty::TypeAndMut { ty: pointee, .. }) => {
2168-
return ptr_field_layout(pointee);
2169-
}
2170-
ty::TyAdt(def, _) if def.is_box() => {
2171-
return ptr_field_layout(self.ty.boxed_ty());
2121+
assert!(i < 2);
2122+
2123+
// Reuse the fat *T type as its own thin pointer data field.
2124+
// This provides information about e.g. DST struct pointees
2125+
// (which may have no non-DST form), and will work as long
2126+
// as the `Abi` or `FieldPlacement` is checked by users.
2127+
if i == 0 {
2128+
let nil = tcx.mk_nil();
2129+
let ptr_ty = if self.ty.is_unsafe_ptr() {
2130+
tcx.mk_mut_ptr(nil)
2131+
} else {
2132+
tcx.mk_mut_ref(tcx.types.re_static, nil)
2133+
};
2134+
return cx.layout_of(ptr_ty).map_same(|mut ptr_layout| {
2135+
ptr_layout.ty = self.ty;
2136+
ptr_layout
2137+
});
2138+
}
2139+
2140+
match tcx.struct_tail(pointee).sty {
2141+
ty::TySlice(_) |
2142+
ty::TyStr => tcx.types.usize,
2143+
ty::TyDynamic(..) => {
2144+
// FIXME(eddyb) use an usize/fn() array with
2145+
// the correct number of vtables slots.
2146+
tcx.mk_imm_ref(tcx.types.re_static, tcx.mk_nil())
2147+
}
2148+
_ => bug!("TyLayout::field_type({:?}): not applicable", self)
2149+
}
21722150
}
21732151

21742152
// Arrays and slices.

src/librustc_trans/type_of.rs

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -321,7 +321,8 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyLayout<'tcx> {
321321
return self.field(ccx, index).llvm_type(ccx);
322322
}
323323
ty::TyAdt(def, _) if def.is_box() => {
324-
return self.field(ccx, index).llvm_type(ccx);
324+
let ptr_ty = ccx.tcx().mk_mut_ptr(self.ty.boxed_ty());
325+
return ccx.layout_of(ptr_ty).scalar_pair_element_llvm_type(ccx, index);
325326
}
326327
_ => {}
327328
}
@@ -428,15 +429,6 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyLayout<'tcx> {
428429
});
429430
}
430431

431-
ty::TyAdt(def, _) if def.is_box() && offset.bytes() == 0 => {
432-
let (size, align) = ccx.size_and_align_of(self.ty.boxed_ty());
433-
result = Some(LlvmPointee {
434-
size,
435-
align,
436-
safe: Some(PointerKind::UniqueOwned)
437-
});
438-
}
439-
440432
_ => {
441433
let mut data_variant = match self.variants {
442434
layout::Variants::NicheFilling { dataful_variant, .. } => {
@@ -466,6 +458,15 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyLayout<'tcx> {
466458
}
467459
}
468460
}
461+
462+
// FIXME(eddyb) This should be for `ptr::Unique<T>`, not `Box<T>`.
463+
if let Some(ref mut pointee) = result {
464+
if let ty::TyAdt(def, _) = self.ty.sty {
465+
if def.is_box() && offset.bytes() == 0 {
466+
pointee.safe = Some(PointerKind::UniqueOwned);
467+
}
468+
}
469+
}
469470
}
470471
}
471472

0 commit comments

Comments
 (0)