]> git.lizzy.rs Git - rust.git/commitdiff
Rollup merge of #67300 - aloucks:issue-65970, r=rkruppe
authorMazdak Farrokhzad <twingoow@gmail.com>
Sun, 15 Dec 2019 04:57:27 +0000 (05:57 +0100)
committerGitHub <noreply@github.com>
Sun, 15 Dec 2019 04:57:27 +0000 (05:57 +0100)
Restore original implementation of Vec::retain

This PR reverts #48065, which aimed to optimize `Vec::retain` by making use of `Vec::drain_filter`. Unfortunately at that time, `drain_filter` was unsound.

The soundness hole in `Vec::drain_filter` was fixed in #61224 by guaranteeing that cleanup logic runs via a nested `Drop`, even in the event of a panic. Implementing this nested drop affects codegen (apparently?) and results in slower code.

Fixes #65970

1  2 
src/liballoc/vec.rs

diff --combined src/liballoc/vec.rs
index 52b45b0b8fe079ded0a0182b357462c659465eeb,e5abfdd52022ae72d68f82af7d2232f5bcc0d1c5..2ad4e22884ea77630388bfc2dc42c3fdc7d20dd4
@@@ -315,10 -315,6 +315,10 @@@ impl<T> Vec<T> 
      /// let mut vec: Vec<i32> = Vec::new();
      /// ```
      #[inline]
 +    #[cfg_attr(
 +        not(bootstrap),
 +        rustc_const_stable(feature = "const_vec_new", since = "1.32.0"),
 +    )]
      #[stable(feature = "rust1", since = "1.0.0")]
      pub const fn new() -> Vec<T> {
          Vec {
      pub fn retain<F>(&mut self, mut f: F)
          where F: FnMut(&T) -> bool
      {
-         self.drain_filter(|x| !f(x));
+         let len = self.len();
+         let mut del = 0;
+         {
+             let v = &mut **self;
+             for i in 0..len {
+                 if !f(&v[i]) {
+                     del += 1;
+                 } else if del > 0 {
+                     v.swap(i - del, i);
+                 }
+             }
+         }
+         if del > 0 {
+             self.truncate(len - del);
+         }
      }
  
      /// Removes all but the first of consecutive elements in the vector that resolve to the same