]> git.proxmox.com Git - rustc.git/blame - compiler/rustc_data_structures/src/functor.rs
New upstream version 1.59.0+dfsg1
[rustc.git] / compiler / rustc_data_structures / src / functor.rs
CommitLineData
fc512014
XL
1use rustc_index::vec::{Idx, IndexVec};
2use std::mem;
fc512014 3
a2a8927a 4pub trait IdFunctor: Sized {
fc512014
XL
5 type Inner;
6
a2a8927a 7 fn try_map_id<F, E>(self, f: F) -> Result<Self, E>
fc512014 8 where
a2a8927a 9 F: FnMut(Self::Inner) -> Result<Self::Inner, E>;
fc512014
XL
10}
11
12impl<T> IdFunctor for Box<T> {
13 type Inner = T;
14
15 #[inline]
a2a8927a 16 fn try_map_id<F, E>(self, mut f: F) -> Result<Self, E>
fc512014 17 where
a2a8927a 18 F: FnMut(Self::Inner) -> Result<Self::Inner, E>,
fc512014
XL
19 {
20 let raw = Box::into_raw(self);
a2a8927a 21 Ok(unsafe {
fc512014 22 // SAFETY: The raw pointer points to a valid value of type `T`.
a2a8927a 23 let value = raw.read();
fc512014
XL
24 // SAFETY: Converts `Box<T>` to `Box<MaybeUninit<T>>` which is the
25 // inverse of `Box::assume_init()` and should be safe.
a2a8927a 26 let raw: Box<mem::MaybeUninit<T>> = Box::from_raw(raw.cast());
fc512014 27 // SAFETY: Write the mapped value back into the `Box`.
a2a8927a
XL
28 Box::write(raw, f(value)?)
29 })
fc512014
XL
30 }
31}
32
33impl<T> IdFunctor for Vec<T> {
34 type Inner = T;
35
36 #[inline]
a2a8927a 37 fn try_map_id<F, E>(self, mut f: F) -> Result<Self, E>
fc512014 38 where
a2a8927a 39 F: FnMut(Self::Inner) -> Result<Self::Inner, E>,
fc512014 40 {
a2a8927a
XL
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
fc512014 58 unsafe {
a2a8927a
XL
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;
fc512014 69 }
a2a8927a
XL
70
71 mem::forget(hole_vec);
72 Ok(Vec::from_raw_parts(ptr, length, capacity))
fc512014 73 }
fc512014
XL
74 }
75}
76
77impl<T> IdFunctor for Box<[T]> {
78 type Inner = T;
79
80 #[inline]
a2a8927a 81 fn try_map_id<F, E>(self, f: F) -> Result<Self, E>
fc512014 82 where
a2a8927a 83 F: FnMut(Self::Inner) -> Result<Self::Inner, E>,
fc512014 84 {
a2a8927a 85 Vec::from(self).try_map_id(f).map(Into::into)
fc512014
XL
86 }
87}
88
89impl<I: Idx, T> IdFunctor for IndexVec<I, T> {
90 type Inner = T;
91
92 #[inline]
a2a8927a 93 fn try_map_id<F, E>(self, f: F) -> Result<Self, E>
fc512014 94 where
a2a8927a 95 F: FnMut(Self::Inner) -> Result<Self::Inner, E>,
fc512014 96 {
a2a8927a 97 self.raw.try_map_id(f).map(IndexVec::from_raw)
fc512014
XL
98 }
99}