deferred_reference/
core_traits_impl.rs

1//! This module contains trait implementations from the core library for [Deferred].
2
3use core::ops::{Deref, DerefMut, Index, IndexMut};
4
5use crate::{Deferred, Reference, SliceLike, SlicePointerIndex};
6
7// if a reference may be copied, then so may the corresponding [Deferred].
8impl<T: Copy + Reference> Copy for Deferred<T> {}
9
10// if a reference may be cloned, then so may the corresponding [Deferred].
11impl<T: Clone + Copy + Reference> Clone for Deferred<T> {
12    fn clone(&self) -> Self {
13        *self
14    }
15}
16
17// SAFETY: this is safe, because we merely inherit the Sync trait bounds from the Rust reference types.
18unsafe impl<T: Sync + Reference> Sync for Deferred<T> {}
19
20// SAFETY: this is safe, because we merely inherit the Send trait bounds from the Rust reference types.
21unsafe impl<T: Send + Reference> Send for Deferred<T> {}
22
23impl<T: Reference> Deref for Deferred<T> {
24    type Target = T::Target;
25    
26    fn deref(&self) -> &Self::Target {
27        // SAFETY: the pointer is valid, non-null and aligned, so this is safe.
28        // SAFETY: the caller is still responsible for not giving out any
29        // SAFETY: mutable references to the same place before calling deref(),
30        // SAFETY: however, creating such mutable references would have to happen
31        // SAFETY: through an `unsafe` block where the caller is responsible for
32        // SAFETY: the guarantees that no mutable reference can co-exist when
33        // SAFETY: deref() is called! hence, this is again safe.
34        unsafe {
35            &*self.as_ptr()
36        }
37    }
38}
39
40impl<T: ?Sized> DerefMut for Deferred<&mut T> {
41    fn deref_mut(&mut self) -> &mut T {
42        // SAFETY: the pointer is valid, non-null and aligned, so this is safe.
43        // SAFETY: the caller is still responsible for not giving out any mutable
44        // SAFETY: or immutable references to the same place before calling deref_mut(),
45        // SAFETY: however, creating such references would have to happen
46        // SAFETY: through an `unsafe` block where the caller is responsible for
47        // SAFETY: the guarantees that no references can co-exist when
48        // SAFETY: deref_mut() is called! hence, this is again safe.
49        unsafe {
50            &mut *self.as_mut_ptr()
51        }
52    }
53}
54
55impl<T: ?Sized> core::fmt::Pointer for Deferred<&T> {
56    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
57        <*const T>::fmt(&self.as_ptr(), f)
58    }
59}
60impl<T: ?Sized> core::fmt::Pointer for Deferred<&mut T> {
61    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
62        <*mut T>::fmt(&self.as_mut_ptr(), f)
63    }
64}
65
66// requires #![feature(coerce_unsized)]:
67// this doesn't work, compiler panicks: error: internal compiler error: compiler/rustc_mir/src/monomorphize/collector.rs:884:22: unexpected unsized tail: [u8; 1024]
68// impl<T, const N: usize> CoerceUnsized<Deferred<&[T]>> for Deferred<&[T; N]> {}
69// impl<T, const N: usize> CoerceUnsized<Deferred<&[T]>> for Deferred<&mut [T; N]> {}
70// impl<T, const N: usize> CoerceUnsized<Deferred<&mut [T]>> for Deferred<&mut [T; N]> {}
71// requires additional #![feature(unsize)]:
72// impl<T, U> CoerceUnsized<Deferred<U>> for Deferred<T>
73// where
74//     T: Reference,
75//     T::Target: Unsize<U::Target>,
76//     U: Reference,
77// {}
78
79impl<I, T> Index<I> for Deferred<T>
80where
81    T: Reference,
82    T::Target: SliceLike,
83    I: SlicePointerIndex<T::Target>,
84{
85    type Output = I::Output;
86
87    fn index(&self, index: I) -> &Self::Output {
88        // SAFETY: `Deferred` guarantees that the pointer is valid and safe to dereference
89        unsafe {
90            &*index.index(self.as_ptr())
91        }
92    }
93}
94
95impl<I, T> IndexMut<I> for Deferred<&mut T>
96where
97    T: SliceLike + ?Sized,
98    I: SlicePointerIndex<T>,
99{
100    fn index_mut(&mut self, index: I) -> &mut Self::Output {
101        // SAFETY: `Deferred` guarantees that the pointer is valid and safe to dereference
102        unsafe {
103            &mut *index.index_mut(self.as_mut_ptr())
104        }
105    }
106}
107
108impl<'a, T: ?Sized> From<Deferred<&'a mut T>> for Deferred<&'a T> {
109    fn from(deferred: Deferred<&mut T>) -> Self {
110        // SAFETY: downgrading from a (deferred) mutable reference
111        // SAFETY: to a (deferred) immutable reference is always safe
112        unsafe {
113            Deferred::from_raw(deferred.as_ptr())
114        }
115    }
116}
117
118impl<'a, T: ?Sized> From<&'a T> for Deferred<&'a T> {
119    fn from(reference: &T) -> Self {
120        // SAFETY: an actual immutable reference gives us all the guarantees
121        // SAFETY: demanded by the invariant of `Deferred`, so this is safe
122        unsafe {
123            Deferred::from_raw(reference)
124        }
125    }
126}
127
128impl<'a, T: ?Sized> From<&'a mut T> for Deferred<&'a mut T> {
129    fn from(reference: &mut T) -> Self {
130        // SAFETY: an actual mutable reference gives us all the guarantees
131        // SAFETY: demanded by the invariant of `Deferred`, so this is safe
132        unsafe {
133            Deferred::from_raw_mut(reference)
134        }
135    }
136}
137
138impl<'a, T, const N: usize> From<Deferred<&'a [T; N]>> for Deferred<&'a [T]> {
139    fn from(deferred: Deferred<&[T; N]>) -> Self {
140        // SAFETY: we exchange one `Deferred` for another, so this is safe
141        unsafe {
142            Deferred::from_raw(core::ptr::slice_from_raw_parts(deferred.as_ptr() as *const T, N))
143        }
144    }
145}
146
147impl<'a, T, const N: usize> From<Deferred<&'a mut [T; N]>> for Deferred<&'a mut [T]> {
148    fn from(deferred: Deferred<&mut [T; N]>) -> Self {
149        // SAFETY: we exchange one `Deferred` for another, so this is safe
150        unsafe {
151            Deferred::from_raw_mut(core::ptr::slice_from_raw_parts_mut(deferred.as_mut_ptr() as *mut T, N))
152        }
153    }
154}
155
156impl<'a, T, const N: usize> From<Deferred<&'a mut [T; N]>> for Deferred<&'a [T]> {
157    fn from(deferred: Deferred<&mut [T; N]>) -> Self {
158        // SAFETY: we exchange one `Deferred` for another, so this is safe
159        unsafe {
160            Deferred::from_raw(core::ptr::slice_from_raw_parts(deferred.as_ptr() as *const T, N))
161        }
162    }
163}
164
165#[cfg(test)]
166mod tests {
167    use crate::{Defer, DeferMut, Deferred};
168    use core::cell::UnsafeCell;
169
170    /// tests for `Index` and `IndexMut` traits
171    mod index {
172        use super::*;
173
174        #[test]
175        fn array() {
176            let mut buffer = [0u8; 1024];
177            let deferred = Deferred::from(&mut buffer);
178            assert_eq!(1024, (&deferred[..]).len());
179            // canary triggers miri if something is wrong with the Index trait implementation
180            let canary = unsafe { &mut deferred.clone_unchecked()[1000] };
181            assert_eq!(23, (&deferred[1001..]).len());
182            assert_eq!(&0, &deferred[0]);
183            assert_eq!(5, (&deferred[5..10]).len());
184            assert_eq!(10, (&deferred[..10]).len());
185            assert_eq!(11, (&deferred[..=10]).len());
186            assert_eq!(6, (&deferred[5..=10]).len());
187            assert_eq!(0, (&deferred[0..0]).len());
188            assert_eq!(1, (&deferred[0..1]).len());
189            assert_eq!(&mut 0, canary);
190        }
191        #[test]
192        fn array_mut() {
193            let mut buffer = [0u8; 1024];
194            let mut deferred = Deferred::from(&mut buffer);
195            assert_eq!(1024, (&mut deferred[..]).len());
196            // canary triggers miri if something is wrong with the IndexMut trait implementation
197            let canary = unsafe { &mut deferred.clone_unchecked()[1000] };
198            assert_eq!(23, (&mut deferred[1001..]).len());
199            assert_eq!(&mut 0, &mut deferred[0]);
200            assert_eq!(5, (&mut deferred[5..10]).len());
201            assert_eq!(10, (&mut deferred[..10]).len());
202            assert_eq!(11, (&mut deferred[..=10]).len());
203            assert_eq!(6, (&mut deferred[5..=10]).len());
204            assert_eq!(0, (&mut deferred[0..0]).len());
205            assert_eq!(1, (&mut deferred[0..1]).len());
206            assert_eq!(&mut 0, canary);
207        }
208        #[test]
209        fn slice() {
210            let mut buffer = [0u8; 1024];
211            let deferred = Deferred::from(&mut buffer[..]);
212            let _x = &deferred[..];
213            // canary triggers miri if something is wrong with the Index trait implementation
214            // this triggers miri on stable rust for now, until the `slice_ptr_len` feature lands.
215            // see <https://github.com/rust-lang/rust/issues/71146>.
216            #[cfg(feature = "slice_ptr_len")]
217            let canary = unsafe { &mut deferred.clone_unchecked()[1000] };
218            assert_eq!(23, (&deferred[1001..]).len());
219            assert_eq!(&0, &deferred[0]);
220            assert_eq!(5, (&deferred[5..10]).len());
221            assert_eq!(10, (&deferred[..10]).len());
222            assert_eq!(11, (&deferred[..=10]).len());
223            assert_eq!(6, (&deferred[5..=10]).len());
224            assert_eq!(0, (&deferred[0..0]).len());
225            assert_eq!(1, (&deferred[0..1]).len());
226            #[cfg(feature = "slice_ptr_len")]
227            assert_eq!(&mut 0, canary);
228        }
229        #[test]
230        fn slice_mut() {
231            let mut buffer = [0u8; 1024];
232            let mut deferred = Deferred::from(&mut buffer[..]);
233            let _x = &mut deferred[..];
234            // canary triggers miri if something is wrong with the IndexMut trait implementation
235            // this triggers miri on stable rust for now, until the `slice_ptr_len` feature lands.
236            // see <https://github.com/rust-lang/rust/issues/71146>.
237            #[cfg(feature = "slice_ptr_len")]
238            let canary = unsafe { &mut deferred.clone_unchecked()[1000] };
239            assert_eq!(23, (&mut deferred[1001..]).len());
240            assert_eq!(&mut 0, &mut deferred[0]);
241            assert_eq!(5, (&mut deferred[5..10]).len());
242            assert_eq!(10, (&mut deferred[..10]).len());
243            assert_eq!(11, (&mut deferred[..=10]).len());
244            assert_eq!(6, (&mut deferred[5..=10]).len());
245            assert_eq!(0, (&mut deferred[0..0]).len());
246            assert_eq!(1, (&mut deferred[0..1]).len());
247            #[cfg(feature = "slice_ptr_len")]
248            assert_eq!(&mut 0, canary);
249        }
250    }
251
252    /// tests for the `From` trait
253    mod from  {
254        use super::*;
255        #[test]
256        fn from_ref() {
257            let buffer = [0u8; 1024];
258            let _deferred = Deferred::from(&buffer);
259            let _deferred: Deferred<&[u8]> = Deferred::from(&buffer[..]);
260        }
261        #[test]
262        fn from_mut() {
263            let mut buffer = [0u8; 1024];
264            let _deferred = Deferred::from(&mut buffer);
265            let _deferred: Deferred<&mut [u8]> = Deferred::from(&mut buffer[..]);
266        }
267        #[test]
268        fn ref_array_to_slice() {
269            let buffer = UnsafeCell::new([0u8; 1024]);
270            let deferred = buffer.defer();
271            let _deferred_slice: Deferred<&[u8]> = deferred.into();
272            let _deferred_slice: Deferred<&[u8]> = Deferred::from(deferred);
273        }
274        #[test]
275        fn mut_array_to_slice() {
276            let buffer = UnsafeCell::new([0u8; 1024]);
277            let deferred = unsafe { buffer.defer_mut() };
278            let _deferred_slice: Deferred<&mut [u8]> = deferred.into();
279            let deferred = unsafe { buffer.defer_mut() };
280            let _deferred_slice: Deferred<&mut [u8]> = Deferred::from(deferred);
281        }
282        #[test]
283        fn mut_array_to_ref_slice() {
284            let buffer = UnsafeCell::new([0u8; 1024]);
285            let deferred = unsafe { buffer.defer_mut() };
286            let _deferred_slice: Deferred<&[u8]> = deferred.into();
287            let deferred = unsafe { buffer.defer_mut() };
288            let _deferred_slice: Deferred<&[u8]> = Deferred::from(deferred);
289        }
290        #[test]
291        fn mut_to_ref() {
292            let buffer = UnsafeCell::new([0u8; 1024]);
293            let deferred = unsafe { buffer.defer_mut() };
294            let _deferred_slice: Deferred<&[u8; 1024]> = deferred.into();
295            let deferred = unsafe { buffer.defer_mut() };
296            let _deferred_slice: Deferred<&[u8; 1024]> = Deferred::from(deferred);
297            let buffer = UnsafeCell::new(1u32);
298            let deferred = unsafe { buffer.defer_mut() };
299            let _deferred_u32: Deferred<&u32> = deferred.into();
300            let deferred = unsafe { buffer.defer_mut() };
301            let _deferred_u32: Deferred<&u32> = Deferred::from(deferred);
302        }
303    }
304}