]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_data_structures/src/functor.rs
Rollup merge of #94145 - ssomers:binary_heap_tests, r=jyn514
[rust.git] / compiler / rustc_data_structures / src / functor.rs
1 use rustc_index::vec::{Idx, IndexVec};
2 use std::mem;
3
4 pub trait IdFunctor: Sized {
5     type Inner;
6
7     fn try_map_id<F, E>(self, f: F) -> Result<Self, E>
8     where
9         F: FnMut(Self::Inner) -> Result<Self::Inner, E>;
10 }
11
12 impl<T> IdFunctor for Box<T> {
13     type Inner = T;
14
15     #[inline]
16     fn try_map_id<F, E>(self, mut f: F) -> Result<Self, E>
17     where
18         F: FnMut(Self::Inner) -> Result<Self::Inner, E>,
19     {
20         let raw = Box::into_raw(self);
21         Ok(unsafe {
22             // SAFETY: The raw pointer points to a valid value of type `T`.
23             let value = raw.read();
24             // SAFETY: Converts `Box<T>` to `Box<MaybeUninit<T>>` which is the
25             // inverse of `Box::assume_init()` and should be safe.
26             let raw: Box<mem::MaybeUninit<T>> = Box::from_raw(raw.cast());
27             // SAFETY: Write the mapped value back into the `Box`.
28             Box::write(raw, f(value)?)
29         })
30     }
31 }
32
33 impl<T> IdFunctor for Vec<T> {
34     type Inner = T;
35
36     #[inline]
37     fn try_map_id<F, E>(self, f: F) -> Result<Self, E>
38     where
39         F: FnMut(Self::Inner) -> Result<Self::Inner, E>,
40     {
41         self.into_iter().map(f).collect()
42     }
43 }
44
45 impl<T> IdFunctor for Box<[T]> {
46     type Inner = T;
47
48     #[inline]
49     fn try_map_id<F, E>(self, f: F) -> Result<Self, E>
50     where
51         F: FnMut(Self::Inner) -> Result<Self::Inner, E>,
52     {
53         Vec::from(self).try_map_id(f).map(Into::into)
54     }
55 }
56
57 impl<I: Idx, T> IdFunctor for IndexVec<I, T> {
58     type Inner = T;
59
60     #[inline]
61     fn try_map_id<F, E>(self, f: F) -> Result<Self, E>
62     where
63         F: FnMut(Self::Inner) -> Result<Self::Inner, E>,
64     {
65         self.raw.try_map_id(f).map(IndexVec::from_raw)
66     }
67 }