about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMichael Goulet <michael@errs.io>2022-11-12 23:54:39 +0000
committerMichael Goulet <michael@errs.io>2023-01-04 00:56:05 +0000
commitb25da9ce6dd28d13c85911e0630d019403b7f5f3 (patch)
tree4b52425698e3d4667415153eab332b27db540012
parentc7572670a1302f5c7e245d069200e22da9df0316 (diff)
downloadrust-b25da9ce6dd28d13c85911e0630d019403b7f5f3.tar.gz
rust-b25da9ce6dd28d13c85911e0630d019403b7f5f3.zip
layout_of: `T: Thin` implies `sizeof(&T) == sizeof(usize)`
-rw-r--r--compiler/rustc_ty_utils/src/layout.rs36
-rw-r--r--src/test/ui/layout/thin-meta-implies-thin-ptr.rs11
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) }
+}