Rollup merge of #124251 - scottmcm:unop-ptr-metadata, r=oli-obk · model-checking/verify-rust-std@565dce2 (original) (raw)
4 files changed
lines changed
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -2821,6 +2821,21 @@ impl<P: ?Sized, T: ptr::Thin> AggregateRawPtr<*mut T> for *mut P { | ||
2821 | 2821 | type Metadata = <P as ptr::Pointee>::Metadata; |
2822 | 2822 | } |
2823 | 2823 | |
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 | + | |
2824 | 2839 | // Some functions are defined here because they accidentally got made |
2825 | 2840 | // available in this module on stable. See https://github.com/rust-lang/rust/issues/15702. |
2826 | 2841 | // (`transmute` also falls into this category, but it cannot be wrapped due to the |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -360,6 +360,10 @@ define!("mir_assume", fn Assume(operand: bool)); | ||
360 | 360 | define!("mir_deinit", fn Deinit<T>(place: T)); |
361 | 361 | define!("mir_checked", fn Checked<T>(binop: T) -> (T, bool)); |
362 | 362 | 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 | +); | |
363 | 367 | define!("mir_copy_for_deref", fn CopyForDeref<T>(place: T) -> T); |
364 | 368 | define!("mir_retag", fn Retag<T>(place: T)); |
365 | 369 | define!("mir_move", fn Move<T>(place: T) -> T); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -3,6 +3,8 @@ | ||
3 | 3 | use crate::fmt; |
4 | 4 | use crate::hash::{Hash, Hasher}; |
5 | 5 | use crate::intrinsics::aggregate_raw_ptr; |
6 | +#[cfg(not(bootstrap))] | |
7 | +use crate::intrinsics::ptr_metadata; | |
6 | 8 | use crate:📑:Freeze; |
7 | 9 | |
8 | 10 | /// Provides the pointer metadata type of any pointed-to type. |
@@ -94,10 +96,17 @@ pub trait Thin = Pointee<Metadata = ()>; | ||
94 | 96 | #[rustc_const_unstable(feature = "ptr_metadata", issue = "81513")] |
95 | 97 | #[inline] |
96 | 98 | 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 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 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 | +} | |
101 | 110 | } |
102 | 111 | |
103 | 112 | /// 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>( | ||
132 | 141 | } |
133 | 142 | |
134 | 143 | #[repr(C)] |
144 | +#[cfg(bootstrap)] | |
135 | 145 | union PtrRepr<T: ?Sized> { |
136 | 146 | const_ptr: *const T, |
137 | 147 | mut_ptr: *mut T, |
138 | 148 | components: PtrComponents<T>, |
139 | 149 | } |
140 | 150 | |
141 | 151 | #[repr(C)] |
152 | +#[cfg(bootstrap)] | |
142 | 153 | struct PtrComponents<T: ?Sized> { |
143 | 154 | data_pointer: *const (), |
144 | 155 | metadata: <T as Pointee>::Metadata, |
145 | 156 | } |
146 | 157 | |
147 | 158 | // Manual impl needed to avoid `T: Copy` bound. |
159 | +#[cfg(bootstrap)] | |
148 | 160 | impl<T: ?Sized> Copy for PtrComponents<T> {} |
149 | 161 | |
150 | 162 | // Manual impl needed to avoid `T: Clone` bound. |
163 | +#[cfg(bootstrap)] | |
151 | 164 | impl<T: ?Sized> Clone for PtrComponents<T> { |
152 | 165 | fn clone(&self) -> Self { |
153 | 166 | *self |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1171,3 +1171,15 @@ fn test_ptr_from_raw_parts_in_const() { | ||
1171 | 1171 | assert_eq!(EMPTY_SLICE_PTR.addr(), 123); |
1172 | 1172 | assert_eq!(EMPTY_SLICE_PTR.len(), 456); |
1173 | 1173 | } |
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 | +} |