Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 565dce2

Browse files
authoredMay 29, 2024
Rollup merge of rust-lang#124251 - scottmcm:unop-ptr-metadata, r=oli-obk
Add an intrinsic for `ptr::metadata` The follow-up to rust-lang#123840, so we can remove `PtrComponents` and `PtrRepr` from libcore entirely (well, after a bootstrap update). As discussed in <https://rust-lang.zulipchat.com/#narrow/stream/189540-t-compiler.2Fwg-mir-opt/topic/.60ptr_metadata.60.20in.20MIR/near/435637808>, this introduces `UnOp::PtrMetadata` taking a raw pointer and returning the associated metadata value. By no longer going through a `union`, this should also help future PRs better optimize pointer operations. r? ``@oli-obk``
2 parents 914d2c0 + a4025eb commit 565dce2

File tree

4 files changed

+48
-4
lines changed

4 files changed

+48
-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/intrinsics/mir.rs

+4
Original file line numberDiff line numberDiff line change
@@ -360,6 +360,10 @@ define!("mir_assume", fn Assume(operand: bool));
360360
define!("mir_deinit", fn Deinit<T>(place: T));
361361
define!("mir_checked", fn Checked<T>(binop: T) -> (T, bool));
362362
define!("mir_len", fn Len<T>(place: T) -> usize);
363+
define!(
364+
"mir_ptr_metadata",
365+
fn PtrMetadata<P: ?Sized>(place: *const P) -> <P as ::core::ptr::Pointee>::Metadata
366+
);
363367
define!("mir_copy_for_deref", fn CopyForDeref<T>(place: T) -> T);
364368
define!("mir_retag", fn Retag<T>(place: T));
365369
define!("mir_move", fn Move<T>(place: T) -> T);

‎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)
Failed to load comments.