facet_core/impls_core/
pointer.rs

1use core::fmt;
2use core::hash::Hash;
3
4use crate::{
5    Facet, MarkerTraits, PointerType, Shape, Type, TypeParam, ValuePointerType, ValueVTable,
6};
7
8// *const pointers
9unsafe impl<'a, T: Facet<'a> + ?Sized> Facet<'a> for *const T {
10    const SHAPE: &'static Shape = &const {
11        Shape::builder_for_sized::<Self>()
12            .vtable(
13                ValueVTable::builder::<Self>()
14                    .marker_traits({
15                        let mut marker_traits = MarkerTraits::EQ
16                            .union(MarkerTraits::COPY)
17                            .union(MarkerTraits::UNPIN);
18
19                        if T::SHAPE
20                            .vtable
21                            .marker_traits()
22                            .contains(MarkerTraits::REF_UNWIND_SAFE)
23                        {
24                            marker_traits = marker_traits
25                                .union(MarkerTraits::UNWIND_SAFE)
26                                .union(MarkerTraits::REF_UNWIND_SAFE);
27                        }
28
29                        marker_traits
30                    })
31                    .debug(Some(|p, f| fmt::Debug::fmt(p.get(), f)))
32                    .partial_eq(Some(|a, b| {
33                        #[allow(ambiguous_wide_pointer_comparisons)]
34                        (*a.get() == *b.get())
35                    }))
36                    .partial_ord(Some(|a, b| {
37                        #[allow(ambiguous_wide_pointer_comparisons)]
38                        (a.get().partial_cmp(b.get()))
39                    }))
40                    .ord(Some(|a, b| {
41                        #[allow(ambiguous_wide_pointer_comparisons)]
42                        (a.get().cmp(b.get()))
43                    }))
44                    .hash(Some(|value, hasher| value.get().hash(&mut { hasher })))
45                    .clone_into(Some(|src, dst| unsafe { dst.put(*src.get()).into() }))
46                    .type_name(|f, opts| {
47                        if let Some(opts) = opts.for_children() {
48                            write!(f, "*const ")?;
49                            (T::SHAPE.vtable.type_name())(f, opts)
50                        } else {
51                            write!(f, "*const …")
52                        }
53                    })
54                    .build(),
55            )
56            .inner(T::SHAPE)
57            .type_identifier("*const _")
58            .type_params(&[TypeParam {
59                name: "T",
60                shape: T::SHAPE,
61            }])
62            .ty({
63                let is_wide = ::core::mem::size_of::<Self>() != ::core::mem::size_of::<*const ()>();
64                let vpt = ValuePointerType {
65                    mutable: false,
66                    wide: is_wide,
67                    target: T::SHAPE,
68                };
69
70                Type::Pointer(PointerType::Raw(vpt))
71            })
72            .build()
73    };
74}
75
76// *mut pointers
77unsafe impl<'a, T: Facet<'a> + ?Sized> Facet<'a> for *mut T {
78    const SHAPE: &'static Shape = &const {
79        Shape::builder_for_sized::<Self>()
80            .vtable(
81                ValueVTable::builder::<Self>()
82                    .marker_traits({
83                        let mut marker_traits = MarkerTraits::EQ
84                            .union(MarkerTraits::COPY)
85                            .union(MarkerTraits::UNPIN);
86
87                        if T::SHAPE
88                            .vtable
89                            .marker_traits()
90                            .contains(MarkerTraits::REF_UNWIND_SAFE)
91                        {
92                            marker_traits = marker_traits
93                                .union(MarkerTraits::UNWIND_SAFE)
94                                .union(MarkerTraits::REF_UNWIND_SAFE);
95                        }
96
97                        marker_traits
98                    })
99                    .partial_eq(Some(|a, b| {
100                        #[allow(ambiguous_wide_pointer_comparisons)]
101                        (*a.get() == *b.get())
102                    }))
103                    .partial_ord(Some(|a, b| {
104                        #[allow(ambiguous_wide_pointer_comparisons)]
105                        (a.get().partial_cmp(b.get()))
106                    }))
107                    .ord(Some(|a, b| {
108                        #[allow(ambiguous_wide_pointer_comparisons)]
109                        (a.get().cmp(b.get()))
110                    }))
111                    .hash(Some(|value, hasher| value.get().hash(&mut { hasher })))
112                    .debug(Some(|p, f| fmt::Debug::fmt(p.get(), f)))
113                    .clone_into(Some(|src, dst| unsafe { dst.put(*src.get()).into() }))
114                    .type_name(|f, opts| {
115                        if let Some(opts) = opts.for_children() {
116                            write!(f, "*mut ")?;
117                            (T::SHAPE.vtable.type_name())(f, opts)
118                        } else {
119                            write!(f, "*mut …")
120                        }
121                    })
122                    .build(),
123            )
124            .inner(T::SHAPE)
125            .type_identifier("*mut _")
126            .type_params(&[TypeParam {
127                name: "T",
128                shape: T::SHAPE,
129            }])
130            .ty({
131                let is_wide = ::core::mem::size_of::<Self>() != ::core::mem::size_of::<*const ()>();
132                let vpt = ValuePointerType {
133                    mutable: true,
134                    wide: is_wide,
135                    target: T::SHAPE,
136                };
137
138                Type::Pointer(PointerType::Raw(vpt))
139            })
140            .build()
141    };
142}
143
144#[cfg(test)]
145mod test {
146    use core::panic::{RefUnwindSafe, UnwindSafe};
147    use impls::impls;
148
149    #[allow(unused)]
150    const fn assert_impls_unwind_safe<T: UnwindSafe>() {}
151    #[allow(unused)]
152    const fn assert_impls_ref_unwind_safe<T: RefUnwindSafe>() {}
153
154    #[allow(unused)]
155    const fn ref_unwind_safe<T: RefUnwindSafe>() {
156        assert_impls_unwind_safe::<&T>();
157        assert_impls_ref_unwind_safe::<&T>();
158
159        assert_impls_ref_unwind_safe::<&mut T>();
160
161        assert_impls_unwind_safe::<*const T>();
162        assert_impls_ref_unwind_safe::<*const T>();
163
164        assert_impls_unwind_safe::<*mut T>();
165        assert_impls_ref_unwind_safe::<*mut T>();
166    }
167
168    #[test]
169    fn mut_ref_not_unwind_safe() {
170        assert!(impls!(&mut (): !UnwindSafe));
171    }
172}