{
  "$type": "site.standard.document",
  "bskyPostRef": {
    "cid": "bafyreibuoi6fg7xvr35rpe5gh2vuzrx3esfrbaz42ztrdmrm7sfn3tjbnm",
    "uri": "at://did:plc:ivbknywyskln22er3nkssdhl/app.bsky.feed.post/3ml5cbwsun3b2"
  },
  "path": "/t/std-phantomunsized-marker-type/24219#post_5",
  "publishedAt": "2026-05-05T21:26:00.000Z",
  "site": "https://internals.rust-lang.org",
  "textContent": "As an extension, `PhantomUnsized` could gain a type parameter specifying the pointer metadata. The type must be `Copy` and have the same layout as `usize` (for now, assuming the compiler can't take types larger/smaller than `usize`).\n\nFor example you could define your own 2D plane type:\n\n\n    // NOTE: This would not be compatible with the current `usize` restriction.\n    // However, I'm assuming this restriction would exist because the compiler\n    // assumes pointer metadata has the same layout as a pointer.\n    #[derive(Copy)]\n    struct PlaneMeta {\n      width: u32,\n      height: u32,\n    }\n\n    struct Plane<T> {\n      // Stride is stored in the Plane header because it is the same across all\n      // pointers/references.\n      stride: u32,\n      // :)\n      _align_hack: [T; 0],\n      _phantom: PhantomData<T>,\n      _unsized: PhantomUnsized<PlaneMeta>,\n    }\n\n    // `&Plane<u8>` now works as a 2D slice. This can also be extended to any\n    // number of dimensions.\n\n\nLibraries could opt in to `MetaSized` with a new trait `PointerLayout` (probably under `std::ops`).\n\n**NOTE** : I'm not sure if this should be implemented on the pointer metadata or the pointee.\n\n**NOTE 2** : `size_of_val_raw` may not interact with this well as `PointerLayout` implementations can assume their pointers are dereferenceable. However the docs say that \"this function is only safe to call\" if the metadata is from a slice or trait object. _For now_ I've added a const generic arg specifying whether the call is from `*_of_val` (using references) or `*_of_val_raw` (using ptrs).\n\nin `main/library/core/src/ops/mod.rs`:\n\n\n    pub trait std::ops::PointerLayout<T: Pointee<Metadata = Self>> {\n      unsafe fn layout_of<const RAW: bool>(ptr: *const T) -> Layout;\n    }\n\n\n\n    // This implementation makes `Plane<T>` `MetaSized`.\n    impl<T> std::ops::PointerLayout<Plane<T>> for PlaneMeta {\n      unsafe fn layout_of<const RAW: bool>(ptr: *const Plane<T>) -> Layout {\n        // Panicking is free because of the const generic, but implementations do not\n        // have to panic because `*_of_val_raw` is allowed to invoke UB.\n        if RAW {\n          panic!(\"plane ptrs are not supported: pointer must be deref to compute\");\n        }\n        let stride = unsafe { (&raw const (*ptr).stride).read() };\n        let meta = std::ptr::metadata(ptr);\n        // It is undefined behavior to construct invalid planes with sizes that\n        // overflow `usize` so we are allowed to invoke UB \"for speed\".\n        let trailing_len = (stride as usize).unchecked_mul(meta.height as usize);\n        unsafe {\n          try {\n            Layout::new_minimum::<Plane<T>>()\n              .extend(Layout::new::<T>().repeat(trailing_len)?)?.0\n           }\n          .unwrap_unchecked()\n        }\n      }\n    }\n\n\nThis would then allow for creating boxed planes (with some unsafe code):\n\n\n    pub fn new_boxed(width: u32, height: u32, item: T) -> Box<Self>\n      where T: Copy\n    {\n      let Some(trailing_len) = (width as usize).checked_mul(height as usize) else {\n        panic!(\"plane is too large to allocate ({width}x{height})\")\n      };\n      let offset;\n      let Ok(layout) = try {\n        let layout;\n        (layout, offset) = Layout::new_minimum::<Plane<T>>()\n          .extend(Layout::new::<T>().repeat(trailing_len)?)?;\n        layout.pad_to_align()?\n      } else {\n        panic!(\"plane is too large to allocate ({width}x{height})\")\n      };\n\n      // Assume `Box::new_uninit_unsized_layout` exists (I wish it did :( )\n      let mut this = Box::new_uninit_unsized_layout::<Self>(\n        layout,\n        // Metadata needs to be passed when creating unsized types.\n        // Alternatively this could always return `Box<[MaybeUninit<u8>]>`.\n        PlaneMeta { width, height }\n      );\n      unsafe {\n        (&raw mut (*this.as_ptr()).stride).write(width);\n      }\n      let items = unsafe {\n        std::slice::slice_from_raw_parts_mut(\n          this.as_ptr()\n            .byte_add(offset)\n            .cast::<MaybeUninit<T>>(),\n          trailing_len,\n        )\n      };\n      items.fill(MaybeUninit::new(item));\n      this.assume_init()\n    }\n\n\nI've omitted the `Drop` impl for `Plane`. It is trivial to write (it just drops all elements in place).",
  "title": "`std::marker::PhantomUnsized` marker type"
}