]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_data_structures/src/functor.rs
Auto merge of #91182 - ChrisDenton:command-broken-symlink, r=m-ou-se
[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, mut f: F) -> Result<Self, E>
38     where
39         F: FnMut(Self::Inner) -> Result<Self::Inner, E>,
40     {
41         struct HoleVec<T> {
42             vec: Vec<mem::ManuallyDrop<T>>,
43             hole: Option<usize>,
44         }
45
46         impl<T> Drop for HoleVec<T> {
47             fn drop(&mut self) {
48                 unsafe {
49                     for (index, slot) in self.vec.iter_mut().enumerate() {
50                         if self.hole != Some(index) {
51                             mem::ManuallyDrop::drop(slot);
52                         }
53                     }
54                 }
55             }
56         }
57
58         unsafe {
59             let (ptr, length, capacity) = self.into_raw_parts();
60             let vec = Vec::from_raw_parts(ptr.cast(), length, capacity);
61             let mut hole_vec = HoleVec { vec, hole: None };
62
63             for (index, slot) in hole_vec.vec.iter_mut().enumerate() {
64                 hole_vec.hole = Some(index);
65                 let original = mem::ManuallyDrop::take(slot);
66                 let mapped = f(original)?;
67                 *slot = mem::ManuallyDrop::new(mapped);
68                 hole_vec.hole = None;
69             }
70
71             mem::forget(hole_vec);
72             Ok(Vec::from_raw_parts(ptr, length, capacity))
73         }
74     }
75 }
76
77 impl<T> IdFunctor for Box<[T]> {
78     type Inner = T;
79
80     #[inline]
81     fn try_map_id<F, E>(self, f: F) -> Result<Self, E>
82     where
83         F: FnMut(Self::Inner) -> Result<Self::Inner, E>,
84     {
85         Vec::from(self).try_map_id(f).map(Into::into)
86     }
87 }
88
89 impl<I: Idx, T> IdFunctor for IndexVec<I, T> {
90     type Inner = T;
91
92     #[inline]
93     fn try_map_id<F, E>(self, f: F) -> Result<Self, E>
94     where
95         F: FnMut(Self::Inner) -> Result<Self::Inner, E>,
96     {
97         self.raw.try_map_id(f).map(IndexVec::from_raw)
98     }
99 }