diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index 116b2720f39a4..d9bf95d13ac17 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -23,7 +23,7 @@ use crate::builder::{Builder, RunConfig, ShouldRun, Step}; use crate::compile; use crate::tool::{self, Tool}; use crate::cache::{INTERNER, Interned}; -use time; +use time::{self, Timespec}; pub fn pkgname(builder: &Builder, component: &str) -> String { if component == "cargo" { @@ -528,7 +528,19 @@ impl Step for Rustc { t!(fs::create_dir_all(image.join("share/man/man1"))); let man_src = builder.src.join("src/doc/man"); let man_dst = image.join("share/man/man1"); - let month_year = t!(time::strftime("%B %Y", &time::now())); + + // Reproducible builds: If SOURCE_DATE_EPOCH is set, use that as the time. + let time = env::var("SOURCE_DATE_EPOCH") + .map(|timestamp| { + let epoch = timestamp.parse().map_err(|err| { + format!("could not parse SOURCE_DATE_EPOCH: {}", err) + }).unwrap(); + + time::at(Timespec::new(epoch, 0)) + }) + .unwrap_or_else(|_| time::now()); + + let month_year = t!(time::strftime("%B %Y", &time)); // don't use our `bootstrap::util::{copy, cp_r}`, because those try // to hardlink, and we don't want to edit the source templates for file_entry in builder.read_dir(&man_src) { diff --git a/src/liballoc/collections/vec_deque.rs b/src/liballoc/collections/vec_deque.rs index b3f7ef5fd6ecc..579d7de96e6da 100644 --- a/src/liballoc/collections/vec_deque.rs +++ b/src/liballoc/collections/vec_deque.rs @@ -12,7 +12,7 @@ use core::fmt; use core::iter::{repeat_with, FromIterator, FusedIterator}; use core::mem; use core::ops::Bound::{Excluded, Included, Unbounded}; -use core::ops::{Index, IndexMut, RangeBounds}; +use core::ops::{Index, IndexMut, RangeBounds, Try}; use core::ptr; use core::ptr::NonNull; use core::slice; @@ -2172,6 +2172,14 @@ impl<'a, T> Iterator for Iter<'a, T> { accum = front.iter().fold(accum, &mut f); back.iter().fold(accum, &mut f) } + + fn try_fold(&mut self, init: B, mut f: F) -> R where + Self: Sized, F: FnMut(B, Self::Item) -> R, R: Try + { + let (front, back) = RingSlices::ring_slices(self.ring, self.head, self.tail); + let accum = front.iter().try_fold(init, &mut f)?; + back.iter().try_fold(accum, &mut f) + } } #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs index d2ff1bae63561..5165a7ca5a8f3 100644 --- a/src/liballoc/lib.rs +++ b/src/liballoc/lib.rs @@ -113,6 +113,7 @@ #![feature(slice_partition_dedup)] #![feature(maybe_uninit)] #![feature(alloc_layout_extra)] +#![feature(try_trait)] // Allow testing this library diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index c0dc010fe59a5..5efb74bc12080 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -433,6 +433,27 @@ impl Rc { } } + /// Consumes the `Rc`, returning the wrapped pointer as `NonNull`. + /// + /// # Examples + /// + /// ``` + /// #![feature(rc_into_raw_non_null)] + /// + /// use std::rc::Rc; + /// + /// let x = Rc::new(10); + /// let ptr = Rc::into_raw_non_null(x); + /// let deref = unsafe { *ptr.as_ref() }; + /// assert_eq!(deref, 10); + /// ``` + #[unstable(feature = "rc_into_raw_non_null", issue = "47336")] + #[inline] + pub fn into_raw_non_null(this: Self) -> NonNull { + // safe because Rc guarantees its pointer is non-null + unsafe { NonNull::new_unchecked(Rc::into_raw(this) as *mut _) } + } + /// Creates a new [`Weak`][weak] pointer to this value. /// /// [weak]: struct.Weak.html diff --git a/src/liballoc/sync.rs b/src/liballoc/sync.rs index 390a079165054..5cffa93db11d4 100644 --- a/src/liballoc/sync.rs +++ b/src/liballoc/sync.rs @@ -413,6 +413,27 @@ impl Arc { } } + /// Consumes the `Arc`, returning the wrapped pointer as `NonNull`. + /// + /// # Examples + /// + /// ``` + /// #![feature(rc_into_raw_non_null)] + /// + /// use std::sync::Arc; + /// + /// let x = Arc::new(10); + /// let ptr = Arc::into_raw_non_null(x); + /// let deref = unsafe { *ptr.as_ref() }; + /// assert_eq!(deref, 10); + /// ``` + #[unstable(feature = "rc_into_raw_non_null", issue = "47336")] + #[inline] + pub fn into_raw_non_null(this: Self) -> NonNull { + // safe because Arc guarantees its pointer is non-null + unsafe { NonNull::new_unchecked(Arc::into_raw(this) as *mut _) } + } + /// Creates a new [`Weak`][weak] pointer to this value. /// /// [weak]: struct.Weak.html diff --git a/src/liballoc/tests/vec_deque.rs b/src/liballoc/tests/vec_deque.rs index 76831ba65e3b8..e2896cffea092 100644 --- a/src/liballoc/tests/vec_deque.rs +++ b/src/liballoc/tests/vec_deque.rs @@ -1433,3 +1433,41 @@ fn test_rotate_right_random() { } } } + +#[test] +fn test_try_fold_empty() { + assert_eq!(Some(0), VecDeque::::new().iter().try_fold(0, |_, _| None)); +} + +#[test] +fn test_try_fold_none() { + let v: VecDeque = (0..12).collect(); + assert_eq!(None, v.into_iter().try_fold(0, |a, b| + if b < 11 { Some(a + b) } else { None })); +} + +#[test] +fn test_try_fold_ok() { + let v: VecDeque = (0..12).collect(); + assert_eq!(Ok::<_, ()>(66), v.into_iter().try_fold(0, |a, b| Ok(a + b))); +} + +#[test] +fn test_try_fold_unit() { + let v: VecDeque<()> = std::iter::repeat(()).take(42).collect(); + assert_eq!(Some(()), v.into_iter().try_fold((), |(), ()| Some(()))); +} + +#[test] +fn test_try_fold_rotated() { + let mut v: VecDeque<_> = (0..12).collect(); + for n in 0..30 { + if n & 1 == 0 { + let r = v[n]; + v.rotate_left(n ^ r); + } else { + v.rotate_right(n % 11); + } + assert_eq!(Ok::<_, ()>(66), v.into_iter().try_fold(0, |a, b| Ok(a + b))); + } +} diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs index ac92018563654..80f324b805725 100644 --- a/src/libcore/str/mod.rs +++ b/src/libcore/str/mod.rs @@ -3489,6 +3489,8 @@ impl str { /// /// assert_eq!("Hello\tworld", s.trim()); /// ``` + #[must_use = "this returns the trimmed string as a slice, \ + without modifying the original"] #[stable(feature = "rust1", since = "1.0.0")] pub fn trim(&self) -> &str { self.trim_matches(|c: char| c.is_whitespace()) @@ -3524,6 +3526,8 @@ impl str { /// let s = " עברית "; /// assert!(Some('ע') == s.trim_start().chars().next()); /// ``` + #[must_use = "this returns the trimmed string as a new slice, \ + without modifying the original"] #[stable(feature = "trim_direction", since = "1.30.0")] pub fn trim_start(&self) -> &str { self.trim_start_matches(|c: char| c.is_whitespace()) @@ -3559,6 +3563,8 @@ impl str { /// let s = " עברית "; /// assert!(Some('ת') == s.trim_end().chars().rev().next()); /// ``` + #[must_use = "this returns the trimmed string as a new slice, \ + without modifying the original"] #[stable(feature = "trim_direction", since = "1.30.0")] pub fn trim_end(&self) -> &str { self.trim_end_matches(|c: char| c.is_whitespace()) @@ -3661,6 +3667,8 @@ impl str { /// ``` /// assert_eq!("1foo1barXX".trim_matches(|c| c == '1' || c == 'X'), "foo1bar"); /// ``` + #[must_use = "this returns the trimmed string as a new slice, \ + without modifying the original"] #[stable(feature = "rust1", since = "1.0.0")] pub fn trim_matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> &'a str where P::Searcher: DoubleEndedSearcher<'a> @@ -3706,6 +3714,8 @@ impl str { /// let x: &[_] = &['1', '2']; /// assert_eq!("12foo1bar12".trim_start_matches(x), "foo1bar12"); /// ``` + #[must_use = "this returns the trimmed string as a new slice, \ + without modifying the original"] #[stable(feature = "trim_direction", since = "1.30.0")] pub fn trim_start_matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> &'a str { let mut i = self.len(); @@ -3749,6 +3759,8 @@ impl str { /// ``` /// assert_eq!("1fooX".trim_end_matches(|c| c == '1' || c == 'X'), "1foo"); /// ``` + #[must_use = "this returns the trimmed string as a new slice, \ + without modifying the original"] #[stable(feature = "trim_direction", since = "1.30.0")] pub fn trim_end_matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> &'a str where P::Searcher: ReverseSearcher<'a>