]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_data_structures/src/functor.rs
Auto merge of #85053 - camsteffen:duplicate-lint, r=davidtwco
[rust.git] / compiler / rustc_data_structures / src / functor.rs
1 use rustc_index::vec::{Idx, IndexVec};
2 use std::mem;
3 use std::ptr;
4
5 pub trait IdFunctor {
6     type Inner;
7
8     fn map_id<F>(self, f: F) -> Self
9     where
10         F: FnMut(Self::Inner) -> Self::Inner;
11 }
12
13 impl<T> IdFunctor for Box<T> {
14     type Inner = T;
15
16     #[inline]
17     fn map_id<F>(self, mut f: F) -> Self
18     where
19         F: FnMut(Self::Inner) -> Self::Inner,
20     {
21         let raw = Box::into_raw(self);
22         unsafe {
23             // SAFETY: The raw pointer points to a valid value of type `T`.
24             let value = ptr::read(raw);
25             // SAFETY: Converts `Box<T>` to `Box<MaybeUninit<T>>` which is the
26             // inverse of `Box::assume_init()` and should be safe.
27             let mut raw: Box<mem::MaybeUninit<T>> = Box::from_raw(raw.cast());
28             // SAFETY: Write the mapped value back into the `Box`.
29             ptr::write(raw.as_mut_ptr(), f(value));
30             // SAFETY: We just initialized `raw`.
31             raw.assume_init()
32         }
33     }
34 }
35
36 impl<T> IdFunctor for Vec<T> {
37     type Inner = T;
38
39     #[inline]
40     fn map_id<F>(mut self, mut f: F) -> Self
41     where
42         F: FnMut(Self::Inner) -> Self::Inner,
43     {
44         // FIXME: We don't really care about panics here and leak
45         // far more than we should, but that should be fine for now.
46         let len = self.len();
47         unsafe {
48             self.set_len(0);
49             let start = self.as_mut_ptr();
50             for i in 0..len {
51                 let p = start.add(i);
52                 ptr::write(p, f(ptr::read(p)));
53             }
54             self.set_len(len);
55         }
56         self
57     }
58 }
59
60 impl<T> IdFunctor for Box<[T]> {
61     type Inner = T;
62
63     #[inline]
64     fn map_id<F>(self, f: F) -> Self
65     where
66         F: FnMut(Self::Inner) -> Self::Inner,
67     {
68         Vec::from(self).map_id(f).into()
69     }
70 }
71
72 impl<I: Idx, T> IdFunctor for IndexVec<I, T> {
73     type Inner = T;
74
75     #[inline]
76     fn map_id<F>(self, f: F) -> Self
77     where
78         F: FnMut(Self::Inner) -> Self::Inner,
79     {
80         IndexVec::from_raw(self.raw.map_id(f))
81     }
82 }