Skip to content

Commit 87b9f24

Browse files
committed
Add an intrinsic for ptr::metadata
1 parent 6fcf130 commit 87b9f24

File tree

3 files changed

+44
-4
lines changed

3 files changed

+44
-4
lines changed

core/src/intrinsics.rs

+15
Original file line numberDiff line numberDiff line change
@@ -2821,6 +2821,21 @@ impl<P: ?Sized, T: ptr::Thin> AggregateRawPtr<*mut T> for *mut P {
28212821
type Metadata = <P as ptr::Pointee>::Metadata;
28222822
}
28232823

2824+
/// Lowers in MIR to `Rvalue::UnaryOp` with `UnOp::PtrMetadata`.
2825+
///
2826+
/// This is used to implement functions like `ptr::metadata`.
2827+
#[rustc_nounwind]
2828+
#[unstable(feature = "core_intrinsics", issue = "none")]
2829+
#[rustc_const_unstable(feature = "ptr_metadata", issue = "81513")]
2830+
#[rustc_intrinsic]
2831+
#[rustc_intrinsic_must_be_overridden]
2832+
#[cfg(not(bootstrap))]
2833+
pub const fn ptr_metadata<P: ptr::Pointee<Metadata = M> + ?Sized, M>(_ptr: *const P) -> M {
2834+
// To implement a fallback we'd have to assume the layout of the pointer,
2835+
// but the whole point of this intrinsic is that we shouldn't do that.
2836+
unreachable!()
2837+
}
2838+
28242839
// Some functions are defined here because they accidentally got made
28252840
// available in this module on stable. See <https://github.com/rust-lang/rust/issues/15702>.
28262841
// (`transmute` also falls into this category, but it cannot be wrapped due to the

core/src/ptr/metadata.rs

+17-4
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
use crate::fmt;
44
use crate::hash::{Hash, Hasher};
55
use crate::intrinsics::aggregate_raw_ptr;
6+
#[cfg(not(bootstrap))]
7+
use crate::intrinsics::ptr_metadata;
68
use crate::marker::Freeze;
79

810
/// Provides the pointer metadata type of any pointed-to type.
@@ -94,10 +96,17 @@ pub trait Thin = Pointee<Metadata = ()>;
9496
#[rustc_const_unstable(feature = "ptr_metadata", issue = "81513")]
9597
#[inline]
9698
pub const fn metadata<T: ?Sized>(ptr: *const T) -> <T as Pointee>::Metadata {
97-
// SAFETY: Accessing the value from the `PtrRepr` union is safe since *const T
98-
// and PtrComponents<T> have the same memory layouts. Only std can make this
99-
// guarantee.
100-
unsafe { PtrRepr { const_ptr: ptr }.components.metadata }
99+
#[cfg(bootstrap)]
100+
{
101+
// SAFETY: Accessing the value from the `PtrRepr` union is safe since *const T
102+
// and PtrComponents<T> have the same memory layouts. Only std can make this
103+
// guarantee.
104+
unsafe { PtrRepr { const_ptr: ptr }.components.metadata }
105+
}
106+
#[cfg(not(bootstrap))]
107+
{
108+
ptr_metadata(ptr)
109+
}
101110
}
102111

103112
/// Forms a (possibly-wide) raw pointer from a data pointer and metadata.
@@ -132,22 +141,26 @@ pub const fn from_raw_parts_mut<T: ?Sized>(
132141
}
133142

134143
#[repr(C)]
144+
#[cfg(bootstrap)]
135145
union PtrRepr<T: ?Sized> {
136146
const_ptr: *const T,
137147
mut_ptr: *mut T,
138148
components: PtrComponents<T>,
139149
}
140150

141151
#[repr(C)]
152+
#[cfg(bootstrap)]
142153
struct PtrComponents<T: ?Sized> {
143154
data_pointer: *const (),
144155
metadata: <T as Pointee>::Metadata,
145156
}
146157

147158
// Manual impl needed to avoid `T: Copy` bound.
159+
#[cfg(bootstrap)]
148160
impl<T: ?Sized> Copy for PtrComponents<T> {}
149161

150162
// Manual impl needed to avoid `T: Clone` bound.
163+
#[cfg(bootstrap)]
151164
impl<T: ?Sized> Clone for PtrComponents<T> {
152165
fn clone(&self) -> Self {
153166
*self

core/tests/ptr.rs

+12
Original file line numberDiff line numberDiff line change
@@ -1171,3 +1171,15 @@ fn test_ptr_from_raw_parts_in_const() {
11711171
assert_eq!(EMPTY_SLICE_PTR.addr(), 123);
11721172
assert_eq!(EMPTY_SLICE_PTR.len(), 456);
11731173
}
1174+
1175+
#[test]
1176+
fn test_ptr_metadata_in_const() {
1177+
use std::fmt::Debug;
1178+
1179+
const ARRAY_META: () = std::ptr::metadata::<[u16; 3]>(&[1, 2, 3]);
1180+
const SLICE_META: usize = std::ptr::metadata::<[u16]>(&[1, 2, 3]);
1181+
const DYN_META: DynMetadata<dyn Debug> = std::ptr::metadata::<dyn Debug>(&[0_u8; 42]);
1182+
assert_eq!(ARRAY_META, ());
1183+
assert_eq!(SLICE_META, 3);
1184+
assert_eq!(DYN_META.size_of(), 42);
1185+
}

0 commit comments

Comments
 (0)