From b1e481d712fcf3d4b97ebf9e9a049c51701cf5e1 Mon Sep 17 00:00:00 2001 From: Ivan Tham Date: Sat, 12 Sep 2020 13:35:03 +0800 Subject: [PATCH 01/15] Simplify iter zip struct doc --- library/core/src/iter/adapters/zip.rs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/library/core/src/iter/adapters/zip.rs b/library/core/src/iter/adapters/zip.rs index e02de0ce45dff..a854f70dcd0ba 100644 --- a/library/core/src/iter/adapters/zip.rs +++ b/library/core/src/iter/adapters/zip.rs @@ -8,11 +8,8 @@ use super::super::{ /// An iterator that iterates two other iterators simultaneously. /// -/// This `struct` is created by the [`zip`] method on [`Iterator`]. See its -/// documentation for more. -/// -/// [`zip`]: trait.Iterator.html#method.zip -/// [`Iterator`]: trait.Iterator.html +/// This `struct` is created by [`Iterator::zip`]. See its documentation +/// for more. #[derive(Clone)] #[must_use = "iterators are lazy and do nothing unless consumed"] #[stable(feature = "rust1", since = "1.0.0")] From 8a261a2b342d85d11c67a8d4dd3408778bd0f5b7 Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Sat, 12 Sep 2020 13:40:50 +0200 Subject: [PATCH 02/15] Simplify SyncOnceCell's `take` and `drop`. --- library/std/src/lazy.rs | 39 +++++++++++++-------------------------- 1 file changed, 13 insertions(+), 26 deletions(-) diff --git a/library/std/src/lazy.rs b/library/std/src/lazy.rs index 091e2091fb095..e0095e64faf31 100644 --- a/library/std/src/lazy.rs +++ b/library/std/src/lazy.rs @@ -7,7 +7,7 @@ use crate::{ cell::{Cell, UnsafeCell}, fmt, marker::PhantomData, - mem::{self, MaybeUninit}, + mem::MaybeUninit, ops::{Deref, Drop}, panic::{RefUnwindSafe, UnwindSafe}, sync::Once, @@ -316,13 +316,7 @@ impl SyncOnceCell { /// ``` #[unstable(feature = "once_cell", issue = "74465")] pub fn into_inner(mut self) -> Option { - // SAFETY: Safe because we immediately free `self` without dropping - let inner = unsafe { self.take_inner() }; - - // Don't drop this `SyncOnceCell`. We just moved out one of the fields, but didn't set - // the state to uninitialized. - mem::forget(self); - inner + self.take() } /// Takes the value out of this `SyncOnceCell`, moving it back to an uninitialized state. @@ -348,22 +342,12 @@ impl SyncOnceCell { /// ``` #[unstable(feature = "once_cell", issue = "74465")] pub fn take(&mut self) -> Option { - mem::take(self).into_inner() - } - - /// Takes the wrapped value out of a `SyncOnceCell`. - /// Afterwards the cell is no longer initialized. - /// - /// Safety: The cell must now be free'd WITHOUT dropping. No other usages of the cell - /// are valid. Only used by `into_inner` and `drop`. - unsafe fn take_inner(&mut self) -> Option { - // The mutable reference guarantees there are no other threads that can observe us - // taking out the wrapped value. - // Right after this function `self` is supposed to be freed, so it makes little sense - // to atomically set the state to uninitialized. if self.is_initialized() { - let value = mem::replace(&mut self.value, UnsafeCell::new(MaybeUninit::uninit())); - Some(value.into_inner().assume_init()) + self.once = Once::new(); + // SAFETY: `self.value` is initialized and contains a valid `T`. + // `self.once` is reset, so `is_initialized()` will be false again + // which prevents the value from being read twice. + unsafe { Some((&mut *self.value.get()).assume_init_read()) } } else { None } @@ -416,9 +400,12 @@ impl SyncOnceCell { unsafe impl<#[may_dangle] T> Drop for SyncOnceCell { fn drop(&mut self) { - // SAFETY: The cell is being dropped, so it can't be accessed again. - // We also don't touch the `T`, which validates our usage of #[may_dangle]. - unsafe { self.take_inner() }; + if self.is_initialized() { + // Safety: The cell is initialized and being dropped, so it can't + // be accessed again. We also don't touch the `T` other than + // dropping it, which validates our usage of #[may_dangle]. + unsafe { (&mut *self.value.get()).assume_init_drop() }; + } } } From 73e0a56dde24693768d56960023f00ef61f28684 Mon Sep 17 00:00:00 2001 From: Christiaan Dirkx Date: Fri, 4 Sep 2020 20:17:06 +0200 Subject: [PATCH 03/15] Make all methods of `Duration` const Make the following methods of `Duration` unstable const under `duration_const_2`: - `from_secs_f64` - `from_secs_f32` - `mul_f64` - `mul_f32` - `div_f64` - `div_f32` This results in all methods of `Duration` being (unstable) const. Also adds tests for these methods in a const context, moved the test to `library` as part of #76268. Possible because of #72449, which made the relevant `f32` and `f64` methods const. Tracking issue: #72440 --- library/core/src/time.rs | 18 +++-- library/core/tests/lib.rs | 3 + library/core/tests/time.rs | 101 ++++++++++++++++++++++++ src/test/ui/consts/duration-consts-2.rs | 67 ---------------- 4 files changed, 116 insertions(+), 73 deletions(-) delete mode 100644 src/test/ui/consts/duration-consts-2.rs diff --git a/library/core/src/time.rs b/library/core/src/time.rs index f39781788d7c0..6dc542dee58e6 100644 --- a/library/core/src/time.rs +++ b/library/core/src/time.rs @@ -693,7 +693,8 @@ impl Duration { /// ``` #[stable(feature = "duration_float", since = "1.38.0")] #[inline] - pub fn from_secs_f64(secs: f64) -> Duration { + #[rustc_const_unstable(feature = "duration_consts_2", issue = "72440")] + pub const fn from_secs_f64(secs: f64) -> Duration { const MAX_NANOS_F64: f64 = ((u64::MAX as u128 + 1) * (NANOS_PER_SEC as u128)) as f64; let nanos = secs * (NANOS_PER_SEC as f64); if !nanos.is_finite() { @@ -727,7 +728,8 @@ impl Duration { /// ``` #[stable(feature = "duration_float", since = "1.38.0")] #[inline] - pub fn from_secs_f32(secs: f32) -> Duration { + #[rustc_const_unstable(feature = "duration_consts_2", issue = "72440")] + pub const fn from_secs_f32(secs: f32) -> Duration { const MAX_NANOS_F32: f32 = ((u64::MAX as u128 + 1) * (NANOS_PER_SEC as u128)) as f32; let nanos = secs * (NANOS_PER_SEC as f32); if !nanos.is_finite() { @@ -761,7 +763,8 @@ impl Duration { /// ``` #[stable(feature = "duration_float", since = "1.38.0")] #[inline] - pub fn mul_f64(self, rhs: f64) -> Duration { + #[rustc_const_unstable(feature = "duration_consts_2", issue = "72440")] + pub const fn mul_f64(self, rhs: f64) -> Duration { Duration::from_secs_f64(rhs * self.as_secs_f64()) } @@ -782,7 +785,8 @@ impl Duration { /// ``` #[stable(feature = "duration_float", since = "1.38.0")] #[inline] - pub fn mul_f32(self, rhs: f32) -> Duration { + #[rustc_const_unstable(feature = "duration_consts_2", issue = "72440")] + pub const fn mul_f32(self, rhs: f32) -> Duration { Duration::from_secs_f32(rhs * self.as_secs_f32()) } @@ -802,7 +806,8 @@ impl Duration { /// ``` #[stable(feature = "duration_float", since = "1.38.0")] #[inline] - pub fn div_f64(self, rhs: f64) -> Duration { + #[rustc_const_unstable(feature = "duration_consts_2", issue = "72440")] + pub const fn div_f64(self, rhs: f64) -> Duration { Duration::from_secs_f64(self.as_secs_f64() / rhs) } @@ -824,7 +829,8 @@ impl Duration { /// ``` #[stable(feature = "duration_float", since = "1.38.0")] #[inline] - pub fn div_f32(self, rhs: f32) -> Duration { + #[rustc_const_unstable(feature = "duration_consts_2", issue = "72440")] + pub const fn div_f32(self, rhs: f32) -> Duration { Duration::from_secs_f32(self.as_secs_f32() / rhs) } diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs index a2e294ace1860..04402117f7da6 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs @@ -10,8 +10,11 @@ #![feature(core_private_diy_float)] #![feature(debug_non_exhaustive)] #![feature(dec2flt)] +#![feature(div_duration)] +#![feature(duration_consts_2)] #![feature(duration_constants)] #![feature(duration_saturating_ops)] +#![feature(duration_zero)] #![feature(exact_size_is_empty)] #![feature(fixed_size_array)] #![feature(flt2dec)] diff --git a/library/core/tests/time.rs b/library/core/tests/time.rs index 4f90eb63b0472..7c43885040b3e 100644 --- a/library/core/tests/time.rs +++ b/library/core/tests/time.rs @@ -321,3 +321,104 @@ fn debug_formatting_precision_high() { assert_eq!(format!("{:.10?}", Duration::new(4, 001_000_000)), "4.0010000000s"); assert_eq!(format!("{:.20?}", Duration::new(4, 001_000_000)), "4.00100000000000000000s"); } + +#[test] +fn duration_const() { + // test that the methods of `Duration` are usable in a const context + + const DURATION: Duration = Duration::new(0, 123_456_789); + + const SUB_SEC_MILLIS: u32 = DURATION.subsec_millis(); + assert_eq!(SUB_SEC_MILLIS, 123); + + const SUB_SEC_MICROS: u32 = DURATION.subsec_micros(); + assert_eq!(SUB_SEC_MICROS, 123_456); + + const SUB_SEC_NANOS: u32 = DURATION.subsec_nanos(); + assert_eq!(SUB_SEC_NANOS, 123_456_789); + + const ZERO: Duration = Duration::zero(); + assert_eq!(ZERO, Duration::new(0, 0)); + + const IS_ZERO: bool = ZERO.is_zero(); + assert!(IS_ZERO); + + const ONE: Duration = Duration::new(1, 0); + + const SECONDS: u64 = ONE.as_secs(); + assert_eq!(SECONDS, 1); + + const FROM_SECONDS: Duration = Duration::from_secs(1); + assert_eq!(FROM_SECONDS, ONE); + + const SECONDS_F32: f32 = ONE.as_secs_f32(); + assert_eq!(SECONDS_F32, 1.0); + + const FROM_SECONDS_F32: Duration = Duration::from_secs_f32(1.0); + assert_eq!(FROM_SECONDS_F32, ONE); + + const SECONDS_F64: f64 = ONE.as_secs_f64(); + assert_eq!(SECONDS_F64, 1.0); + + const FROM_SECONDS_F64: Duration = Duration::from_secs_f64(1.0); + assert_eq!(FROM_SECONDS_F64, ONE); + + const MILLIS: u128 = ONE.as_millis(); + assert_eq!(MILLIS, 1_000); + + const FROM_MILLIS: Duration = Duration::from_millis(1_000); + assert_eq!(FROM_MILLIS, ONE); + + const MICROS: u128 = ONE.as_micros(); + assert_eq!(MICROS, 1_000_000); + + const FROM_MICROS: Duration = Duration::from_micros(1_000_000); + assert_eq!(FROM_MICROS, ONE); + + const NANOS: u128 = ONE.as_nanos(); + assert_eq!(NANOS, 1_000_000_000); + + const FROM_NANOS: Duration = Duration::from_nanos(1_000_000_000); + assert_eq!(FROM_NANOS, ONE); + + const MAX: Duration = Duration::new(u64::MAX, 999_999_999); + + const CHECKED_ADD: Option = MAX.checked_add(ONE); + assert_eq!(CHECKED_ADD, None); + + const CHECKED_SUB: Option = ZERO.checked_sub(ONE); + assert_eq!(CHECKED_SUB, None); + + const CHECKED_MUL: Option = ONE.checked_mul(1); + assert_eq!(CHECKED_MUL, Some(ONE)); + + const MUL_F32: Duration = ONE.mul_f32(1.0); + assert_eq!(MUL_F32, ONE); + + const MUL_F64: Duration = ONE.mul_f64(1.0); + assert_eq!(MUL_F64, ONE); + + const CHECKED_DIV: Option = ONE.checked_div(1); + assert_eq!(CHECKED_DIV, Some(ONE)); + + const DIV_F32: Duration = ONE.div_f32(1.0); + assert_eq!(DIV_F32, ONE); + + const DIV_F64: Duration = ONE.div_f64(1.0); + assert_eq!(DIV_F64, ONE); + + const DIV_DURATION_F32: f32 = ONE.div_duration_f32(ONE); + assert_eq!(DIV_DURATION_F32, 1.0); + + const DIV_DURATION_F64: f64 = ONE.div_duration_f64(ONE); + assert_eq!(DIV_DURATION_F64, 1.0); + + const SATURATING_ADD: Duration = MAX.saturating_add(ONE); + assert_eq!(SATURATING_ADD, MAX); + + const SATURATING_SUB: Duration = ZERO.saturating_sub(ONE); + assert_eq!(SATURATING_SUB, ZERO); + + const SATURATING_MUL: Duration = MAX.saturating_mul(2); + assert_eq!(SATURATING_MUL, MAX); +} diff --git a/src/test/ui/consts/duration-consts-2.rs b/src/test/ui/consts/duration-consts-2.rs deleted file mode 100644 index bc0969e4f1fba..0000000000000 --- a/src/test/ui/consts/duration-consts-2.rs +++ /dev/null @@ -1,67 +0,0 @@ -// run-pass - -#![feature(const_panic)] -#![feature(duration_consts_2)] -#![feature(div_duration)] -#![feature(duration_saturating_ops)] - -use std::time::Duration; - -fn duration() { - const ZERO : Duration = Duration::new(0, 0); - assert_eq!(ZERO, Duration::from_secs(0)); - - const ONE : Duration = Duration::new(0, 1); - assert_eq!(ONE, Duration::from_nanos(1)); - - const MAX : Duration = Duration::new(u64::MAX, 1_000_000_000 - 1); - - const MAX_CHECKED_ADD_ZERO : Option = MAX.checked_add(ZERO); - assert_eq!(MAX_CHECKED_ADD_ZERO, Some(MAX)); - - const MAX_CHECKED_ADD_ONE : Option = MAX.checked_add(ONE); - assert_eq!(MAX_CHECKED_ADD_ONE, None); - - const ONE_CHECKED_SUB_ONE : Option = ONE.checked_sub(ONE); - assert_eq!(ONE_CHECKED_SUB_ONE, Some(ZERO)); - - const ZERO_CHECKED_SUB_ONE : Option = ZERO.checked_sub(ONE); - assert_eq!(ZERO_CHECKED_SUB_ONE, None); - - const ONE_CHECKED_MUL_ONE : Option = ONE.checked_mul(1); - assert_eq!(ONE_CHECKED_MUL_ONE, Some(ONE)); - - const MAX_CHECKED_MUL_TWO : Option = MAX.checked_mul(2); - assert_eq!(MAX_CHECKED_MUL_TWO, None); - - const ONE_CHECKED_DIV_ONE : Option = ONE.checked_div(1); - assert_eq!(ONE_CHECKED_DIV_ONE, Some(ONE)); - - const ONE_CHECKED_DIV_ZERO : Option = ONE.checked_div(0); - assert_eq!(ONE_CHECKED_DIV_ZERO, None); - - const MAX_AS_F32 : f32 = MAX.as_secs_f32(); - assert_eq!(MAX_AS_F32, 18446744000000000000.0_f32); - - const MAX_AS_F64 : f64 = MAX.as_secs_f64(); - assert_eq!(MAX_AS_F64, 18446744073709552000.0_f64); - - const ONE_AS_F32 : f32 = ONE.div_duration_f32(ONE); - assert_eq!(ONE_AS_F32, 1.0_f32); - - const ONE_AS_F64 : f64 = ONE.div_duration_f64(ONE); - assert_eq!(ONE_AS_F64, 1.0_f64); - - const MAX_SATURATING_ADD_ONE : Duration = MAX.saturating_add(ONE); - assert_eq!(MAX_SATURATING_ADD_ONE, MAX); - - const ZERO_SATURATING_SUB_ONE : Duration = ZERO.saturating_sub(ONE); - assert_eq!(ZERO_SATURATING_SUB_ONE, ZERO); - - const MAX_SATURATING_MUL_TWO : Duration = MAX.saturating_mul(2); - assert_eq!(MAX_SATURATING_MUL_TWO, MAX); -} - -fn main() { - duration(); -} From 869021e2606de502ccd8920412f1988da0e40952 Mon Sep 17 00:00:00 2001 From: Christiaan Dirkx Date: Sat, 12 Sep 2020 15:58:30 +0200 Subject: [PATCH 04/15] Add mailmap entry --- .mailmap | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.mailmap b/.mailmap index cc7b2a677baf6..fa0728bd79461 100644 --- a/.mailmap +++ b/.mailmap @@ -55,6 +55,9 @@ Chris C Cerami Chris C Cerami Chris Thorn Chris Thorn Chris Vittal Christopher Vittal +Christiaan Dirkx +Christiaan Dirkx CDirkx +Christiaan Dirkx CDirkx Christian Poveda Christian Poveda Christian Poveda From aa68aaa8e1b6c667987b71a83c332f1ce0988e54 Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Sat, 12 Sep 2020 17:11:47 +0200 Subject: [PATCH 05/15] Mark Once::new as #[inline]. Without this, it was not inlined in SyncOnceCell::into_inner(), causing unecessary checks and dead code. --- library/std/src/sync/once.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/library/std/src/sync/once.rs b/library/std/src/sync/once.rs index 8fed369bffc27..29ae338cb2ec7 100644 --- a/library/std/src/sync/once.rs +++ b/library/std/src/sync/once.rs @@ -191,6 +191,7 @@ struct WaiterQueue<'a> { impl Once { /// Creates a new `Once` value. + #[inline] #[stable(feature = "once_new", since = "1.2.0")] #[rustc_const_stable(feature = "const_once_new", since = "1.32.0")] pub const fn new() -> Once { From 4f0047ed108889ea97ad7656307a8a829dd56636 Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Sat, 12 Sep 2020 18:35:32 +0200 Subject: [PATCH 06/15] Add a comment on is_trivially_sized about obviously !Sized types --- compiler/rustc_middle/src/ty/sty.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 9f5fc5a2d3fbc..825221c22a8c1 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -2280,6 +2280,12 @@ impl<'tcx> TyS<'tcx> { /// /// Returning true means the type is known to be sized. Returning /// `false` means nothing -- could be sized, might not be. + /// + /// Note that we could never rely on the fact that a type such as `[_]` is + /// trivially `!Sized` because we could be in a type environment with a + /// bound such as `[_]: Copy`. A function with such a bound obviously never + /// can be called, but that doesn't mean it shouldn't typecheck. This is why + /// this method doesn't return `Option`. pub fn is_trivially_sized(&self, tcx: TyCtxt<'tcx>) -> bool { match self.kind() { ty::Infer(ty::IntVar(_) | ty::FloatVar(_)) From 75f0f7af3172cedaa01e9bf066c06017bfe9a426 Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Sat, 12 Sep 2020 13:27:57 +0200 Subject: [PATCH 07/15] Fix a typo --- src/librustdoc/clean/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 1bdbad4675556..00f27bb51ed21 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -839,7 +839,7 @@ impl<'a, 'tcx> Clean for (&'a ty::Generics, ty::GenericPredicates<'tcx let mut where_predicates = where_predicates.into_iter().flat_map(|p| p.clean(cx)).collect::>(); - // Type parameters and have a Sized bound by default unless removed with + // Type parameters have a Sized bound by default unless removed with // ?Sized. Scan through the predicates and mark any type parameter with // a Sized bound, removing the bounds as we find them. // From caf6c92d19216d75bf248643a11df77a598293e7 Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Sat, 12 Sep 2020 13:30:21 +0200 Subject: [PATCH 08/15] Clean up some language trait items comparisons --- .../src/traits/error_reporting/mod.rs | 7 +------ compiler/rustc_traits/src/chalk/db.rs | 20 +++++-------------- 2 files changed, 6 insertions(+), 21 deletions(-) diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index dcd8379803319..611280b413dd7 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -1507,12 +1507,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> { // avoid inundating the user with unnecessary errors, but we now // check upstream for type errors and don't add the obligations to // begin with in those cases. - if self - .tcx - .lang_items() - .sized_trait() - .map_or(false, |sized_id| sized_id == trait_ref.def_id()) - { + if self.tcx.lang_items().sized_trait() == Some(trait_ref.def_id()) { self.need_type_info_err(body_id, span, self_ty, ErrorCode::E0282).emit(); return; } diff --git a/compiler/rustc_traits/src/chalk/db.rs b/compiler/rustc_traits/src/chalk/db.rs index 7cc567dabb28f..2fad54013ad5b 100644 --- a/compiler/rustc_traits/src/chalk/db.rs +++ b/compiler/rustc_traits/src/chalk/db.rs @@ -110,25 +110,15 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t .map(|i| chalk_ir::AssocTypeId(i.def_id)) .collect(); - let well_known = if self - .interner - .tcx - .lang_items() - .sized_trait() - .map(|t| def_id == t) - .unwrap_or(false) - { + let well_known = if self.interner.tcx.lang_items().sized_trait() == Some(def_id) { Some(chalk_solve::rust_ir::WellKnownTrait::Sized) - } else if self.interner.tcx.lang_items().copy_trait().map(|t| def_id == t).unwrap_or(false) - { + } else if self.interner.tcx.lang_items().copy_trait() == Some(def_id) { Some(chalk_solve::rust_ir::WellKnownTrait::Copy) - } else if self.interner.tcx.lang_items().clone_trait().map(|t| def_id == t).unwrap_or(false) - { + } else if self.interner.tcx.lang_items().clone_trait() == Some(def_id) { Some(chalk_solve::rust_ir::WellKnownTrait::Clone) - } else if self.interner.tcx.lang_items().drop_trait().map(|t| def_id == t).unwrap_or(false) - { + } else if self.interner.tcx.lang_items().drop_trait() == Some(def_id) { Some(chalk_solve::rust_ir::WellKnownTrait::Drop) - } else if self.interner.tcx.lang_items().fn_trait().map(|t| def_id == t).unwrap_or(false) { + } else if self.interner.tcx.lang_items().fn_trait() == Some(def_id) { Some(chalk_solve::rust_ir::WellKnownTrait::Fn) } else if self .interner From 2eeb8f18eb493a8ec3b830aabb3e7f1723953bc0 Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Sat, 12 Sep 2020 15:47:52 -0400 Subject: [PATCH 09/15] Remove Windows details from Unix and VmWorks symlink() docstrings This note is not relevant to other operating systems. --- library/std/src/sys/unix/ext/fs.rs | 9 --------- library/std/src/sys/vxworks/ext/fs.rs | 9 --------- 2 files changed, 18 deletions(-) diff --git a/library/std/src/sys/unix/ext/fs.rs b/library/std/src/sys/unix/ext/fs.rs index 487ac266ee9cd..4b9f4ceb29c49 100644 --- a/library/std/src/sys/unix/ext/fs.rs +++ b/library/std/src/sys/unix/ext/fs.rs @@ -836,15 +836,6 @@ impl DirEntryExt for fs::DirEntry { /// /// The `dst` path will be a symbolic link pointing to the `src` path. /// -/// # Note -/// -/// On Windows, you must specify whether a symbolic link points to a file -/// or directory. Use `os::windows::fs::symlink_file` to create a -/// symbolic link to a file, or `os::windows::fs::symlink_dir` to create a -/// symbolic link to a directory. Additionally, the process must have -/// `SeCreateSymbolicLinkPrivilege` in order to be able to create a -/// symbolic link. -/// /// # Examples /// /// ```no_run diff --git a/library/std/src/sys/vxworks/ext/fs.rs b/library/std/src/sys/vxworks/ext/fs.rs index 9b4c64bdb6d84..68dc21b806c0f 100644 --- a/library/std/src/sys/vxworks/ext/fs.rs +++ b/library/std/src/sys/vxworks/ext/fs.rs @@ -774,15 +774,6 @@ impl DirEntryExt for fs::DirEntry { /// /// The `dst` path will be a symbolic link pointing to the `src` path. /// -/// # Note -/// -/// On Windows, you must specify whether a symbolic link points to a file -/// or directory. Use `os::windows::fs::symlink_file` to create a -/// symbolic link to a file, or `os::windows::fs::symlink_dir` to create a -/// symbolic link to a directory. Additionally, the process must have -/// `SeCreateSymbolicLinkPrivilege` in order to be able to create a -/// symbolic link. -/// /// # Examples /// /// ```no_run From f75d29f9cffdf001a22df0d71d338af69872ab4e Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 13 Sep 2020 11:27:21 +0200 Subject: [PATCH 10/15] reduce size of test_from_iter_specialization_with_iterator_adapters test in Miri --- library/alloc/tests/vec.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/alloc/tests/vec.rs b/library/alloc/tests/vec.rs index 53b0d0a271844..f3e6eb6292693 100644 --- a/library/alloc/tests/vec.rs +++ b/library/alloc/tests/vec.rs @@ -880,7 +880,7 @@ fn test_from_iter_partially_drained_in_place_specialization() { #[test] fn test_from_iter_specialization_with_iterator_adapters() { fn assert_in_place_trait(_: &T) {}; - let src: Vec = vec![0usize; 65535]; + let src: Vec = vec![0usize; if cfg!(miri) { 256 } else { 65535 }]; let srcptr = src.as_ptr(); let iter = src .into_iter() From bb417400e0cea1799053b1e3c94a579456245ba7 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 13 Sep 2020 12:14:59 +0200 Subject: [PATCH 11/15] fix slice::check_range aliasing problems --- library/alloc/src/collections/vec_deque.rs | 6 +- library/alloc/src/slice.rs | 2 + library/alloc/src/string.rs | 3 +- library/alloc/src/vec.rs | 2 +- library/alloc/tests/vec.rs | 2 +- library/core/src/slice/mod.rs | 148 ++++++++++----------- 6 files changed, 81 insertions(+), 82 deletions(-) diff --git a/library/alloc/src/collections/vec_deque.rs b/library/alloc/src/collections/vec_deque.rs index 253a3e9f2bea9..65cfe9a9b4996 100644 --- a/library/alloc/src/collections/vec_deque.rs +++ b/library/alloc/src/collections/vec_deque.rs @@ -1089,11 +1089,7 @@ impl VecDeque { where R: RangeBounds, { - // SAFETY: This buffer is only used to check the range. It might be partially - // uninitialized, but `check_range` needs a contiguous slice. - // https://github.com/rust-lang/rust/pull/75207#discussion_r471193682 - let buffer = unsafe { slice::from_raw_parts(self.ptr(), self.len()) }; - let Range { start, end } = buffer.check_range(range); + let Range { start, end } = slice::check_range(self.len(), range); let tail = self.wrap_add(self.tail, start); let head = self.wrap_add(self.tail, end); (tail, head) diff --git a/library/alloc/src/slice.rs b/library/alloc/src/slice.rs index 677bfdd2349ec..55afdd94f4468 100644 --- a/library/alloc/src/slice.rs +++ b/library/alloc/src/slice.rs @@ -91,6 +91,8 @@ use crate::borrow::ToOwned; use crate::boxed::Box; use crate::vec::Vec; +#[unstable(feature = "slice_check_range", issue = "76393")] +pub use core::slice::check_range; #[unstable(feature = "array_chunks", issue = "74985")] pub use core::slice::ArrayChunks; #[unstable(feature = "array_chunks", issue = "74985")] diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs index e1724bf3c9a90..2b0ce5ede5630 100644 --- a/library/alloc/src/string.rs +++ b/library/alloc/src/string.rs @@ -49,6 +49,7 @@ use core::iter::{FromIterator, FusedIterator}; use core::ops::Bound::{Excluded, Included, Unbounded}; use core::ops::{self, Add, AddAssign, Index, IndexMut, Range, RangeBounds}; use core::ptr; +use core::slice; use core::str::{lossy, pattern::Pattern}; use crate::borrow::{Cow, ToOwned}; @@ -1506,7 +1507,7 @@ impl String { // of the vector version. The data is just plain bytes. // Because the range removal happens in Drop, if the Drain iterator is leaked, // the removal will not happen. - let Range { start, end } = self.as_bytes().check_range(range); + let Range { start, end } = slice::check_range(self.len(), range); assert!(self.is_char_boundary(start)); assert!(self.is_char_boundary(end)); diff --git a/library/alloc/src/vec.rs b/library/alloc/src/vec.rs index baa6c0919defe..3d48a06fd241a 100644 --- a/library/alloc/src/vec.rs +++ b/library/alloc/src/vec.rs @@ -1310,7 +1310,7 @@ impl Vec { // the hole, and the vector length is restored to the new length. // let len = self.len(); - let Range { start, end } = self.check_range(range); + let Range { start, end } = slice::check_range(len, range); unsafe { // set self.vec length's to start, to be safe in case Drain is leaked diff --git a/library/alloc/tests/vec.rs b/library/alloc/tests/vec.rs index f3e6eb6292693..e65bbb9b4dce8 100644 --- a/library/alloc/tests/vec.rs +++ b/library/alloc/tests/vec.rs @@ -880,7 +880,7 @@ fn test_from_iter_partially_drained_in_place_specialization() { #[test] fn test_from_iter_specialization_with_iterator_adapters() { fn assert_in_place_trait(_: &T) {}; - let src: Vec = vec![0usize; if cfg!(miri) { 256 } else { 65535 }]; + let src: Vec = vec![0usize; 256]; let srcptr = src.as_ptr(); let iter = src .into_iter() diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index 4c027b23584bf..5e4537e5dc8fe 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -354,79 +354,6 @@ impl [T] { unsafe { &mut *index.get_unchecked_mut(self) } } - /// Converts a range over this slice to [`Range`]. - /// - /// The returned range is safe to pass to [`get_unchecked`] and [`get_unchecked_mut`]. - /// - /// [`get_unchecked`]: #method.get_unchecked - /// [`get_unchecked_mut`]: #method.get_unchecked_mut - /// - /// # Panics - /// - /// Panics if the range is out of bounds. - /// - /// # Examples - /// - /// ``` - /// #![feature(slice_check_range)] - /// - /// let v = [10, 40, 30]; - /// assert_eq!(1..2, v.check_range(1..2)); - /// assert_eq!(0..2, v.check_range(..2)); - /// assert_eq!(1..3, v.check_range(1..)); - /// ``` - /// - /// Panics when [`Index::index`] would panic: - /// - /// ```should_panic - /// #![feature(slice_check_range)] - /// - /// [10, 40, 30].check_range(2..1); - /// ``` - /// - /// ```should_panic - /// #![feature(slice_check_range)] - /// - /// [10, 40, 30].check_range(1..4); - /// ``` - /// - /// ```should_panic - /// #![feature(slice_check_range)] - /// - /// [10, 40, 30].check_range(1..=usize::MAX); - /// ``` - /// - /// [`Index::index`]: ops::Index::index - #[track_caller] - #[unstable(feature = "slice_check_range", issue = "76393")] - pub fn check_range>(&self, range: R) -> Range { - let start = match range.start_bound() { - Bound::Included(&start) => start, - Bound::Excluded(start) => { - start.checked_add(1).unwrap_or_else(|| slice_start_index_overflow_fail()) - } - Bound::Unbounded => 0, - }; - - let len = self.len(); - let end = match range.end_bound() { - Bound::Included(end) => { - end.checked_add(1).unwrap_or_else(|| slice_end_index_overflow_fail()) - } - Bound::Excluded(&end) => end, - Bound::Unbounded => len, - }; - - if start > end { - slice_index_order_fail(start, end); - } - if end > len { - slice_end_index_len_fail(end, len); - } - - Range { start, end } - } - /// Returns a raw pointer to the slice's buffer. /// /// The caller must ensure that the slice outlives the pointer this @@ -2770,7 +2697,7 @@ impl [T] { where T: Copy, { - let Range { start: src_start, end: src_end } = self.check_range(src); + let Range { start: src_start, end: src_end } = check_range(self.len(), src); let count = src_end - src_start; assert!(dest <= self.len() - count, "dest is out of bounds"); // SAFETY: the conditions for `ptr::copy` have all been checked above, @@ -6660,6 +6587,79 @@ unsafe impl<'a, T> TrustedRandomAccess for RChunksExactMut<'a, T> { // Free functions // +/// Performs bounds-checking of the given range. +/// The returned [`Range`] is safe to pass to [`get_unchecked`] and [`get_unchecked_mut`] +/// for slices of the given length. +/// +/// [`get_unchecked`]: ../../std/primitive.slice.html#method.get_unchecked +/// [`get_unchecked_mut`]: ../../std/primitive.slice.html#method.get_unchecked_mut +/// +/// # Panics +/// +/// Panics if the range is out of bounds. +/// +/// # Examples +/// +/// ``` +/// #![feature(slice_check_range)] +/// use std::slice; +/// +/// let v = [10, 40, 30]; +/// assert_eq!(1..2, slice::check_range(v.len(), 1..2)); +/// assert_eq!(0..2, slice::check_range(v.len(), ..2)); +/// assert_eq!(1..3, slice::check_range(v.len(), 1..)); +/// ``` +/// +/// Panics when [`Index::index`] would panic: +/// +/// ```should_panic +/// #![feature(slice_check_range)] +/// +/// std::slice::check_range(3, 2..1); +/// ``` +/// +/// ```should_panic +/// #![feature(slice_check_range)] +/// +/// std::slice::check_range(3, 1..4); +/// ``` +/// +/// ```should_panic +/// #![feature(slice_check_range)] +/// +/// std::slice::check_range(3, 1..=usize::MAX); +/// ``` +/// +/// [`Index::index`]: ops::Index::index +#[track_caller] +#[unstable(feature = "slice_check_range", issue = "76393")] +pub fn check_range>(len: usize, range: R) -> Range { + let start = match range.start_bound() { + Bound::Included(&start) => start, + Bound::Excluded(start) => { + start.checked_add(1).unwrap_or_else(|| slice_start_index_overflow_fail()) + } + Bound::Unbounded => 0, + }; + + let end = match range.end_bound() { + Bound::Included(end) => { + end.checked_add(1).unwrap_or_else(|| slice_end_index_overflow_fail()) + } + Bound::Excluded(&end) => end, + Bound::Unbounded => len, + }; + + if start > end { + slice_index_order_fail(start, end); + } + if end > len { + slice_end_index_len_fail(end, len); + } + + Range { start, end } +} + /// Forms a slice from a pointer and a length. /// /// The `len` argument is the number of **elements**, not the number of bytes. From 20a2e095eca14319d233a70b87c1b4415737f94d Mon Sep 17 00:00:00 2001 From: Ivan Tham Date: Sun, 13 Sep 2020 19:20:57 +0800 Subject: [PATCH 12/15] Simplify iter chain struct doc --- library/core/src/iter/adapters/chain.rs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/library/core/src/iter/adapters/chain.rs b/library/core/src/iter/adapters/chain.rs index 6700ef017bde4..13c6a75d58b5c 100644 --- a/library/core/src/iter/adapters/chain.rs +++ b/library/core/src/iter/adapters/chain.rs @@ -4,11 +4,8 @@ use crate::usize; /// An iterator that links two iterators together, in a chain. /// -/// This `struct` is created by the [`chain`] method on [`Iterator`]. See its -/// documentation for more. -/// -/// [`chain`]: trait.Iterator.html#method.chain -/// [`Iterator`]: trait.Iterator.html +/// This `struct` is created by [`Iterator::chain`]. See its documentation +/// for more. #[derive(Clone, Debug)] #[must_use = "iterators are lazy and do nothing unless consumed"] #[stable(feature = "rust1", since = "1.0.0")] From 458aaba08467dc6b8d04b79f955a46be779d94f1 Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Sun, 19 Jul 2020 20:57:04 +0200 Subject: [PATCH 13/15] Add Atomic*::from_mut. The atomic equivalent of Cell::from_mut. --- library/core/src/sync/atomic.rs | 98 ++++++++++++++++++++++++++++++++- 1 file changed, 97 insertions(+), 1 deletion(-) diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs index 38eabaaa396e0..cdd9b3ae90bbd 100644 --- a/library/core/src/sync/atomic.rs +++ b/library/core/src/sync/atomic.rs @@ -110,6 +110,7 @@ use self::Ordering::*; use crate::cell::UnsafeCell; use crate::fmt; use crate::intrinsics; +use crate::mem::align_of; use crate::hint::spin_loop; @@ -327,6 +328,27 @@ impl AtomicBool { unsafe { &mut *(self.v.get() as *mut bool) } } + /// Get atomic access to a `&mut bool`. + /// + /// # Examples + /// + /// ``` + /// #![feature(atomic_from_mut)] + /// use std::sync::atomic::{AtomicBool, Ordering}; + /// + /// let mut some_bool = true; + /// let a = AtomicBool::from_mut(&mut some_bool); + /// a.store(false, Ordering::Relaxed); + /// assert_eq!(some_bool, false); + /// ``` + #[inline] + #[unstable(feature = "atomic_from_mut", issue = "76314")] + pub fn from_mut(v: &mut bool) -> &Self { + // SAFETY: the mutable reference guarantees unique ownership, and + // alignment of both `bool` and `Self` is 1. + unsafe { &*(v as *mut bool as *mut Self) } + } + /// Consumes the atomic and returns the contained value. /// /// This is safe because passing `self` by value guarantees that no other threads are @@ -820,6 +842,30 @@ impl AtomicPtr { unsafe { &mut *self.p.get() } } + /// Get atomic access to a pointer. + /// + /// # Examples + /// + /// ``` + /// #![feature(atomic_from_mut)] + /// use std::sync::atomic::{AtomicPtr, Ordering}; + /// + /// let mut some_ptr = &mut 123 as *mut i32; + /// let a = AtomicPtr::from_mut(&mut some_ptr); + /// a.store(&mut 456, Ordering::Relaxed); + /// assert_eq!(unsafe { *some_ptr }, 456); + /// ``` + #[inline] + #[unstable(feature = "atomic_from_mut", issue = "76314")] + pub fn from_mut(v: &mut *mut T) -> &Self { + let [] = [(); align_of::() - align_of::<*mut T>()]; + // SAFETY: + // - the mutable reference guarantees unique ownership. + // - the alignment of `*mut T` and `Self` is the same on all platforms + // supported by rust, as verified above. + unsafe { &*(v as *mut *mut T as *mut Self) } + } + /// Consumes the atomic and returns the contained value. /// /// This is safe because passing `self` by value guarantees that no other threads are @@ -1104,6 +1150,12 @@ impl From<*mut T> for AtomicPtr { } } +macro_rules! if_not_8_bit { + (u8, $($tt:tt)*) => { "" }; + (i8, $($tt:tt)*) => { "" }; + ($_:ident, $($tt:tt)*) => { $($tt)* }; +} + #[cfg(target_has_atomic_load_store = "8")] macro_rules! atomic_int { ($cfg_cas:meta, @@ -1115,7 +1167,8 @@ macro_rules! atomic_int { $stable_nand:meta, $const_stable:meta, $stable_init_const:meta, - $s_int_type:expr, $int_ref:expr, + $(from_mut: cfg($from_mut_cfg:meta),)? + $s_int_type:literal, $int_ref:expr, $extra_feature:expr, $min_fn:ident, $max_fn:ident, $align:expr, @@ -1226,6 +1279,45 @@ assert_eq!(some_var.load(Ordering::SeqCst), 5); } } + doc_comment! { + concat!("Get atomic access to a `&mut ", stringify!($int_type), "`. + +", +if_not_8_bit! { + $int_type, + concat!( + "**Note:** This function is only available on targets where `", + stringify!($int_type), "` has an alignment of ", $align, " bytes." + ) +}, +" + +# Examples + +``` +#![feature(atomic_from_mut)] +", $extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering}; + +let mut some_int = 123; +let a = ", stringify!($atomic_type), "::from_mut(&mut some_int); +a.store(100, Ordering::Relaxed); +assert_eq!(some_int, 100); +``` + "), + #[inline] + $(#[cfg($from_mut_cfg)])? + #[unstable(feature = "atomic_from_mut", issue = "76314")] + pub fn from_mut(v: &mut $int_type) -> &Self { + let [] = [(); align_of::() - align_of::<$int_type>()]; + // SAFETY: + // - the mutable reference guarantees unique ownership. + // - the alignment of `$int_type` and `Self` is the + // same on all platforms enabled by `$from_mut_cfg` + // as verified above. + unsafe { &*(v as *mut $int_type as *mut Self) } + } + } + doc_comment! { concat!("Consumes the atomic and returns the contained value. @@ -1984,6 +2076,7 @@ atomic_int! { stable(feature = "integer_atomics_stable", since = "1.34.0"), rustc_const_stable(feature = "const_integer_atomics", since = "1.34.0"), unstable(feature = "integer_atomics", issue = "32976"), + from_mut: cfg(not(target_arch = "x86")), "i64", "../../../std/primitive.i64.html", "", atomic_min, atomic_max, @@ -2002,6 +2095,7 @@ atomic_int! { stable(feature = "integer_atomics_stable", since = "1.34.0"), rustc_const_stable(feature = "const_integer_atomics", since = "1.34.0"), unstable(feature = "integer_atomics", issue = "32976"), + from_mut: cfg(not(target_arch = "x86")), "u64", "../../../std/primitive.u64.html", "", atomic_umin, atomic_umax, @@ -2020,6 +2114,7 @@ atomic_int! { unstable(feature = "integer_atomics", issue = "32976"), rustc_const_stable(feature = "const_integer_atomics", since = "1.34.0"), unstable(feature = "integer_atomics", issue = "32976"), + from_mut: cfg(not(target_arch = "x86_64")), "i128", "../../../std/primitive.i128.html", "#![feature(integer_atomics)]\n\n", atomic_min, atomic_max, @@ -2038,6 +2133,7 @@ atomic_int! { unstable(feature = "integer_atomics", issue = "32976"), rustc_const_stable(feature = "const_integer_atomics", since = "1.34.0"), unstable(feature = "integer_atomics", issue = "32976"), + from_mut: cfg(not(target_arch = "x86_64")), "u128", "../../../std/primitive.u128.html", "#![feature(integer_atomics)]\n\n", atomic_umin, atomic_umax, From 3be40b22c83491e4a4d34e2ad06aa81b804b9fad Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Sat, 12 Sep 2020 21:20:17 +0200 Subject: [PATCH 14/15] Fix AtomicPtr::from_mut align check: Avoid generic arg in const expr. See #76200. --- library/core/src/sync/atomic.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs index cdd9b3ae90bbd..920a82f5af481 100644 --- a/library/core/src/sync/atomic.rs +++ b/library/core/src/sync/atomic.rs @@ -858,7 +858,7 @@ impl AtomicPtr { #[inline] #[unstable(feature = "atomic_from_mut", issue = "76314")] pub fn from_mut(v: &mut *mut T) -> &Self { - let [] = [(); align_of::() - align_of::<*mut T>()]; + let [] = [(); align_of::>() - align_of::<*mut ()>()]; // SAFETY: // - the mutable reference guarantees unique ownership. // - the alignment of `*mut T` and `Self` is the same on all platforms From cf0720146e89a9af8759951aaf774ef19f33f556 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sun, 13 Sep 2020 14:37:35 +0200 Subject: [PATCH 15/15] Fix CI LLVM to work on NixOS out of the box --- src/bootstrap/bootstrap.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index 44a17f75451a9..5f78031e1c7cb 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -429,6 +429,8 @@ def download_stage0(self): llvm_assertions = self.get_toml('assertions', 'llvm') == 'true' if self.program_out_of_date(self.llvm_stamp(), llvm_sha + str(llvm_assertions)): self._download_ci_llvm(llvm_sha, llvm_assertions) + for binary in ["llvm-config", "FileCheck"]: + self.fix_bin_or_dylib("{}/bin/{}".format(self.llvm_root(), binary)) with output(self.llvm_stamp()) as llvm_stamp: llvm_stamp.write(self.date + llvm_sha + str(llvm_assertions))