about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/bootstrap/builder.rs10
-rw-r--r--src/libcore/iter/adapters/chain.rs22
-rw-r--r--src/libcore/slice/mod.rs16
-rw-r--r--src/libcore/tests/iter.rs48
-rw-r--r--src/libcore/tests/slice.rs19
-rw-r--r--src/librustc_driver/Cargo.toml1
-rw-r--r--src/librustc_plugin/deprecated/lib.rs2
-rw-r--r--src/libstd/io/mod.rs66
-rw-r--r--src/libstd/sys/unix/process/process_common.rs54
-rw-r--r--src/libstd/sys/unix/process/process_unix.rs13
10 files changed, 189 insertions, 62 deletions
diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs
index f0054c36c0c..afde076a35a 100644
--- a/src/bootstrap/builder.rs
+++ b/src/bootstrap/builder.rs
@@ -859,12 +859,12 @@ impl<'a> Builder<'a> {
             stage = compiler.stage;
         }
 
-        let mut extra_args = env::var(&format!("RUSTFLAGS_STAGE_{}", stage)).unwrap_or_default();
+        let mut extra_args = String::new();
         if stage != 0 {
-            let s = env::var("RUSTFLAGS_STAGE_NOT_0").unwrap_or_default();
-            if !extra_args.is_empty() {
-                extra_args.push_str(" ");
-            }
+            let s = env::var("RUSTFLAGS_NOT_BOOTSTRAP").unwrap_or_default();
+            extra_args.push_str(&s);
+        } else {
+            let s = env::var("RUSTFLAGS_BOOTSTRAP").unwrap_or_default();
             extra_args.push_str(&s);
         }
 
diff --git a/src/libcore/iter/adapters/chain.rs b/src/libcore/iter/adapters/chain.rs
index 0b9f7f6b609..c9612596b1b 100644
--- a/src/libcore/iter/adapters/chain.rs
+++ b/src/libcore/iter/adapters/chain.rs
@@ -173,17 +173,23 @@ impl<A, B> Iterator for Chain<A, B> where
 
     #[inline]
     fn size_hint(&self) -> (usize, Option<usize>) {
-        let (a_lower, a_upper) = self.a.size_hint();
-        let (b_lower, b_upper) = self.b.size_hint();
+        match self.state {
+            ChainState::Both => {
+                let (a_lower, a_upper) = self.a.size_hint();
+                let (b_lower, b_upper) = self.b.size_hint();
 
-        let lower = a_lower.saturating_add(b_lower);
+                let lower = a_lower.saturating_add(b_lower);
 
-        let upper = match (a_upper, b_upper) {
-            (Some(x), Some(y)) => x.checked_add(y),
-            _ => None
-        };
+                let upper = match (a_upper, b_upper) {
+                    (Some(x), Some(y)) => x.checked_add(y),
+                    _ => None
+                };
 
-        (lower, upper)
+                (lower, upper)
+            }
+            ChainState::Front => self.a.size_hint(),
+            ChainState::Back => self.b.size_hint(),
+        }
     }
 }
 
diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs
index ce5af13d4ca..bfbbb15c8d4 100644
--- a/src/libcore/slice/mod.rs
+++ b/src/libcore/slice/mod.rs
@@ -4637,6 +4637,22 @@ impl<'a, T> DoubleEndedIterator for ChunksExactMut<'a, T> {
             Some(tail)
         }
     }
+
+    #[inline]
+    fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
+        let len = self.len();
+        if n >= len {
+            self.v = &mut [];
+            None
+        } else {
+            let start = (len - 1 - n) * self.chunk_size;
+            let end = start + self.chunk_size;
+            let (temp, _tail) = mem::replace(&mut self.v, &mut []).split_at_mut(end);
+            let (head, nth_back) = temp.split_at_mut(start);
+            self.v = head;
+            Some(nth_back)
+        }
+    }
 }
 
 #[stable(feature = "chunks_exact", since = "1.31.0")]
diff --git a/src/libcore/tests/iter.rs b/src/libcore/tests/iter.rs
index a1a27e1d538..3a4f76852a0 100644
--- a/src/libcore/tests/iter.rs
+++ b/src/libcore/tests/iter.rs
@@ -153,6 +153,54 @@ fn test_iterator_chain_find() {
 }
 
 #[test]
+fn test_iterator_chain_size_hint() {
+    struct Iter {
+        is_empty: bool,
+    }
+
+    impl Iterator for Iter {
+        type Item = ();
+
+        // alternates between `None` and `Some(())`
+        fn next(&mut self) -> Option<Self::Item> {
+            if self.is_empty {
+                self.is_empty = false;
+                None
+            } else {
+                self.is_empty = true;
+                Some(())
+            }
+        }
+
+        fn size_hint(&self) -> (usize, Option<usize>) {
+            if self.is_empty {
+                (0, Some(0))
+            } else {
+                (1, Some(1))
+            }
+        }
+    }
+
+    impl DoubleEndedIterator for Iter {
+        fn next_back(&mut self) -> Option<Self::Item> {
+            self.next()
+        }
+    }
+
+    // this chains an iterator of length 0 with an iterator of length 1,
+    // so after calling `.next()` once, the iterator is empty and the
+    // state is `ChainState::Back`. `.size_hint()` should now disregard
+    // the size hint of the left iterator
+    let mut iter = Iter { is_empty: true }.chain(once(()));
+    assert_eq!(iter.next(), Some(()));
+    assert_eq!(iter.size_hint(), (0, Some(0)));
+
+    let mut iter = once(()).chain(Iter { is_empty: true });
+    assert_eq!(iter.next_back(), Some(()));
+    assert_eq!(iter.size_hint(), (0, Some(0)));
+}
+
+#[test]
 fn test_zip_nth() {
     let xs = [0, 1, 2, 4, 5];
     let ys = [10, 11, 12];
diff --git a/src/libcore/tests/slice.rs b/src/libcore/tests/slice.rs
index 4790152512a..6609bc3135a 100644
--- a/src/libcore/tests/slice.rs
+++ b/src/libcore/tests/slice.rs
@@ -375,6 +375,25 @@ fn test_chunks_exact_mut_nth() {
 }
 
 #[test]
+fn test_chunks_exact_mut_nth_back() {
+    let v: &mut [i32] = &mut [0, 1, 2, 3, 4, 5];
+    let mut c = v.chunks_exact_mut(2);
+    assert_eq!(c.nth_back(1).unwrap(), &[2, 3]);
+    assert_eq!(c.next().unwrap(), &[0, 1]);
+    assert_eq!(c.next(), None);
+
+    let v2: &mut [i32] = &mut [0, 1, 2, 3, 4];
+    let mut c2 = v2.chunks_exact_mut(3);
+    assert_eq!(c2.nth_back(0).unwrap(), &[0, 1, 2]);
+    assert_eq!(c2.next(), None);
+    assert_eq!(c2.next_back(), None);
+
+    let v3: &mut [i32] = &mut [0, 1, 2, 3, 4];
+    let mut c3 = v3.chunks_exact_mut(10);
+    assert_eq!(c3.nth_back(0), None);
+}
+
+#[test]
 fn test_chunks_exact_mut_last() {
     let v: &mut [i32] = &mut [0, 1, 2, 3, 4, 5];
     let c = v.chunks_exact_mut(2);
diff --git a/src/librustc_driver/Cargo.toml b/src/librustc_driver/Cargo.toml
index f7a423092ac..b030517e28e 100644
--- a/src/librustc_driver/Cargo.toml
+++ b/src/librustc_driver/Cargo.toml
@@ -20,6 +20,7 @@ rustc_data_structures = { path = "../librustc_data_structures" }
 errors = { path = "../librustc_errors", package = "rustc_errors" }
 rustc_metadata = { path = "../librustc_metadata" }
 rustc_mir = { path = "../librustc_mir" }
+rustc_plugin = { path = "../librustc_plugin/deprecated" } # To get this in the sysroot
 rustc_plugin_impl = { path = "../librustc_plugin" }
 rustc_save_analysis = { path = "../librustc_save_analysis" }
 rustc_codegen_utils = { path = "../librustc_codegen_utils" }
diff --git a/src/librustc_plugin/deprecated/lib.rs b/src/librustc_plugin/deprecated/lib.rs
index 5fb18066759..1d0afe84c25 100644
--- a/src/librustc_plugin/deprecated/lib.rs
+++ b/src/librustc_plugin/deprecated/lib.rs
@@ -1,6 +1,6 @@
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/")]
 #![feature(staged_api)]
-#![unstable(feature = "rustc_plugin", issue = "29597")]
+#![unstable(feature = "rustc_private", issue = "27812")]
 #![rustc_deprecated(since = "1.38.0", reason = "\
     import this through `rustc_driver::plugin` instead to make TLS work correctly. \
     See https://github.com/rust-lang/rust/issues/62717")]
diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs
index f2b6ce6feb2..5060f368229 100644
--- a/src/libstd/io/mod.rs
+++ b/src/libstd/io/mod.rs
@@ -353,12 +353,17 @@ fn append_to_string<F>(buf: &mut String, f: F) -> Result<usize>
 // Because we're extending the buffer with uninitialized data for trusted
 // readers, we need to make sure to truncate that if any of this panics.
 fn read_to_end<R: Read + ?Sized>(r: &mut R, buf: &mut Vec<u8>) -> Result<usize> {
-    read_to_end_with_reservation(r, buf, 32)
+    read_to_end_with_reservation(r, buf, |_| 32)
 }
 
-fn read_to_end_with_reservation<R: Read + ?Sized>(r: &mut R,
-                                                  buf: &mut Vec<u8>,
-                                                  reservation_size: usize) -> Result<usize>
+fn read_to_end_with_reservation<R, F>(
+    r: &mut R,
+    buf: &mut Vec<u8>,
+    mut reservation_size: F,
+) -> Result<usize>
+where
+    R: Read + ?Sized,
+    F: FnMut(&R) -> usize,
 {
     let start_len = buf.len();
     let mut g = Guard { len: buf.len(), buf: buf };
@@ -366,7 +371,7 @@ fn read_to_end_with_reservation<R: Read + ?Sized>(r: &mut R,
     loop {
         if g.len == g.buf.len() {
             unsafe {
-                g.buf.reserve(reservation_size);
+                g.buf.reserve(reservation_size(r));
                 let capacity = g.buf.capacity();
                 g.buf.set_len(capacity);
                 r.initializer().initialize(&mut g.buf[g.len..]);
@@ -2253,9 +2258,10 @@ impl<T: Read> Read for Take<T> {
     }
 
     fn read_to_end(&mut self, buf: &mut Vec<u8>) -> Result<usize> {
-        let reservation_size = cmp::min(self.limit, 32) as usize;
-
-        read_to_end_with_reservation(self, buf, reservation_size)
+        // Pass in a reservation_size closure that respects the current value
+        // of limit for each read. If we hit the read limit, this prevents the
+        // final zero-byte read from allocating again.
+        read_to_end_with_reservation(self, buf, |self_| cmp::min(self_.limit, 32) as usize)
     }
 }
 
@@ -2378,6 +2384,7 @@ impl<B: BufRead> Iterator for Lines<B> {
 
 #[cfg(test)]
 mod tests {
+    use crate::cmp;
     use crate::io::prelude::*;
     use super::{Cursor, SeekFrom, repeat};
     use crate::io::{self, IoSlice, IoSliceMut};
@@ -2651,6 +2658,49 @@ mod tests {
         Ok(())
     }
 
+    // A simple example reader which uses the default implementation of
+    // read_to_end.
+    struct ExampleSliceReader<'a> {
+        slice: &'a [u8],
+    }
+
+    impl<'a> Read for ExampleSliceReader<'a> {
+        fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
+            let len = cmp::min(self.slice.len(), buf.len());
+            buf[..len].copy_from_slice(&self.slice[..len]);
+            self.slice = &self.slice[len..];
+            Ok(len)
+        }
+    }
+
+    #[test]
+    fn test_read_to_end_capacity() -> io::Result<()> {
+        let input = &b"foo"[..];
+
+        // read_to_end() generally needs to over-allocate, both for efficiency
+        // and so that it can distinguish EOF. Assert that this is the case
+        // with this simple ExampleSliceReader struct, which uses the default
+        // implementation of read_to_end. Even though vec1 is allocated with
+        // exactly enough capacity for the read, read_to_end will allocate more
+        // space here.
+        let mut vec1 = Vec::with_capacity(input.len());
+        ExampleSliceReader { slice: input }.read_to_end(&mut vec1)?;
+        assert_eq!(vec1.len(), input.len());
+        assert!(vec1.capacity() > input.len(), "allocated more");
+
+        // However, std::io::Take includes an implementation of read_to_end
+        // that will not allocate when the limit has already been reached. In
+        // this case, vec2 never grows.
+        let mut vec2 = Vec::with_capacity(input.len());
+        ExampleSliceReader { slice: input }
+            .take(input.len() as u64)
+            .read_to_end(&mut vec2)?;
+        assert_eq!(vec2.len(), input.len());
+        assert_eq!(vec2.capacity(), input.len(), "did not allocate more");
+
+        Ok(())
+    }
+
     #[test]
     fn io_slice_mut_advance() {
         let mut buf1 = [1; 8];
diff --git a/src/libstd/sys/unix/process/process_common.rs b/src/libstd/sys/unix/process/process_common.rs
index 6bb20bbe087..21fca23a8fe 100644
--- a/src/libstd/sys/unix/process/process_common.rs
+++ b/src/libstd/sys/unix/process/process_common.rs
@@ -20,6 +20,30 @@ cfg_if::cfg_if! {
     }
 }
 
+// Android with api less than 21 define sig* functions inline, so it is not
+// available for dynamic link. Implementing sigemptyset and sigaddset allow us
+// to support older Android version (independent of libc version).
+// The following implementations are based on https://git.io/vSkNf
+cfg_if::cfg_if! {
+    if #[cfg(target_os = "android")] {
+        pub unsafe fn sigemptyset(set: *mut libc::sigset_t) -> libc::c_int {
+            set.write_bytes(0u8, 1);
+            return 0;
+        }
+        #[allow(dead_code)]
+        pub unsafe fn sigaddset(set: *mut libc::sigset_t, signum: libc::c_int) -> libc::c_int {
+            use crate::{slice, mem};
+
+            let raw = slice::from_raw_parts_mut(set as *mut u8, mem::size_of::<libc::sigset_t>());
+            let bit = (signum - 1) as usize;
+            raw[bit / 8] |= 1 << (bit % 8);
+            return 0;
+        }
+    } else {
+        pub use libc::{sigemptyset, sigaddset};
+    }
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // Command
 ////////////////////////////////////////////////////////////////////////////////
@@ -429,36 +453,6 @@ mod tests {
         }
     }
 
-    // Android with api less than 21 define sig* functions inline, so it is not
-    // available for dynamic link. Implementing sigemptyset and sigaddset allow us
-    // to support older Android version (independent of libc version).
-    // The following implementations are based on https://git.io/vSkNf
-
-    #[cfg(not(target_os = "android"))]
-    extern {
-        #[cfg_attr(target_os = "netbsd", link_name = "__sigemptyset14")]
-        fn sigemptyset(set: *mut libc::sigset_t) -> libc::c_int;
-
-        #[cfg_attr(target_os = "netbsd", link_name = "__sigaddset14")]
-        fn sigaddset(set: *mut libc::sigset_t, signum: libc::c_int) -> libc::c_int;
-    }
-
-    #[cfg(target_os = "android")]
-    unsafe fn sigemptyset(set: *mut libc::sigset_t) -> libc::c_int {
-        set.write_bytes(0u8, 1);
-        return 0;
-    }
-
-    #[cfg(target_os = "android")]
-    unsafe fn sigaddset(set: *mut libc::sigset_t, signum: libc::c_int) -> libc::c_int {
-        use crate::slice;
-
-        let raw = slice::from_raw_parts_mut(set as *mut u8, mem::size_of::<libc::sigset_t>());
-        let bit = (signum - 1) as usize;
-        raw[bit / 8] |= 1 << (bit % 8);
-        return 0;
-    }
-
     // See #14232 for more information, but it appears that signal delivery to a
     // newly spawned process may just be raced in the macOS, so to prevent this
     // test from being flaky we ignore it on macOS.
diff --git a/src/libstd/sys/unix/process/process_unix.rs b/src/libstd/sys/unix/process/process_unix.rs
index 327d82e60cf..a9711c71b7a 100644
--- a/src/libstd/sys/unix/process/process_unix.rs
+++ b/src/libstd/sys/unix/process/process_unix.rs
@@ -214,14 +214,7 @@ impl Command {
             // need to clean things up now to avoid confusing the program
             // we're about to run.
             let mut set = MaybeUninit::<libc::sigset_t>::uninit();
-            if cfg!(target_os = "android") {
-                // Implementing sigemptyset allow us to support older Android
-                // versions. See the comment about Android and sig* functions in
-                // process_common.rs
-                set.as_mut_ptr().write_bytes(0u8, 1);
-            } else {
-                cvt(libc::sigemptyset(set.as_mut_ptr()))?;
-            }
+            cvt(sigemptyset(set.as_mut_ptr()))?;
             cvt(libc::pthread_sigmask(libc::SIG_SETMASK, set.as_ptr(),
                                          ptr::null_mut()))?;
             let ret = sys::signal(libc::SIGPIPE, libc::SIG_DFL);
@@ -363,10 +356,10 @@ impl Command {
             }
 
             let mut set = MaybeUninit::<libc::sigset_t>::uninit();
-            cvt(libc::sigemptyset(set.as_mut_ptr()))?;
+            cvt(sigemptyset(set.as_mut_ptr()))?;
             cvt(libc::posix_spawnattr_setsigmask(attrs.0.as_mut_ptr(),
                                                  set.as_ptr()))?;
-            cvt(libc::sigaddset(set.as_mut_ptr(), libc::SIGPIPE))?;
+            cvt(sigaddset(set.as_mut_ptr(), libc::SIGPIPE))?;
             cvt(libc::posix_spawnattr_setsigdefault(attrs.0.as_mut_ptr(),
                                                     set.as_ptr()))?;