Skip to main content

magic_args/
mut.rs

1use core::borrow::{Borrow, BorrowMut};
2use core::cell::Cell;
3use core::ops::{Deref, DerefMut};
4use core::ptr::NonNull;
5
6///////////////////////////////////////////////////////////////////////////////
7
8/// A [`Clone`]-once wrapper.
9///
10/// [`Mut`] allows passing types like `&mut T` safely. [`Mut`] implements a
11/// dummy [`Clone`] that allows being cloned exactly once. This allows passing
12/// non-[`Clone`] types by moving them between [`Mut`]s. [`Mut`] can be thought
13/// of a bit like [`Option`]. [`Mut`] contains a value and when it is [`Clone`]d
14/// the value inside is moved to the new [`Mut`] leaving [`None`] in the old
15/// [`Mut`]. This approach has the disadvantage that the uniqueness check
16/// becomes a runtime panic.
17///
18/// # Panics
19///
20/// [`Mut`] will panic in any of the following situations:
21///
22/// 1) if it is [`Clone::clone`]d more than once
23/// 2) if the inner value is accessed after a [`Clone`]
24///
25/// # Example
26///
27/// ```
28/// # use magic_args::Mut;
29/// fn f(mut y: Mut<&mut i32>, x: i32) {
30///     **y += 2 * x;
31/// }
32///
33/// let x: i32 = 42;
34/// let mut y: i32 = 31;
35///
36/// magic_args::apply(f, (x, Mut::from(&mut y)));
37/// assert_eq!(y, 115);
38/// ```
39///
40/// [`Callable`]: crate::Callable
41#[expect(missing_debug_implementations)]
42pub struct Mut<T>(Cell<Option<T>>);
43
44impl<T> From<T> for Mut<T> {
45    fn from(value: T) -> Self {
46        Mut(Cell::new(Some(value)))
47    }
48}
49
50impl<T> Clone for Mut<T> {
51    #[track_caller]
52    fn clone(&self) -> Self {
53        let inner = self.0.replace(None);
54        assert!(inner.is_some(), "magic_args::Mut cloned twice");
55
56        Self(Cell::new(inner))
57    }
58}
59
60impl<T> Mut<T> {
61    fn inner_ptr(&self) -> NonNull<Option<T>> {
62        let ptr = self.0.as_ptr();
63        NonNull::new(ptr).expect("Cell::as_ptr should never return null")
64    }
65
66    #[track_caller]
67    fn inner_ref(&self) -> &T {
68        // SAFETY: We dereference a pointer to the `Option<T>` inside the
69        //         `Cell`. The pointer is correctly aligned and non-null.
70        #[expect(unsafe_code)]
71        let value = unsafe { self.inner_ptr().as_ref() };
72        value.as_ref().expect("magic_args::Mut cloned twice")
73    }
74
75    #[track_caller]
76    #[expect(clippy::mut_from_ref)]
77    fn inner_mut(&self) -> &mut T {
78        // SAFETY: We dereference a pointer to the `Option<T>` inside the
79        //         `Cell`. The pointer is correctly aligned and non-null.
80        #[expect(unsafe_code)]
81        let value = unsafe { self.inner_ptr().as_mut() };
82        value.as_mut().expect("magic_args::Mut cloned twice")
83    }
84
85    /// Destruct this [`Mut`] and get the value inside.
86    ///
87    /// # Panics
88    ///
89    /// See: [type-level panic docs](Mut#panics).
90    #[track_caller]
91    pub fn into_inner(self) -> T {
92        // SAFETY: We dereference a pointer to the `Option<T>` inside the
93        //         `Cell`. The pointer is correctly aligned and non-null.
94        #[expect(unsafe_code)]
95        let value = unsafe { self.inner_ptr().as_mut() };
96        value.take().expect("magic_args::Mut cloned twice")
97    }
98}
99
100macro_rules! impl_borrow {
101    ($T:ty) => {
102        impl<T> Borrow<T> for Mut<$T> {
103            #[inline]
104            fn borrow(&self) -> &T {
105                self.inner_ref()
106            }
107        }
108
109        impl<T> BorrowMut<T> for Mut<$T> {
110            #[inline]
111            fn borrow_mut(&mut self) -> &mut T {
112                self.inner_mut()
113            }
114        }
115    };
116}
117
118macro_rules! impl_as_ref {
119    ($T:ty) => {
120        impl<T> AsRef<T> for Mut<$T> {
121            #[inline]
122            fn as_ref(&self) -> &T {
123                self.inner_ref()
124            }
125        }
126
127        impl<T> AsMut<T> for Mut<$T> {
128            #[inline]
129            fn as_mut(&mut self) -> &mut T {
130                self.inner_mut()
131            }
132        }
133    };
134}
135
136impl_borrow!(T);
137impl_borrow!(&mut T);
138impl_borrow!(&mut &mut T);
139impl_borrow!(&mut &mut &mut T);
140
141impl_as_ref!(T);
142impl_as_ref!(&mut T);
143impl_as_ref!(&mut &mut T);
144impl_as_ref!(&mut &mut &mut T);
145
146impl<T> Deref for Mut<T> {
147    type Target = T;
148
149    #[inline]
150    fn deref(&self) -> &Self::Target {
151        self.inner_ref()
152    }
153}
154
155impl<T> DerefMut for Mut<T> {
156    #[inline]
157    fn deref_mut(&mut self) -> &mut Self::Target {
158        self.inner_mut()
159    }
160}
161
162///////////////////////////////////////////////////////////////////////////////
163
164#[cfg(test)]
165mod tests {
166    use super::*;
167
168    use crate::apply;
169
170    #[test]
171    fn test_mut() {
172        fn f0(_a: i32, b: Mut<i32>) -> i32 {
173            *b
174        }
175
176        fn f1(_a: i32, mut b: Mut<&mut i32>) -> i32 {
177            let b = b.borrow_mut();
178            *b
179        }
180
181        fn f2(_a: i32, mut b: Mut<&mut &mut i32>) -> i32 {
182            let b = b.borrow_mut();
183            *b
184        }
185
186        fn f3(_a: i32, mut b: Mut<&mut &mut &mut i32>) -> i32 {
187            let b = b.borrow_mut();
188            *b
189        }
190
191        assert_eq!(apply(f0, (42i32, Mut::from(31i32))), 31);
192        assert_eq!(apply(f1, (42i32, Mut::from(&mut 31i32))), 31);
193        assert_eq!(apply(f2, (42i32, Mut::from(&mut &mut 31i32))), 31);
194        assert_eq!(apply(f3, (42i32, Mut::from(&mut &mut &mut 31i32))), 31);
195    }
196}