facet_core/impls_core/
pointer.rs1use core::{fmt, hash::Hash};
2
3use crate::{
4 Facet, HasherProxy, MarkerTraits, PointerType, Shape, Type, TypeParam, VTableView,
5 ValuePointerType, ValueVTable,
6};
7
8macro_rules! impl_facet_for_pointer {
9 ($variant:ident: $type:ty => $shape:expr => $vtable_builder:expr => $ptr_type:ident, $mutable:expr) => {
10 unsafe impl<'a, T: Facet<'a> + ?Sized> Facet<'a> for $type {
11 const VTABLE: &'static ValueVTable = &const {
12 $vtable_builder
13 .type_name(|f, opts| {
14 if let Some(opts) = opts.for_children() {
15 if stringify!($ptr_type) == "Raw" {
16 if $mutable {
17 write!(f, "*mut ")?;
18 } else {
19 write!(f, "*const ")?;
20 }
21 } else {
22 write!(f, "&")?;
23 if $mutable {
24 write!(f, "mut ")?;
25 }
26 }
27 (T::VTABLE.type_name())(f, opts)
28 } else {
29 if stringify!($ptr_type) == "Raw" {
30 if $mutable {
31 write!(f, "*mut ⋯")
32 } else {
33 write!(f, "*const ⋯")
34 }
35 } else {
36 write!(f, "&")?;
37 if $mutable {
38 write!(f, "mut ⋯")
39 } else {
40 write!(f, "⋯")
41 }
42 }
43 }
44 })
45 .build()
46 };
47
48 const SHAPE: &'static Shape<'static> = &const {
49 $shape
50 .type_identifier(
51 const {
52 let ptr_type = stringify!($ptr_type);
53 let is_raw = ptr_type.len() == 3
54 && ptr_type.as_bytes()[0] == b'R'
55 && ptr_type.as_bytes()[1] == b'a'
56 && ptr_type.as_bytes()[2] == b'w';
57 if is_raw {
58 if $mutable { "*mut _" } else { "*const _" }
59 } else {
60 if $mutable { "&mut _" } else { "&_" }
61 }
62 },
63 )
64 .type_params(&[TypeParam {
65 name: "T",
66 shape: || T::SHAPE,
67 }])
68 .ty({
69 let is_wide =
70 ::core::mem::size_of::<$type>() != ::core::mem::size_of::<*const ()>();
71 let vpt = ValuePointerType {
72 mutable: $mutable,
73 wide: is_wide,
74 target: || T::SHAPE,
75 };
76
77 Type::Pointer(PointerType::$ptr_type(vpt))
78 })
79 .build()
80 };
81 }
82 };
83}
84
85impl_facet_for_pointer!(
87 Raw: *const T
88 => Shape::builder_for_sized::<Self>()
89 .inner(|| T::SHAPE)
90 => ValueVTable::builder::<Self>()
91 .marker_traits(|| {
92 let mut marker_traits = MarkerTraits::EQ
93 .union(MarkerTraits::COPY)
94 .union(MarkerTraits::UNPIN);
95
96 if T::SHAPE.vtable.marker_traits().contains(MarkerTraits::REF_UNWIND_SAFE) {
97 marker_traits = marker_traits.union(MarkerTraits::UNWIND_SAFE).union(MarkerTraits::REF_UNWIND_SAFE);
98 }
99
100 marker_traits
101 })
102 .debug(|| Some(fmt::Debug::fmt))
103 .clone_into(|| Some(|src, dst| unsafe { dst.put(*src) }))
104 .partial_eq(|| Some(|&left, &right| core::ptr::eq(left, right)))
105 .partial_ord(|| Some(|&left, &right| {
106 #[allow(ambiguous_wide_pointer_comparisons)]
108 left.partial_cmp(&right)
109 }))
110 .ord(|| Some(|&left, &right| {
111 #[allow(ambiguous_wide_pointer_comparisons)]
112 left.cmp(&right)
113 }))
114 .hash(|| Some(|value, hasher_this, hasher_write_fn| {
115 value.hash(&mut unsafe {
116 HasherProxy::new(hasher_this, hasher_write_fn)
117 })
118 }))
119 => Raw, false
120);
121
122impl_facet_for_pointer!(
124 Raw: *mut T
125 => Shape::builder_for_sized::<Self>()
126 .inner(|| T::SHAPE)
127 => ValueVTable::builder::<Self>()
128 .marker_traits(|| {
129 let mut marker_traits = MarkerTraits::EQ
130 .union(MarkerTraits::COPY)
131 .union(MarkerTraits::UNPIN);
132
133 if T::SHAPE.vtable.marker_traits().contains(MarkerTraits::REF_UNWIND_SAFE) {
134 marker_traits = marker_traits.union(MarkerTraits::UNWIND_SAFE).union(MarkerTraits::REF_UNWIND_SAFE);
135 }
136
137 marker_traits
138 })
139 .debug(|| Some(fmt::Debug::fmt))
140 .clone_into(|| Some(|src, dst| unsafe { dst.put(*src) }))
141 .partial_eq(|| Some(|&left, &right| core::ptr::eq(left, right)))
142 .partial_ord(|| Some(|&left, &right| {
143 #[allow(ambiguous_wide_pointer_comparisons)]
145 left.partial_cmp(&right)
146 }))
147 .ord(|| Some(|&left, &right| {
148 #[allow(ambiguous_wide_pointer_comparisons)]
149 left.cmp(&right)
150 }))
151 .hash(|| Some(|value, hasher_this, hasher_write_fn| {
152 value.hash(&mut unsafe {
153 HasherProxy::new(hasher_this, hasher_write_fn)
154 })
155 }))
156 => Raw, true
157);
158
159impl_facet_for_pointer!(
161 Reference: &'a T
162 => Shape::builder_for_sized::<Self>()
163 => {
164 ValueVTable::builder::<Self>()
165 .marker_traits(|| {
166 let mut marker_traits = MarkerTraits::COPY.union(MarkerTraits::UNPIN);
167 if T::SHAPE.vtable.marker_traits().contains(MarkerTraits::EQ) {
168 marker_traits = marker_traits.union(MarkerTraits::EQ);
169 }
170 if T::SHAPE.vtable.marker_traits().contains(MarkerTraits::SYNC) {
171 marker_traits = marker_traits.union(MarkerTraits::SEND).union(MarkerTraits::SYNC);
172 }
173 if T::SHAPE.vtable.marker_traits().contains(MarkerTraits::REF_UNWIND_SAFE) {
174 marker_traits = marker_traits.union(MarkerTraits::UNWIND_SAFE).union(MarkerTraits::REF_UNWIND_SAFE);
175 }
176
177 marker_traits
178 })
179 .clone_into(|| Some(|src, dst| unsafe { dst.put(core::ptr::read(src)) }))
180 .debug(|| {
181 if T::VTABLE.has_debug() {
182 Some(|value, f| {
183 let view = VTableView::<T>::of();
184 view.debug().unwrap()(*value, f)
185 })
186 } else {
187 None
188 }
189 })
190 .display(|| {
191 if T::VTABLE.has_display() {
192 Some(|value, f| {
193 let view = VTableView::<T>::of();
194 view.display().unwrap()(*value, f)
195 })
196 } else {
197 None
198 }
199 })
200 .partial_eq(|| {
201 if T::VTABLE.has_partial_eq() {
202 Some(|a, b| {
203 let view = VTableView::<T>::of();
204 view.partial_eq().unwrap()(*a, *b)
205 })
206 } else {
207 None
208 }
209 })
210 .partial_ord(|| {
211 if T::VTABLE.has_partial_ord() {
212 Some(|a, b| {
213 let view = VTableView::<T>::of();
214 view.partial_ord().unwrap()(*a, *b)
215 })
216 } else {
217 None
218 }
219 })
220 .ord(|| {
221 if T::VTABLE.has_ord() {
222 Some(|a, b| {
223 let view = VTableView::<T>::of();
224 view.ord().unwrap()(*a, *b)
225 })
226 } else {
227 None
228 }
229 })
230 .hash(|| {
231 if T::VTABLE.has_hash() {
232 Some(|value, hasher_this, hasher_write_fn| {
233 let view = VTableView::<T>::of();
234 view.hash().unwrap()(*value, hasher_this, hasher_write_fn)
235 })
236 } else {
237 None
238 }
239 })
240 }
241 => Reference, false
242);
243
244impl_facet_for_pointer!(
246 Reference: &'a mut T
247 => Shape::builder_for_sized::<Self>()
248 => {
249 ValueVTable::builder::<Self>()
250 .marker_traits(|| {
251 let mut marker_traits = MarkerTraits::UNPIN;
252 if T::SHAPE.vtable.marker_traits().contains(MarkerTraits::EQ) {
253 marker_traits = marker_traits.union(MarkerTraits::EQ);
254 }
255 if T::SHAPE.vtable.marker_traits().contains(MarkerTraits::SEND) {
256 marker_traits = marker_traits.union(MarkerTraits::SEND);
257 }
258 if T::SHAPE.vtable.marker_traits().contains(MarkerTraits::SYNC) {
259 marker_traits = marker_traits.union(MarkerTraits::SYNC);
260 }
261 if T::SHAPE.vtable.marker_traits().contains(MarkerTraits::REF_UNWIND_SAFE) {
262 marker_traits = marker_traits.union(MarkerTraits::REF_UNWIND_SAFE);
263 }
264
265 marker_traits
266 })
267 .debug(|| {
268 if T::VTABLE.has_debug() {
269 Some(|value, f| {
270 let view = VTableView::<T>::of();
271 view.debug().unwrap()(*value, f)
272 })
273 } else {
274 None
275 }
276 })
277 .display(|| {
278 if T::VTABLE.has_display() {
279 Some(|value, f| {
280 let view = VTableView::<T>::of();
281 view.display().unwrap()(*value, f)
282 })
283 } else {
284 None
285 }
286 })
287 .partial_eq(|| {
288 if T::VTABLE.has_partial_eq() {
289 Some(|a, b| {
290 let view = VTableView::<T>::of();
291 view.partial_eq().unwrap()(*a, *b)
292 })
293 } else {
294 None
295 }
296 })
297 .partial_ord(|| {
298 if T::VTABLE.has_partial_ord() {
299 Some(|a, b| {
300 let view = VTableView::<T>::of();
301 view.partial_ord().unwrap()(*a, *b)
302 })
303 } else {
304 None
305 }
306 })
307 .ord(|| {
308 if T::VTABLE.has_ord() {
309 Some(|a, b| {
310 let view = VTableView::<T>::of();
311 view.ord().unwrap()(*a, *b)
312 })
313 } else {
314 None
315 }
316 })
317 .hash(|| {
318 if T::VTABLE.has_hash() {
319 Some(|value, hasher_this, hasher_write_fn| {
320 let view = VTableView::<T>::of();
321 view.hash().unwrap()(*value, hasher_this, hasher_write_fn)
322 })
323 } else {
324 None
325 }
326 })
327 }
328 => Reference, true
329);
330
331#[cfg(test)]
332mod test {
333 use core::panic::{RefUnwindSafe, UnwindSafe};
334 use impls::impls;
335
336 #[allow(unused)]
337 const fn assert_impls_unwind_safe<T: UnwindSafe>() {}
338 #[allow(unused)]
339 const fn assert_impls_ref_unwind_safe<T: RefUnwindSafe>() {}
340
341 #[allow(unused)]
342 const fn ref_unwind_safe<T: RefUnwindSafe>() {
343 assert_impls_unwind_safe::<&T>();
344 assert_impls_ref_unwind_safe::<&T>();
345
346 assert_impls_ref_unwind_safe::<&mut T>();
347
348 assert_impls_unwind_safe::<*const T>();
349 assert_impls_ref_unwind_safe::<*const T>();
350
351 assert_impls_unwind_safe::<*mut T>();
352 assert_impls_ref_unwind_safe::<*mut T>();
353 }
354
355 #[test]
356 fn mut_ref_not_unwind_safe() {
357 assert!(impls!(&mut (): !UnwindSafe));
358 }
359}