Skip to content

Commit 3ec6720

Browse files
committed
add IdFunctor to rustc_data_structures
1 parent f5230fb commit 3ec6720

File tree

1 file changed

+82
-0
lines changed

1 file changed

+82
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
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: Convert's `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+
}

0 commit comments

Comments
 (0)