diff options
| author | Michael Goulet <michael@errs.io> | 2022-11-12 23:54:39 +0000 |
|---|---|---|
| committer | Michael Goulet <michael@errs.io> | 2023-01-04 00:56:05 +0000 |
| commit | b25da9ce6dd28d13c85911e0630d019403b7f5f3 (patch) | |
| tree | 4b52425698e3d4667415153eab332b27db540012 | |
| parent | c7572670a1302f5c7e245d069200e22da9df0316 (diff) | |
| download | rust-b25da9ce6dd28d13c85911e0630d019403b7f5f3.tar.gz rust-b25da9ce6dd28d13c85911e0630d019403b7f5f3.zip | |
layout_of: `T: Thin` implies `sizeof(&T) == sizeof(usize)`
| -rw-r--r-- | compiler/rustc_ty_utils/src/layout.rs | 36 | ||||
| -rw-r--r-- | src/test/ui/layout/thin-meta-implies-thin-ptr.rs | 11 |
2 files changed, 39 insertions, 8 deletions
diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs index c8c6acaa453..6aa016133ca 100644 --- a/compiler/rustc_ty_utils/src/layout.rs +++ b/compiler/rustc_ty_utils/src/layout.rs @@ -155,17 +155,37 @@ fn layout_of_uncached<'tcx>( } let unsized_part = tcx.struct_tail_erasing_lifetimes(pointee, param_env); - let metadata = match unsized_part.kind() { - ty::Foreign(..) => { + + let metadata = if let Some(metadata_def_id) = tcx.lang_items().metadata_type() { + let metadata_ty = tcx.normalize_erasing_regions( + param_env, + tcx.mk_projection(metadata_def_id, [pointee]), + ); + let metadata_layout = cx.layout_of(metadata_ty)?; + // If the metadata is a 1-zst, then the pointer is thin. + if metadata_layout.is_zst() && metadata_layout.align.abi.bytes() == 1 { return Ok(tcx.intern_layout(LayoutS::scalar(cx, data_ptr))); } - ty::Slice(_) | ty::Str => scalar_unit(Int(dl.ptr_sized_integer(), false)), - ty::Dynamic(..) => { - let mut vtable = scalar_unit(Pointer); - vtable.valid_range_mut().start = 1; - vtable + + let Abi::Scalar(metadata) = metadata_layout.abi else { + return Err(LayoutError::Unknown(unsized_part)); + }; + metadata + } else { + match unsized_part.kind() { + ty::Foreign(..) => { + return Ok(tcx.intern_layout(LayoutS::scalar(cx, data_ptr))); + } + ty::Slice(_) | ty::Str => scalar_unit(Int(dl.ptr_sized_integer(), false)), + ty::Dynamic(..) => { + let mut vtable = scalar_unit(Pointer); + vtable.valid_range_mut().start = 1; + vtable + } + _ => { + return Err(LayoutError::Unknown(unsized_part)); + } } - _ => return Err(LayoutError::Unknown(unsized_part)), }; // Effectively a (ptr, meta) tuple. diff --git a/src/test/ui/layout/thin-meta-implies-thin-ptr.rs b/src/test/ui/layout/thin-meta-implies-thin-ptr.rs new file mode 100644 index 00000000000..972579ea8be --- /dev/null +++ b/src/test/ui/layout/thin-meta-implies-thin-ptr.rs @@ -0,0 +1,11 @@ +// check-pass + +#![feature(ptr_metadata)] + +use std::ptr::Thin; + +fn main() {} + +fn foo<T: ?Sized + Thin>(t: *const T) -> *const () { + unsafe { std::mem::transmute(t) } +} |
