diff options
| author | bors <bors@rust-lang.org> | 2021-12-11 10:37:52 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2021-12-11 10:37:52 +0000 |
| commit | b9a37ad0d995c71518629b032f8e816e1efa8bca (patch) | |
| tree | 57b8f04dfb65960fab67fea155d939ab6a8f8886 /compiler | |
| parent | 4a66a704b2c3d30ff07d89380ebb9ba3de3b3182 (diff) | |
| parent | 5da73311be4c6cefc557c8615d39b0e44ef8de95 (diff) | |
| download | rust-b9a37ad0d995c71518629b032f8e816e1efa8bca.tar.gz rust-b9a37ad0d995c71518629b032f8e816e1efa8bca.zip | |
Auto merge of #91776 - matthiaskrgr:rollup-tlb4bw1, r=matthiaskrgr
Rollup of 6 pull requests
Successful merges:
- #91127 (Add `<*{const|mut} T>::{to|from}_bits`)
- #91310 (Add --out-dir flag for rustdoc)
- #91373 (Add needs-unwind to tests that depend on panicking)
- #91426 (Make IdFunctor::try_map_id panic-safe)
- #91515 (Add rsplit_array variants to slices and arrays)
- #91553 (socket ancillary data implementation for dragonflybsd.)
Failed merges:
r? `@ghost`
`@rustbot` modify labels: rollup
Diffstat (limited to 'compiler')
| -rw-r--r-- | compiler/rustc_data_structures/src/functor.rs | 53 | ||||
| -rw-r--r-- | compiler/rustc_data_structures/src/lib.rs | 1 |
2 files changed, 30 insertions, 24 deletions
diff --git a/compiler/rustc_data_structures/src/functor.rs b/compiler/rustc_data_structures/src/functor.rs index 71ff762c714..a3d3f988344 100644 --- a/compiler/rustc_data_structures/src/functor.rs +++ b/compiler/rustc_data_structures/src/functor.rs @@ -34,38 +34,43 @@ impl<T> IdFunctor for Vec<T> { type Inner = T; #[inline] - fn try_map_id<F, E>(mut self, mut f: F) -> Result<Self, E> + fn try_map_id<F, E>(self, mut f: F) -> Result<Self, E> where F: FnMut(Self::Inner) -> Result<Self::Inner, E>, { - // FIXME: We don't really care about panics here and leak - // far more than we should, but that should be fine for now. - let len = self.len(); - unsafe { - self.set_len(0); - let start = self.as_mut_ptr(); - for i in 0..len { - let p = start.add(i); - match f(p.read()) { - Ok(val) => p.write(val), - Err(err) => { - // drop all other elements in self - // (current element was "moved" into the call to f) - for j in (0..i).chain(i + 1..len) { - start.add(j).drop_in_place(); - } + struct HoleVec<T> { + vec: Vec<mem::ManuallyDrop<T>>, + hole: Option<usize>, + } - // returning will drop self, releasing the allocation - // (len is 0 so elements will not be re-dropped) - return Err(err); + impl<T> Drop for HoleVec<T> { + fn drop(&mut self) { + unsafe { + for (index, slot) in self.vec.iter_mut().enumerate() { + if self.hole != Some(index) { + mem::ManuallyDrop::drop(slot); + } } } } - // Even if we encountered an error, set the len back - // so we don't leak memory. - self.set_len(len); } - Ok(self) + + 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)) + } } } diff --git a/compiler/rustc_data_structures/src/lib.rs b/compiler/rustc_data_structures/src/lib.rs index e17724b72f8..181e5180d53 100644 --- a/compiler/rustc_data_structures/src/lib.rs +++ b/compiler/rustc_data_structures/src/lib.rs @@ -23,6 +23,7 @@ #![feature(once_cell)] #![feature(test)] #![feature(thread_id_value)] +#![feature(vec_into_raw_parts)] #![allow(rustc::default_hash_types)] #![deny(unaligned_references)] |
