about summary refs log tree commit diff
path: root/compiler
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2021-12-11 10:37:52 +0000
committerbors <bors@rust-lang.org>2021-12-11 10:37:52 +0000
commitb9a37ad0d995c71518629b032f8e816e1efa8bca (patch)
tree57b8f04dfb65960fab67fea155d939ab6a8f8886 /compiler
parent4a66a704b2c3d30ff07d89380ebb9ba3de3b3182 (diff)
parent5da73311be4c6cefc557c8615d39b0e44ef8de95 (diff)
downloadrust-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.rs53
-rw-r--r--compiler/rustc_data_structures/src/lib.rs1
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)]