enum_ptr/traits/
borrow_mut.rs

1use core::mem::transmute;
2use core::ops::DerefMut;
3
4use crate::{Compact, Compactable};
5
6/// Types that can be mutably borrowed from [`Compact`]. Typically derived from
7/// [`EnumPtr`](crate::EnumPtr).
8pub trait CompactBorrowMut: Compactable {
9    type Target<'a>
10    where
11        Self: 'a;
12
13    fn borrow_mut(compact: &mut Compact<Self>) -> Self::Target<'_>;
14}
15
16/// Types that can be used by [`get_mut`](crate::get_mut) and to derive
17/// [`CompactBorrowMut`].
18///
19/// It's like [`DerefMut`] but with flexible targets and strict constraints.
20///
21/// # Safety
22///
23/// `T` must not `deref_mut` to something that points to its own memory.
24///
25/// A counter-example is `ManuallyDrop<T>`, which will `deref_mut` to `&mut T`.
26pub unsafe trait FieldDerefMut {
27    type Target<'a>
28    where
29        Self: 'a;
30
31    fn deref_mut(&mut self) -> Self::Target<'_>;
32
33    #[doc(hidden)]
34    #[inline]
35    unsafe fn force_deref_mut<'a>(&mut self) -> Self::Target<'a> {
36        transmute(self.deref_mut())
37    }
38}
39
40unsafe impl<T> FieldDerefMut for &mut T {
41    type Target<'a> = &'a mut T
42    where
43        Self: 'a;
44
45    #[inline]
46    fn deref_mut(&mut self) -> Self::Target<'_> {
47        DerefMut::deref_mut(self)
48    }
49}
50
51unsafe impl<T> FieldDerefMut for Option<&mut T> {
52    type Target<'a> = Option<&'a mut T>
53    where
54        Self: 'a;
55
56    #[inline]
57    fn deref_mut(&mut self) -> Self::Target<'_> {
58        self.as_deref_mut()
59    }
60}
61
62#[cfg(feature = "alloc")]
63mod alloc_impl {
64    use super::*;
65
66    use alloc::boxed::Box;
67
68    unsafe impl<T> FieldDerefMut for Box<T> {
69        type Target<'a> = &'a mut T
70        where
71            Self: 'a;
72
73        #[inline]
74        fn deref_mut(&mut self) -> Self::Target<'_> {
75            DerefMut::deref_mut(self)
76        }
77    }
78
79    unsafe impl<T> FieldDerefMut for Option<Box<T>> {
80        type Target<'a> = Option<&'a mut T>
81        where
82            Self: 'a;
83
84        #[inline]
85        fn deref_mut(&mut self) -> Self::Target<'_> {
86            self.as_deref_mut()
87        }
88    }
89}