From 698f8c2f01ea549d77d7dc3338a12e04c11057b9 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Wed, 17 Apr 2024 14:02:58 +0200 Subject: Adding upstream version 1.64.0+dfsg1. Signed-off-by: Daniel Baumann --- compiler/rustc_data_structures/src/functor.rs | 99 +++++++++++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100644 compiler/rustc_data_structures/src/functor.rs (limited to 'compiler/rustc_data_structures/src/functor.rs') diff --git a/compiler/rustc_data_structures/src/functor.rs b/compiler/rustc_data_structures/src/functor.rs new file mode 100644 index 000000000..a3d3f9883 --- /dev/null +++ b/compiler/rustc_data_structures/src/functor.rs @@ -0,0 +1,99 @@ +use rustc_index::vec::{Idx, IndexVec}; +use std::mem; + +pub trait IdFunctor: Sized { + type Inner; + + fn try_map_id(self, f: F) -> Result + where + F: FnMut(Self::Inner) -> Result; +} + +impl IdFunctor for Box { + type Inner = T; + + #[inline] + fn try_map_id(self, mut f: F) -> Result + where + F: FnMut(Self::Inner) -> Result, + { + let raw = Box::into_raw(self); + Ok(unsafe { + // SAFETY: The raw pointer points to a valid value of type `T`. + let value = raw.read(); + // SAFETY: Converts `Box` to `Box>` which is the + // inverse of `Box::assume_init()` and should be safe. + let raw: Box> = Box::from_raw(raw.cast()); + // SAFETY: Write the mapped value back into the `Box`. + Box::write(raw, f(value)?) + }) + } +} + +impl IdFunctor for Vec { + type Inner = T; + + #[inline] + fn try_map_id(self, mut f: F) -> Result + where + F: FnMut(Self::Inner) -> Result, + { + struct HoleVec { + vec: Vec>, + hole: Option, + } + + impl Drop for HoleVec { + fn drop(&mut self) { + unsafe { + for (index, slot) in self.vec.iter_mut().enumerate() { + if self.hole != Some(index) { + mem::ManuallyDrop::drop(slot); + } + } + } + } + } + + unsafe { + let (ptr, length, capacity) = self.into_raw_parts(); + let vec = Vec::from_raw_parts(ptr.cast(), length, capacity); + let mut hole_vec = HoleVec { vec, hole: None }; + + for (index, slot) in hole_vec.vec.iter_mut().enumerate() { + hole_vec.hole = Some(index); + let original = mem::ManuallyDrop::take(slot); + let mapped = f(original)?; + *slot = mem::ManuallyDrop::new(mapped); + hole_vec.hole = None; + } + + mem::forget(hole_vec); + Ok(Vec::from_raw_parts(ptr, length, capacity)) + } + } +} + +impl IdFunctor for Box<[T]> { + type Inner = T; + + #[inline] + fn try_map_id(self, f: F) -> Result + where + F: FnMut(Self::Inner) -> Result, + { + Vec::from(self).try_map_id(f).map(Into::into) + } +} + +impl IdFunctor for IndexVec { + type Inner = T; + + #[inline] + fn try_map_id(self, f: F) -> Result + where + F: FnMut(Self::Inner) -> Result, + { + self.raw.try_map_id(f).map(IndexVec::from_raw) + } +} -- cgit v1.2.3