facet_core/impls/core/
pointer.rs1use core::cmp::Ordering;
4use core::hash::Hash;
5
6use crate::{
7 Def, Facet, HashProxy, OxPtrConst, OxPtrMut, PointerType, Shape, ShapeBuilder, Type,
8 TypeOpsIndirect, TypeParam, VTableIndirect, ValuePointerType, VarianceDesc,
9};
10
11unsafe fn const_ptr_debug<T: ?Sized>(
16 ox: OxPtrConst,
17 f: &mut core::fmt::Formatter<'_>,
18) -> Option<core::fmt::Result> {
19 let p = unsafe { ox.ptr().get::<*const T>() };
20 Some(core::fmt::Debug::fmt(&p, f))
21}
22
23unsafe fn const_ptr_hash<T: ?Sized>(ox: OxPtrConst, hasher: &mut HashProxy<'_>) -> Option<()> {
25 let p = unsafe { ox.ptr().get::<*const T>() };
26 p.hash(hasher);
27 Some(())
28}
29
30#[allow(ambiguous_wide_pointer_comparisons)]
32unsafe fn const_ptr_partial_eq<T: ?Sized>(a: OxPtrConst, b: OxPtrConst) -> Option<bool> {
33 let a_val = unsafe { a.ptr().get::<*const T>() };
34 let b_val = unsafe { b.ptr().get::<*const T>() };
35 Some(*a_val == *b_val)
36}
37
38#[allow(ambiguous_wide_pointer_comparisons)]
40unsafe fn const_ptr_partial_cmp<T: ?Sized>(
41 a: OxPtrConst,
42 b: OxPtrConst,
43) -> Option<Option<Ordering>> {
44 let a_val = unsafe { a.ptr().get::<*const T>() };
45 let b_val = unsafe { b.ptr().get::<*const T>() };
46 Some(a_val.partial_cmp(b_val))
47}
48
49#[allow(ambiguous_wide_pointer_comparisons)]
51unsafe fn const_ptr_cmp<T: ?Sized>(a: OxPtrConst, b: OxPtrConst) -> Option<Ordering> {
52 let a_val = unsafe { a.ptr().get::<*const T>() };
53 let b_val = unsafe { b.ptr().get::<*const T>() };
54 Some(a_val.cmp(b_val))
55}
56
57const unsafe fn const_ptr_drop<T: ?Sized>(_ptr: OxPtrMut) {
59 }
61
62unsafe fn const_ptr_clone<T: ?Sized>(src: OxPtrConst, dst: OxPtrMut) {
64 let src_val = unsafe { src.ptr().get::<*const T>() };
65 let dst_ptr = unsafe { dst.ptr().as_mut::<*const T>() };
66 *dst_ptr = *src_val;
67}
68
69unsafe fn mut_ptr_debug<T: ?Sized>(
71 ox: OxPtrConst,
72 f: &mut core::fmt::Formatter<'_>,
73) -> Option<core::fmt::Result> {
74 let p = unsafe { ox.ptr().get::<*mut T>() };
75 Some(core::fmt::Debug::fmt(&p, f))
76}
77
78unsafe fn mut_ptr_hash<T: ?Sized>(ox: OxPtrConst, hasher: &mut HashProxy<'_>) -> Option<()> {
80 let p = unsafe { ox.ptr().get::<*mut T>() };
81 p.hash(hasher);
82 Some(())
83}
84
85#[allow(ambiguous_wide_pointer_comparisons)]
87unsafe fn mut_ptr_partial_eq<T: ?Sized>(a: OxPtrConst, b: OxPtrConst) -> Option<bool> {
88 let a_val = unsafe { a.ptr().get::<*mut T>() };
89 let b_val = unsafe { b.ptr().get::<*mut T>() };
90 Some(*a_val == *b_val)
91}
92
93#[allow(ambiguous_wide_pointer_comparisons)]
95unsafe fn mut_ptr_partial_cmp<T: ?Sized>(a: OxPtrConst, b: OxPtrConst) -> Option<Option<Ordering>> {
96 let a_val = unsafe { a.ptr().get::<*mut T>() };
97 let b_val = unsafe { b.ptr().get::<*mut T>() };
98 Some(a_val.partial_cmp(b_val))
99}
100
101#[allow(ambiguous_wide_pointer_comparisons)]
103unsafe fn mut_ptr_cmp<T: ?Sized>(a: OxPtrConst, b: OxPtrConst) -> Option<Ordering> {
104 let a_val = unsafe { a.ptr().get::<*mut T>() };
105 let b_val = unsafe { b.ptr().get::<*mut T>() };
106 Some(a_val.cmp(b_val))
107}
108
109const unsafe fn mut_ptr_drop<T: ?Sized>(_ptr: OxPtrMut) {
111 }
113
114unsafe fn mut_ptr_clone<T: ?Sized>(src: OxPtrConst, dst: OxPtrMut) {
116 let src_val = unsafe { src.ptr().get::<*mut T>() };
117 let dst_ptr = unsafe { dst.ptr().as_mut::<*mut T>() };
118 *dst_ptr = *src_val;
119}
120
121unsafe impl<'a, T: Facet<'a> + ?Sized> Facet<'a> for *const T {
123 const SHAPE: &'static Shape = &const {
124 const fn build_const_ptr_vtable<'a, T: Facet<'a> + ?Sized>() -> VTableIndirect {
125 VTableIndirect {
126 display: None,
127 debug: Some(const_ptr_debug::<T>),
128 hash: Some(const_ptr_hash::<T>),
129 invariants: None,
130 parse: None,
131 parse_bytes: None,
132 try_from: None,
133 try_into_inner: None,
134 try_borrow_inner: None,
135 partial_eq: Some(const_ptr_partial_eq::<T>),
136 partial_cmp: Some(const_ptr_partial_cmp::<T>),
137 cmp: Some(const_ptr_cmp::<T>),
138 }
139 }
140
141 const fn build_const_ptr_type_ops<T: ?Sized>() -> TypeOpsIndirect {
142 TypeOpsIndirect {
143 drop_in_place: const_ptr_drop::<T>,
144 default_in_place: None,
145 clone_into: Some(const_ptr_clone::<T>),
146 is_truthy: None,
147 }
148 }
149
150 ShapeBuilder::for_sized::<*const T>("*const T")
151 .decl_id(crate::DeclId::new(crate::decl_id_hash("#ptr#*const T")))
152 .ty({
153 let is_wide = ::core::mem::size_of::<Self>() != ::core::mem::size_of::<*const ()>();
154 let vpt = ValuePointerType {
155 mutable: false,
156 wide: is_wide,
157 target: T::SHAPE,
158 };
159 Type::Pointer(PointerType::Raw(vpt))
160 })
161 .def(Def::Scalar)
162 .type_params(&[TypeParam {
163 name: "T",
164 shape: T::SHAPE,
165 }])
166 .inner(T::SHAPE)
167 .vtable_indirect(&const { build_const_ptr_vtable::<T>() })
168 .type_ops_indirect(&const { build_const_ptr_type_ops::<T>() })
169 .eq()
170 .copy()
171 .build()
172 };
173}
174
175unsafe impl<'a, T: Facet<'a> + ?Sized> Facet<'a> for *mut T {
177 const SHAPE: &'static Shape = &const {
178 const fn build_mut_ptr_vtable<'a, T: Facet<'a> + ?Sized>() -> VTableIndirect {
179 VTableIndirect {
180 display: None,
181 debug: Some(mut_ptr_debug::<T>),
182 hash: Some(mut_ptr_hash::<T>),
183 invariants: None,
184 parse: None,
185 parse_bytes: None,
186 try_from: None,
187 try_into_inner: None,
188 try_borrow_inner: None,
189 partial_eq: Some(mut_ptr_partial_eq::<T>),
190 partial_cmp: Some(mut_ptr_partial_cmp::<T>),
191 cmp: Some(mut_ptr_cmp::<T>),
192 }
193 }
194
195 const fn build_mut_ptr_type_ops<T: ?Sized>() -> TypeOpsIndirect {
196 TypeOpsIndirect {
197 drop_in_place: mut_ptr_drop::<T>,
198 default_in_place: None,
199 clone_into: Some(mut_ptr_clone::<T>),
200 is_truthy: None,
201 }
202 }
203
204 ShapeBuilder::for_sized::<*mut T>("*mut T")
205 .decl_id(crate::DeclId::new(crate::decl_id_hash("#ptr#*mut T")))
206 .ty({
207 let is_wide = ::core::mem::size_of::<Self>() != ::core::mem::size_of::<*const ()>();
208 let vpt = ValuePointerType {
209 mutable: true,
210 wide: is_wide,
211 target: T::SHAPE,
212 };
213 Type::Pointer(PointerType::Raw(vpt))
214 })
215 .def(Def::Scalar)
216 .type_params(&[TypeParam {
217 name: "T",
218 shape: T::SHAPE,
219 }])
220 .inner(T::SHAPE)
221 .vtable_indirect(&const { build_mut_ptr_vtable::<T>() })
222 .type_ops_indirect(&const { build_mut_ptr_type_ops::<T>() })
223 .variance(VarianceDesc::INVARIANT)
225 .eq()
226 .copy()
227 .build()
228 };
229}
230
231#[cfg(test)]
232mod test {
233 use core::panic::{RefUnwindSafe, UnwindSafe};
234
235 #[cfg(feature = "auto-traits")]
236 use impls::impls;
237
238 #[allow(unused)]
239 const fn assert_impls_unwind_safe<T: UnwindSafe>() {}
240 #[allow(unused)]
241 const fn assert_impls_ref_unwind_safe<T: RefUnwindSafe>() {}
242
243 #[allow(unused)]
244 const fn ref_unwind_safe<T: RefUnwindSafe>() {
245 assert_impls_unwind_safe::<&T>();
246 assert_impls_ref_unwind_safe::<&T>();
247
248 assert_impls_ref_unwind_safe::<&mut T>();
249
250 assert_impls_unwind_safe::<*const T>();
251 assert_impls_ref_unwind_safe::<*const T>();
252
253 assert_impls_unwind_safe::<*mut T>();
254 assert_impls_ref_unwind_safe::<*mut T>();
255 }
256
257 #[test]
258 #[cfg(feature = "auto-traits")]
259 fn mut_ref_not_unwind_safe() {
260 assert!(impls!(&mut (): !UnwindSafe));
261 }
262}