From 81e85ce76d6630a8f87f81df2470e76fbe73de7d Mon Sep 17 00:00:00 2001 From: Alexis Bourget Date: Sun, 30 Aug 2020 21:59:43 +0200 Subject: [PATCH 01/14] Move to Arc::clone(&x) over x.clone() in library/std --- library/std/src/collections/hash/map.rs | 4 ++-- library/std/src/sync/barrier.rs | 4 ++-- library/std/src/sync/condvar.rs | 18 +++++++++--------- library/std/src/sync/mutex.rs | 8 ++++---- library/std/src/sync/rwlock.rs | 4 ++-- library/std/src/sys_common/poison.rs | 4 ++-- 6 files changed, 21 insertions(+), 21 deletions(-) diff --git a/library/std/src/collections/hash/map.rs b/library/std/src/collections/hash/map.rs index 70f7214e2f1d7..56f63002b7f11 100644 --- a/library/std/src/collections/hash/map.rs +++ b/library/std/src/collections/hash/map.rs @@ -2381,7 +2381,7 @@ impl<'a, K, V> OccupiedEntry<'a, K, V> { /// use std::rc::Rc; /// /// let mut map: HashMap, u32> = HashMap::new(); - /// let mut known_strings: Vec> = Vec::new(); + /// let known_strings: Vec> = Vec::new(); /// /// // Initialise known strings, run program, etc. /// @@ -2389,7 +2389,7 @@ impl<'a, K, V> OccupiedEntry<'a, K, V> { /// /// fn reclaim_memory(map: &mut HashMap, u32>, known_strings: &[Rc] ) { /// for s in known_strings { - /// if let Entry::Occupied(entry) = map.entry(s.clone()) { + /// if let Entry::Occupied(entry) = map.entry(Rc::clone(s)) { /// // Replaces the entry's key with our version of it in `known_strings`. /// entry.replace_key(); /// } diff --git a/library/std/src/sync/barrier.rs b/library/std/src/sync/barrier.rs index 23c989fd2fdfb..61f097ccf250c 100644 --- a/library/std/src/sync/barrier.rs +++ b/library/std/src/sync/barrier.rs @@ -13,7 +13,7 @@ use crate::sync::{Condvar, Mutex}; /// let mut handles = Vec::with_capacity(10); /// let barrier = Arc::new(Barrier::new(10)); /// for _ in 0..10 { -/// let c = barrier.clone(); +/// let c = Arc::clone(&barrier); /// // The same messages will be printed together. /// // You will NOT see any interleaving. /// handles.push(thread::spawn(move|| { @@ -110,7 +110,7 @@ impl Barrier { /// let mut handles = Vec::with_capacity(10); /// let barrier = Arc::new(Barrier::new(10)); /// for _ in 0..10 { - /// let c = barrier.clone(); + /// let c = Arc::clone(&barrier); /// // The same messages will be printed together. /// // You will NOT see any interleaving. /// handles.push(thread::spawn(move|| { diff --git a/library/std/src/sync/condvar.rs b/library/std/src/sync/condvar.rs index 4efd86aa3ede8..1fbcb0ac08e0f 100644 --- a/library/std/src/sync/condvar.rs +++ b/library/std/src/sync/condvar.rs @@ -33,7 +33,7 @@ impl WaitTimeoutResult { /// use std::time::Duration; /// /// let pair = Arc::new((Mutex::new(false), Condvar::new())); - /// let pair2 = pair.clone(); + /// let pair2 = Arc::clone(&pair); /// /// thread::spawn(move || { /// let (lock, cvar) = &*pair2; @@ -90,7 +90,7 @@ impl WaitTimeoutResult { /// use std::thread; /// /// let pair = Arc::new((Mutex::new(false), Condvar::new())); -/// let pair2 = pair.clone(); +/// let pair2 = Arc::clone(&pair); /// /// // Inside of our lock, spawn a new thread, and then wait for it to start. /// thread::spawn(move|| { @@ -173,7 +173,7 @@ impl Condvar { /// use std::thread; /// /// let pair = Arc::new((Mutex::new(false), Condvar::new())); - /// let pair2 = pair.clone(); + /// let pair2 = Arc::clone(&pair); /// /// thread::spawn(move|| { /// let (lock, cvar) = &*pair2; @@ -229,7 +229,7 @@ impl Condvar { /// use std::thread; /// /// let pair = Arc::new((Mutex::new(true), Condvar::new())); - /// let pair2 = pair.clone(); + /// let pair2 = Arc::clone(&pair); /// /// thread::spawn(move|| { /// let (lock, cvar) = &*pair2; @@ -288,7 +288,7 @@ impl Condvar { /// use std::thread; /// /// let pair = Arc::new((Mutex::new(false), Condvar::new())); - /// let pair2 = pair.clone(); + /// let pair2 = Arc::clone(&pair); /// /// thread::spawn(move|| { /// let (lock, cvar) = &*pair2; @@ -360,7 +360,7 @@ impl Condvar { /// use std::time::Duration; /// /// let pair = Arc::new((Mutex::new(false), Condvar::new())); - /// let pair2 = pair.clone(); + /// let pair2 = Arc::clone(&pair); /// /// thread::spawn(move|| { /// let (lock, cvar) = &*pair2; @@ -429,7 +429,7 @@ impl Condvar { /// use std::time::Duration; /// /// let pair = Arc::new((Mutex::new(true), Condvar::new())); - /// let pair2 = pair.clone(); + /// let pair2 = Arc::clone(&pair); /// /// thread::spawn(move|| { /// let (lock, cvar) = &*pair2; @@ -493,7 +493,7 @@ impl Condvar { /// use std::thread; /// /// let pair = Arc::new((Mutex::new(false), Condvar::new())); - /// let pair2 = pair.clone(); + /// let pair2 = Arc::clone(&pair); /// /// thread::spawn(move|| { /// let (lock, cvar) = &*pair2; @@ -533,7 +533,7 @@ impl Condvar { /// use std::thread; /// /// let pair = Arc::new((Mutex::new(false), Condvar::new())); - /// let pair2 = pair.clone(); + /// let pair2 = Arc::clone(&pair); /// /// thread::spawn(move|| { /// let (lock, cvar) = &*pair2; diff --git a/library/std/src/sync/mutex.rs b/library/std/src/sync/mutex.rs index d7a4f00305c71..39a5a455fe4d5 100644 --- a/library/std/src/sync/mutex.rs +++ b/library/std/src/sync/mutex.rs @@ -85,7 +85,7 @@ use crate::sys_common::poison::{self, LockResult, TryLockError, TryLockResult}; /// use std::thread; /// /// let lock = Arc::new(Mutex::new(0_u32)); -/// let lock2 = lock.clone(); +/// let lock2 = Arc::clone(&lock); /// /// let _ = thread::spawn(move || -> () { /// // This thread will acquire the mutex first, unwrapping the result of @@ -256,7 +256,7 @@ impl Mutex { /// use std::thread; /// /// let mutex = Arc::new(Mutex::new(0)); - /// let c_mutex = mutex.clone(); + /// let c_mutex = Arc::clone(&mutex); /// /// thread::spawn(move || { /// *c_mutex.lock().unwrap() = 10; @@ -292,7 +292,7 @@ impl Mutex { /// use std::thread; /// /// let mutex = Arc::new(Mutex::new(0)); - /// let c_mutex = mutex.clone(); + /// let c_mutex = Arc::clone(&mutex); /// /// thread::spawn(move || { /// let mut lock = c_mutex.try_lock(); @@ -328,7 +328,7 @@ impl Mutex { /// use std::thread; /// /// let mutex = Arc::new(Mutex::new(0)); - /// let c_mutex = mutex.clone(); + /// let c_mutex = Arc::clone(&mutex); /// /// let _ = thread::spawn(move || { /// let _lock = c_mutex.lock().unwrap(); diff --git a/library/std/src/sync/rwlock.rs b/library/std/src/sync/rwlock.rs index 586093c916dea..b7f135f5c8af4 100644 --- a/library/std/src/sync/rwlock.rs +++ b/library/std/src/sync/rwlock.rs @@ -162,7 +162,7 @@ impl RwLock { /// use std::thread; /// /// let lock = Arc::new(RwLock::new(1)); - /// let c_lock = lock.clone(); + /// let c_lock = Arc::clone(&lock); /// /// let n = lock.read().unwrap(); /// assert_eq!(*n, 1); @@ -318,7 +318,7 @@ impl RwLock { /// use std::thread; /// /// let lock = Arc::new(RwLock::new(0)); - /// let c_lock = lock.clone(); + /// let c_lock = Arc::clone(&lock); /// /// let _ = thread::spawn(move || { /// let _lock = c_lock.write().unwrap(); diff --git a/library/std/src/sys_common/poison.rs b/library/std/src/sys_common/poison.rs index 3f079da9098c7..2ab2c700a1bf1 100644 --- a/library/std/src/sys_common/poison.rs +++ b/library/std/src/sys_common/poison.rs @@ -65,7 +65,7 @@ pub struct Guard { /// let mutex = Arc::new(Mutex::new(1)); /// /// // poison the mutex -/// let c_mutex = mutex.clone(); +/// let c_mutex = Arc::clone(&mutex); /// let _ = thread::spawn(move || { /// let mut data = c_mutex.lock().unwrap(); /// *data = 2; @@ -168,7 +168,7 @@ impl PoisonError { /// let mutex = Arc::new(Mutex::new(HashSet::new())); /// /// // poison the mutex - /// let c_mutex = mutex.clone(); + /// let c_mutex = Arc::clone(&mutex); /// let _ = thread::spawn(move || { /// let mut data = c_mutex.lock().unwrap(); /// data.insert(10); From 6b75e3d11b89671df0a3f284252584414bfe17d9 Mon Sep 17 00:00:00 2001 From: Alexis Bourget Date: Sun, 30 Aug 2020 22:14:17 +0200 Subject: [PATCH 02/14] Move to Arc::clone(&x) over x.clone() in library/core --- library/core/src/pin.rs | 2 +- library/core/src/sync/atomic.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/library/core/src/pin.rs b/library/core/src/pin.rs index 8f60c4787d459..fc17f64879a50 100644 --- a/library/core/src/pin.rs +++ b/library/core/src/pin.rs @@ -541,7 +541,7 @@ impl Pin

{ /// use std::pin::Pin; /// /// fn move_pinned_rc(mut x: Rc) { - /// let pinned = unsafe { Pin::new_unchecked(x.clone()) }; + /// let pinned = unsafe { Pin::new_unchecked(Rc::clone(&x)) }; /// { /// let p: Pin<&T> = pinned.as_ref(); /// // This should mean the pointee can never move again. diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs index 1aec7e1b5f871..38eabaaa396e0 100644 --- a/library/core/src/sync/atomic.rs +++ b/library/core/src/sync/atomic.rs @@ -76,7 +76,7 @@ //! fn main() { //! let spinlock = Arc::new(AtomicUsize::new(1)); //! -//! let spinlock_clone = spinlock.clone(); +//! let spinlock_clone = Arc::clone(&spinlock); //! let thread = thread::spawn(move|| { //! spinlock_clone.store(0, Ordering::SeqCst); //! }); From 8783c62f0c8641ef56094fae13e2fed193b60d1f Mon Sep 17 00:00:00 2001 From: Camelid <37223377+camelid@users.noreply.github.com> Date: Tue, 1 Sep 2020 17:48:15 -0700 Subject: [PATCH 03/14] Add missing link in README --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index a7e23d8ac2caa..6cf9577d3330e 100644 --- a/README.md +++ b/README.md @@ -243,6 +243,8 @@ The Rust community congregates in a few places: If you are interested in contributing to the Rust project, please take a look at the [Getting Started][gettingstarted] guide in the [rustc-dev-guide]. +[rustc-dev-guide]: https://rustc-dev-guide.rust-lang.org + ## License Rust is primarily distributed under the terms of both the MIT license From 3e29fdb0fb3be5a35d3e2d55d902be8b4ecbe7bb Mon Sep 17 00:00:00 2001 From: Rune Tynan Date: Thu, 3 Sep 2020 01:37:40 -0400 Subject: [PATCH 04/14] Remove a number of vec UI tests, make them unit tests in the alloc library --- library/alloc/tests/vec.rs | 53 +++++++++++++++++++++++ src/test/ui/array-slice-vec/vec-concat.rs | 14 ------ src/test/ui/array-slice-vec/vec-growth.rs | 16 ------- src/test/ui/array-slice-vec/vec-push.rs | 3 -- src/test/ui/array-slice-vec/vec-slice.rs | 9 ---- src/test/ui/array-slice-vec/vec-to_str.rs | 5 --- src/test/ui/array-slice-vec/vec.rs | 15 ------- 7 files changed, 53 insertions(+), 62 deletions(-) delete mode 100644 src/test/ui/array-slice-vec/vec-concat.rs delete mode 100644 src/test/ui/array-slice-vec/vec-growth.rs delete mode 100644 src/test/ui/array-slice-vec/vec-push.rs delete mode 100644 src/test/ui/array-slice-vec/vec-slice.rs delete mode 100644 src/test/ui/array-slice-vec/vec.rs diff --git a/library/alloc/tests/vec.rs b/library/alloc/tests/vec.rs index ffff543b07fe5..b422960c19982 100644 --- a/library/alloc/tests/vec.rs +++ b/library/alloc/tests/vec.rs @@ -72,6 +72,39 @@ fn test_zst_capacity() { assert_eq!(Vec::<()>::new().capacity(), usize::MAX); } +#[test] +fn test_indexing() { + let v: Vec = vec![10, 20]; + assert_eq!(v[0], 10); + assert_eq!(v[1], 20); + let mut x: usize = 0; + assert_eq!(v[x], 10); + assert_eq!(v[x + 1], 20); + x = x + 1; + assert_eq!(v[x], 20); + assert_eq!(v[x - 1], 10); +} + +#[test] +fn test_debug_fmt() { + let vec1: Vec = vec![]; + assert_eq!("[]", format!("{:?}", vec1)); + + let vec2 = vec![0, 1]; + assert_eq!("[0, 1]", format!("{:?}", vec2)); +} + +#[test] +fn test_push() { + let mut v = vec![]; + v.push(1); + assert_eq!(v, [1]); + v.push(2); + assert_eq!(v, [1, 2]); + v.push(3); + assert_eq!(v, [1, 2, 3]); +} + #[test] fn test_extend() { let mut v = Vec::new(); @@ -117,6 +150,18 @@ fn test_extend() { assert_eq!(count_x, 1); } +#[test] +fn test_extend_from_slice() { + let a: Vec = vec![1, 2, 3, 4, 5]; + let b: Vec = vec![6, 7, 8, 9, 0]; + + let mut v: Vec = a; + + v.extend_from_slice(&b); + + assert_eq!(v, [1, 2, 3, 4, 5, 6, 7, 8, 9, 0]); +} + #[test] fn test_extend_ref() { let mut v = vec![1, 2]; @@ -132,6 +177,14 @@ fn test_extend_ref() { assert_eq!(v, [1, 2, 3, 4, 5, 6, 7]); } +#[test] +fn test_slice_from_ref() { + let values = vec![1, 2, 3, 4, 5]; + let slice = &values[1..3]; + + assert_eq!(slice, [2, 3]); +} + #[test] fn test_slice_from_mut() { let mut values = vec![1, 2, 3, 4, 5]; diff --git a/src/test/ui/array-slice-vec/vec-concat.rs b/src/test/ui/array-slice-vec/vec-concat.rs deleted file mode 100644 index 1f493679b7947..0000000000000 --- a/src/test/ui/array-slice-vec/vec-concat.rs +++ /dev/null @@ -1,14 +0,0 @@ -// run-pass - -use std::vec; - -pub fn main() { - let a: Vec = vec![1, 2, 3, 4, 5]; - let b: Vec = vec![6, 7, 8, 9, 0]; - let mut v: Vec = a; - v.extend_from_slice(&b); - println!("{}", v[9]); - assert_eq!(v[0], 1); - assert_eq!(v[7], 8); - assert_eq!(v[9], 0); -} diff --git a/src/test/ui/array-slice-vec/vec-growth.rs b/src/test/ui/array-slice-vec/vec-growth.rs deleted file mode 100644 index b09f08bb85a82..0000000000000 --- a/src/test/ui/array-slice-vec/vec-growth.rs +++ /dev/null @@ -1,16 +0,0 @@ -// run-pass - - - -pub fn main() { - let mut v = vec![1]; - v.push(2); - v.push(3); - v.push(4); - v.push(5); - assert_eq!(v[0], 1); - assert_eq!(v[1], 2); - assert_eq!(v[2], 3); - assert_eq!(v[3], 4); - assert_eq!(v[4], 5); -} diff --git a/src/test/ui/array-slice-vec/vec-push.rs b/src/test/ui/array-slice-vec/vec-push.rs deleted file mode 100644 index 466ab3fab1cab..0000000000000 --- a/src/test/ui/array-slice-vec/vec-push.rs +++ /dev/null @@ -1,3 +0,0 @@ -// run-pass - -pub fn main() { let mut v = vec![1, 2, 3]; v.push(1); } diff --git a/src/test/ui/array-slice-vec/vec-slice.rs b/src/test/ui/array-slice-vec/vec-slice.rs deleted file mode 100644 index 1f090ddd9c97d..0000000000000 --- a/src/test/ui/array-slice-vec/vec-slice.rs +++ /dev/null @@ -1,9 +0,0 @@ -// run-pass - - -pub fn main() { - let v = vec![1,2,3,4,5]; - let v2 = &v[1..3]; - assert_eq!(v2[0], 2); - assert_eq!(v2[1], 3); -} diff --git a/src/test/ui/array-slice-vec/vec-to_str.rs b/src/test/ui/array-slice-vec/vec-to_str.rs index a11cfc8e9b5c9..fbff19b862283 100644 --- a/src/test/ui/array-slice-vec/vec-to_str.rs +++ b/src/test/ui/array-slice-vec/vec-to_str.rs @@ -2,11 +2,6 @@ pub fn main() { - assert_eq!(format!("{:?}", vec![0, 1]), "[0, 1]".to_string()); - - let foo = vec![3, 4]; let bar: &[isize] = &[4, 5]; - - assert_eq!(format!("{:?}", foo), "[3, 4]"); assert_eq!(format!("{:?}", bar), "[4, 5]"); } diff --git a/src/test/ui/array-slice-vec/vec.rs b/src/test/ui/array-slice-vec/vec.rs deleted file mode 100644 index e76c1ab440e6e..0000000000000 --- a/src/test/ui/array-slice-vec/vec.rs +++ /dev/null @@ -1,15 +0,0 @@ -// run-pass - - - -pub fn main() { - let v: Vec = vec![10, 20]; - assert_eq!(v[0], 10); - assert_eq!(v[1], 20); - let mut x: usize = 0; - assert_eq!(v[x], 10); - assert_eq!(v[x + 1], 20); - x = x + 1; - assert_eq!(v[x], 20); - assert_eq!(v[x - 1], 10); -} From 791f93c796f7b4f0346eee276baf6e31ed3c81ea Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Wed, 2 Sep 2020 23:39:50 -0700 Subject: [PATCH 05/14] Allow try blocks as the argument to return expressions Fixes 76271 --- compiler/rustc_ast/src/token.rs | 1 + src/test/ui/try-block/try-block-in-return.rs | 12 ++++++++++++ 2 files changed, 13 insertions(+) create mode 100644 src/test/ui/try-block/try-block-in-return.rs diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs index c6cc890b47f79..f3da0ec130a52 100644 --- a/compiler/rustc_ast/src/token.rs +++ b/compiler/rustc_ast/src/token.rs @@ -173,6 +173,7 @@ pub fn ident_can_begin_expr(name: Symbol, span: Span, is_raw: bool) -> bool { kw::Move, kw::Return, kw::True, + kw::Try, kw::Unsafe, kw::While, kw::Yield, diff --git a/src/test/ui/try-block/try-block-in-return.rs b/src/test/ui/try-block/try-block-in-return.rs new file mode 100644 index 0000000000000..a15bfeef1c12d --- /dev/null +++ b/src/test/ui/try-block/try-block-in-return.rs @@ -0,0 +1,12 @@ +// run-pass +// compile-flags: --edition 2018 + +#![feature(try_blocks)] + +fn issue_76271() -> Option { + return try { 4 } +} + +fn main() { + assert_eq!(issue_76271(), Some(4)); +} From 2278c7255a1423b12d0efee3de43b23fa0d5b892 Mon Sep 17 00:00:00 2001 From: Rune Tynan Date: Thu, 3 Sep 2020 15:43:07 -0400 Subject: [PATCH 06/14] Remove vec-to_str.rs, merge the remaining test in with vec --- library/alloc/tests/vec.rs | 3 +++ src/test/ui/array-slice-vec/vec-to_str.rs | 7 ------- 2 files changed, 3 insertions(+), 7 deletions(-) delete mode 100644 src/test/ui/array-slice-vec/vec-to_str.rs diff --git a/library/alloc/tests/vec.rs b/library/alloc/tests/vec.rs index b422960c19982..f1c6af46d3103 100644 --- a/library/alloc/tests/vec.rs +++ b/library/alloc/tests/vec.rs @@ -92,6 +92,9 @@ fn test_debug_fmt() { let vec2 = vec![0, 1]; assert_eq!("[0, 1]", format!("{:?}", vec2)); + + let slice: &[isize] = &[4, 5]; + assert_eq!("[4, 5]", format!("{:?}", slice)); } #[test] diff --git a/src/test/ui/array-slice-vec/vec-to_str.rs b/src/test/ui/array-slice-vec/vec-to_str.rs deleted file mode 100644 index fbff19b862283..0000000000000 --- a/src/test/ui/array-slice-vec/vec-to_str.rs +++ /dev/null @@ -1,7 +0,0 @@ -// run-pass - - -pub fn main() { - let bar: &[isize] = &[4, 5]; - assert_eq!(format!("{:?}", bar), "[4, 5]"); -} From 2bc4c03eb8180f2852f773054c75cfcfe42e9cc3 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Thu, 3 Sep 2020 17:49:09 -0700 Subject: [PATCH 07/14] Disable use of `--eh-frame-hdr` on wasm32. --- compiler/rustc_target/src/spec/wasm32_base.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/compiler/rustc_target/src/spec/wasm32_base.rs b/compiler/rustc_target/src/spec/wasm32_base.rs index 62fc8f06183b7..a7957d84cbeef 100644 --- a/compiler/rustc_target/src/spec/wasm32_base.rs +++ b/compiler/rustc_target/src/spec/wasm32_base.rs @@ -83,6 +83,7 @@ pub fn options() -> TargetOptions { dll_prefix: String::new(), dll_suffix: ".wasm".to_string(), linker_is_gnu: false, + eh_frame_header: false, max_atomic_width: Some(64), From a3ee65f87e2138191cd855968c136f6ee6e35c16 Mon Sep 17 00:00:00 2001 From: Lzu Tao Date: Fri, 4 Sep 2020 02:42:50 +0000 Subject: [PATCH 08/14] Remove a useless allowed attr --- library/core/src/slice/mod.rs | 1 - library/std/src/os/raw/mod.rs | 1 - library/std/src/os/raw/tests.rs | 1 - 3 files changed, 3 deletions(-) diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index 503f015e76a68..4a4cf9cfc17dc 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -66,7 +66,6 @@ impl [T] { #[rustc_const_stable(feature = "const_slice_len", since = "1.32.0")] #[inline] // SAFETY: const sound because we transmute out the length field as a usize (which it must be) - #[allow(unused_attributes)] #[allow_internal_unstable(const_fn_union)] pub const fn len(&self) -> usize { // SAFETY: this is safe because `&[T]` and `FatPtr` have the same layout. diff --git a/library/std/src/os/raw/mod.rs b/library/std/src/os/raw/mod.rs index 1fe27a3460000..83e8853fe7923 100644 --- a/library/std/src/os/raw/mod.rs +++ b/library/std/src/os/raw/mod.rs @@ -9,7 +9,6 @@ #![stable(feature = "raw_os", since = "1.1.0")] #[cfg(test)] -#[allow(unused_imports)] mod tests; #[doc(include = "char.md")] diff --git a/library/std/src/os/raw/tests.rs b/library/std/src/os/raw/tests.rs index e808faf81d657..e7bb7d7e73e80 100644 --- a/library/std/src/os/raw/tests.rs +++ b/library/std/src/os/raw/tests.rs @@ -1,5 +1,4 @@ use crate::any::TypeId; -use crate::mem; macro_rules! ok { ($($t:ident)*) => {$( From a2fbf39cc8b619ac5b469afd43d0ff8b520511aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Miku=C5=82a?= Date: Fri, 4 Sep 2020 15:20:13 +0200 Subject: [PATCH 09/14] Fix rust.use-lld when linker is not set --- src/bootstrap/lib.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index 54651214363ba..1b655f55fb071 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -863,7 +863,12 @@ impl Build { && !target.contains("msvc") { Some(self.cc(target)) - } else if can_use_lld && self.config.use_lld && self.build == target { + } else if target.contains("msvc") + && can_use_lld + && self.config.use_lld + && self.build == target + { + // Currently we support using LLD directly via `rust.use_lld` option only with MSVC Some(&self.initial_lld) } else { None From 8f2d9069a8c19c5471c4f3490ce21eb910cf3074 Mon Sep 17 00:00:00 2001 From: Amjad Alsharafi Date: Fri, 4 Sep 2020 01:47:35 +0800 Subject: [PATCH 10/14] Implementation of incompatible features error If two features are defined as incompatible, using them together would result in an error --- compiler/rustc_ast_passes/src/feature_gate.rs | 34 +++++++++++++++++++ compiler/rustc_feature/src/active.rs | 5 +++ compiler/rustc_feature/src/lib.rs | 2 +- .../const-generics/min-and-full-same-time.rs | 7 ++++ .../min-and-full-same-time.stderr | 13 +++++++ 5 files changed, 60 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/const-generics/min-and-full-same-time.rs create mode 100644 src/test/ui/const-generics/min-and-full-same-time.stderr diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index 0ee8ef55e61bf..97e6b363eff60 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -608,6 +608,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { pub fn check_crate(krate: &ast::Crate, sess: &Session) { maybe_stage_features(sess, krate); + check_incompatible_features(sess); let mut visitor = PostExpansionVisitor { sess, features: &sess.features_untracked() }; let spans = sess.parse_sess.gated_spans.spans.borrow(); @@ -677,3 +678,36 @@ fn maybe_stage_features(sess: &Session, krate: &ast::Crate) { } } } + +fn check_incompatible_features(sess: &Session) { + let features = sess.features_untracked(); + + let declared_features = features + .declared_lang_features + .iter() + .copied() + .map(|(name, span, _)| (name, span)) + .chain(features.declared_lib_features.iter().copied()); + + for (f1, f2) in rustc_feature::INCOMPATIBLE_FEATURES + .iter() + .filter(|&&(f1, f2)| features.enabled(f1) && features.enabled(f2)) + { + if let Some((f1_name, f1_span)) = declared_features.clone().find(|(name, _)| name == f1) { + if let Some((f2_name, f2_span)) = declared_features.clone().find(|(name, _)| name == f2) + { + let spans = vec![f1_span, f2_span]; + sess.struct_span_err( + spans.clone(), + &format!( + "features `{}` and `{}` are incompatible, using them at the same time \ + is not allowed", + f1_name, f2_name + ), + ) + .help("remove one of these features") + .emit(); + } + } + } +} diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs index e858980738d71..3d7b3da45ccb9 100644 --- a/compiler/rustc_feature/src/active.rs +++ b/compiler/rustc_feature/src/active.rs @@ -605,3 +605,8 @@ pub const INCOMPLETE_FEATURES: &[Symbol] = &[ sym::lazy_normalization_consts, sym::specialization, ]; + +/// Some features are not allowed to be used together at the same time, if +/// the two are present, produce an error +pub const INCOMPATIBLE_FEATURES: &[(Symbol, Symbol)] = + &[(sym::const_generics, sym::min_const_generics)]; diff --git a/compiler/rustc_feature/src/lib.rs b/compiler/rustc_feature/src/lib.rs index 4393368cd4524..15564a59658cb 100644 --- a/compiler/rustc_feature/src/lib.rs +++ b/compiler/rustc_feature/src/lib.rs @@ -131,7 +131,7 @@ pub fn find_feature_issue(feature: Symbol, issue: GateIssue) -> Option $DIR/min-and-full-same-time.rs:1:12 + | +LL | #![feature(const_generics)] + | ^^^^^^^^^^^^^^ +... +LL | #![feature(min_const_generics)] + | ^^^^^^^^^^^^^^^^^^ + | + = help: remove one of these features + +error: aborting due to previous error + From 9e7ef659e16464d892d0b84aa9828b76c0e5e4ca Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Fri, 4 Sep 2020 13:10:23 -0400 Subject: [PATCH 11/14] Account for version number in NtIdent hack Issue #74616 tracks a backwards-compatibility hack for certain macros. This has is implemented by hard-coding the filenames and macro names of certain code that we want to continue to compile. However, the initial implementation of the hack was based on the directory structure when building the crate from its repository (e.g. `js-sys/src/lib.rs`). When the crate is build as a dependency, it will include a version number from the clone from the cargo registry (e.g. `js-sys-0.3.17/src/lib.rs`), which would fail the check. This commit modifies the backwards-compatibility hack to check that desired crate name (`js-sys` or `time-macros-impl`) is a prefix of the proper part of the path. See https://github.com/rust-lang/rust/issues/76070#issuecomment-687215646 for more details. --- compiler/rustc_ast/src/token.rs | 16 ++++++++-- .../group-compat-hack/group-compat-hack.rs | 31 +++++++++++++++---- .../group-compat-hack.stdout | 5 ++- .../js-sys-0.3.17/src/lib.rs | 7 +++++ .../time-macros-impl-0.1.0/src/lib.rs | 7 +++++ 5 files changed, 56 insertions(+), 10 deletions(-) create mode 100644 src/test/ui/proc-macro/group-compat-hack/js-sys-0.3.17/src/lib.rs create mode 100644 src/test/ui/proc-macro/group-compat-hack/time-macros-impl-0.1.0/src/lib.rs diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs index c6cc890b47f79..a2c651d1537b5 100644 --- a/compiler/rustc_ast/src/token.rs +++ b/compiler/rustc_ast/src/token.rs @@ -809,9 +809,19 @@ impl Nonterminal { if let ExpnKind::Macro(_, macro_name) = orig_span.ctxt().outer_expn_data().kind { let filename = source_map.span_to_filename(orig_span); if let FileName::Real(RealFileName::Named(path)) = filename { - if (path.ends_with("time-macros-impl/src/lib.rs") - && macro_name == sym::impl_macros) - || (path.ends_with("js-sys/src/lib.rs") && macro_name == sym::arrays) + let matches_prefix = |prefix| { + // Check for a path that ends with 'prefix*/src/lib.rs' + let mut iter = path.components().rev(); + iter.next().and_then(|p| p.as_os_str().to_str()) == Some("lib.rs") + && iter.next().and_then(|p| p.as_os_str().to_str()) == Some("src") + && iter + .next() + .and_then(|p| p.as_os_str().to_str()) + .map_or(false, |p| p.starts_with(prefix)) + }; + + if (macro_name == sym::impl_macros && matches_prefix("time-macros-impl")) + || (macro_name == sym::arrays && matches_prefix("js-sys")) { let snippet = source_map.span_to_snippet(orig_span); if snippet.as_deref() == Ok("$name") { diff --git a/src/test/ui/proc-macro/group-compat-hack/group-compat-hack.rs b/src/test/ui/proc-macro/group-compat-hack/group-compat-hack.rs index 35c101587de05..bc82a2ff196d2 100644 --- a/src/test/ui/proc-macro/group-compat-hack/group-compat-hack.rs +++ b/src/test/ui/proc-macro/group-compat-hack/group-compat-hack.rs @@ -13,18 +13,37 @@ extern crate std; // place of a `None`-delimited group. This allows us to maintain // backwards compatibility for older versions of these crates. -include!("js-sys/src/lib.rs"); -include!("time-macros-impl/src/lib.rs"); +mod no_version { + include!("js-sys/src/lib.rs"); + include!("time-macros-impl/src/lib.rs"); -macro_rules! other { - ($name:ident) => { - #[my_macro] struct Three($name); + macro_rules! other { + ($name:ident) => { + #[my_macro] struct Three($name); + } } + + struct Foo; + impl_macros!(Foo); + arrays!(Foo); + other!(Foo); } -fn main() { +mod with_version { + include!("js-sys-0.3.17/src/lib.rs"); + include!("time-macros-impl-0.1.0/src/lib.rs"); + + macro_rules! other { + ($name:ident) => { + #[my_macro] struct Three($name); + } + } + struct Foo; impl_macros!(Foo); arrays!(Foo); other!(Foo); } + + +fn main() {} diff --git a/src/test/ui/proc-macro/group-compat-hack/group-compat-hack.stdout b/src/test/ui/proc-macro/group-compat-hack/group-compat-hack.stdout index d519daab1f287..e7645280a7509 100644 --- a/src/test/ui/proc-macro/group-compat-hack/group-compat-hack.stdout +++ b/src/test/ui/proc-macro/group-compat-hack/group-compat-hack.stdout @@ -1,3 +1,6 @@ Called proc_macro_hack with TokenStream [Ident { ident: "struct", span: $DIR/time-macros-impl/src/lib.rs:5:21: 5:27 (#5) }, Ident { ident: "One", span: $DIR/time-macros-impl/src/lib.rs:5:28: 5:31 (#5) }, Group { delimiter: Parenthesis, stream: TokenStream [Ident { ident: "Foo", span: $DIR/group-compat-hack.rs:27:18: 27:21 (#0) }], span: $DIR/time-macros-impl/src/lib.rs:5:31: 5:38 (#5) }, Punct { ch: ';', spacing: Alone, span: $DIR/time-macros-impl/src/lib.rs:5:38: 5:39 (#5) }] Called proc_macro_hack with TokenStream [Ident { ident: "struct", span: $DIR/js-sys/src/lib.rs:5:21: 5:27 (#9) }, Ident { ident: "Two", span: $DIR/js-sys/src/lib.rs:5:28: 5:31 (#9) }, Group { delimiter: Parenthesis, stream: TokenStream [Ident { ident: "Foo", span: $DIR/group-compat-hack.rs:28:13: 28:16 (#0) }], span: $DIR/js-sys/src/lib.rs:5:31: 5:38 (#9) }, Punct { ch: ';', spacing: Alone, span: $DIR/js-sys/src/lib.rs:5:38: 5:39 (#9) }] -Called proc_macro_hack with TokenStream [Ident { ident: "struct", span: $DIR/group-compat-hack.rs:21:21: 21:27 (#13) }, Ident { ident: "Three", span: $DIR/group-compat-hack.rs:21:28: 21:33 (#13) }, Group { delimiter: Parenthesis, stream: TokenStream [Group { delimiter: None, stream: TokenStream [Ident { ident: "Foo", span: $DIR/group-compat-hack.rs:29:12: 29:15 (#0) }], span: $DIR/group-compat-hack.rs:21:34: 21:39 (#13) }], span: $DIR/group-compat-hack.rs:21:33: 21:40 (#13) }, Punct { ch: ';', spacing: Alone, span: $DIR/group-compat-hack.rs:21:40: 21:41 (#13) }] +Called proc_macro_hack with TokenStream [Ident { ident: "struct", span: $DIR/group-compat-hack.rs:22:25: 22:31 (#13) }, Ident { ident: "Three", span: $DIR/group-compat-hack.rs:22:32: 22:37 (#13) }, Group { delimiter: Parenthesis, stream: TokenStream [Group { delimiter: None, stream: TokenStream [Ident { ident: "Foo", span: $DIR/group-compat-hack.rs:29:12: 29:15 (#0) }], span: $DIR/group-compat-hack.rs:22:38: 22:43 (#13) }], span: $DIR/group-compat-hack.rs:22:37: 22:44 (#13) }, Punct { ch: ';', spacing: Alone, span: $DIR/group-compat-hack.rs:22:44: 22:45 (#13) }] +Called proc_macro_hack with TokenStream [Ident { ident: "struct", span: $DIR/time-macros-impl-0.1.0/src/lib.rs:5:21: 5:27 (#19) }, Ident { ident: "One", span: $DIR/time-macros-impl-0.1.0/src/lib.rs:5:28: 5:31 (#19) }, Group { delimiter: Parenthesis, stream: TokenStream [Ident { ident: "Foo", span: $DIR/group-compat-hack.rs:43:18: 43:21 (#0) }], span: $DIR/time-macros-impl-0.1.0/src/lib.rs:5:31: 5:38 (#19) }, Punct { ch: ';', spacing: Alone, span: $DIR/time-macros-impl-0.1.0/src/lib.rs:5:38: 5:39 (#19) }] +Called proc_macro_hack with TokenStream [Ident { ident: "struct", span: $DIR/js-sys-0.3.17/src/lib.rs:5:21: 5:27 (#23) }, Ident { ident: "Two", span: $DIR/js-sys-0.3.17/src/lib.rs:5:28: 5:31 (#23) }, Group { delimiter: Parenthesis, stream: TokenStream [Ident { ident: "Foo", span: $DIR/group-compat-hack.rs:44:13: 44:16 (#0) }], span: $DIR/js-sys-0.3.17/src/lib.rs:5:31: 5:38 (#23) }, Punct { ch: ';', spacing: Alone, span: $DIR/js-sys-0.3.17/src/lib.rs:5:38: 5:39 (#23) }] +Called proc_macro_hack with TokenStream [Ident { ident: "struct", span: $DIR/group-compat-hack.rs:38:25: 38:31 (#27) }, Ident { ident: "Three", span: $DIR/group-compat-hack.rs:38:32: 38:37 (#27) }, Group { delimiter: Parenthesis, stream: TokenStream [Group { delimiter: None, stream: TokenStream [Ident { ident: "Foo", span: $DIR/group-compat-hack.rs:45:12: 45:15 (#0) }], span: $DIR/group-compat-hack.rs:38:38: 38:43 (#27) }], span: $DIR/group-compat-hack.rs:38:37: 38:44 (#27) }, Punct { ch: ';', spacing: Alone, span: $DIR/group-compat-hack.rs:38:44: 38:45 (#27) }] diff --git a/src/test/ui/proc-macro/group-compat-hack/js-sys-0.3.17/src/lib.rs b/src/test/ui/proc-macro/group-compat-hack/js-sys-0.3.17/src/lib.rs new file mode 100644 index 0000000000000..d1a66940ebf3c --- /dev/null +++ b/src/test/ui/proc-macro/group-compat-hack/js-sys-0.3.17/src/lib.rs @@ -0,0 +1,7 @@ +// ignore-test this is not a test + +macro_rules! arrays { + ($name:ident) => { + #[my_macro] struct Two($name); + } +} diff --git a/src/test/ui/proc-macro/group-compat-hack/time-macros-impl-0.1.0/src/lib.rs b/src/test/ui/proc-macro/group-compat-hack/time-macros-impl-0.1.0/src/lib.rs new file mode 100644 index 0000000000000..c94c357920974 --- /dev/null +++ b/src/test/ui/proc-macro/group-compat-hack/time-macros-impl-0.1.0/src/lib.rs @@ -0,0 +1,7 @@ +// ignore-test this is not a test + +macro_rules! impl_macros { + ($name:ident) => { + #[my_macro] struct One($name); + } +} From ceffb46fad5d57d8c5b78528cee1a68ada98aa86 Mon Sep 17 00:00:00 2001 From: Rich Kadel Date: Fri, 4 Sep 2020 13:42:10 -0700 Subject: [PATCH 12/14] Update llvm-project to include PR 73 https://github.com/rust-lang/llvm-project/pull/73 --- src/llvm-project | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/llvm-project b/src/llvm-project index 45790d79496be..833dd1e3d4fd3 160000 --- a/src/llvm-project +++ b/src/llvm-project @@ -1 +1 @@ -Subproject commit 45790d79496be37fbce6ec57abad5af8fa7a34d7 +Subproject commit 833dd1e3d4fd350c7c9f6fb2ce0c5f16af7a1e21 From cff5f56886b60bab024d51d26866e99a293da56b Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 1 Sep 2020 23:16:51 +0200 Subject: [PATCH 13/14] rename MaybeUninit slice methods first_ptr -> slice_as_ptr first_ptr_mut -> slice_as_mut_ptr slice_get_ref -> slice_assume_init_ref slice_get_mut -> slice_assume_init_mut --- library/alloc/src/collections/btree/node.rs | 26 +++--- library/core/src/array/iter.rs | 4 +- library/core/src/array/mod.rs | 2 +- library/core/src/fmt/num.rs | 11 ++- library/core/src/mem/maybe_uninit.rs | 25 ++++-- library/core/src/num/flt2dec/mod.rs | 88 ++++++++++++------- .../core/src/num/flt2dec/strategy/dragon.rs | 10 +-- .../core/src/num/flt2dec/strategy/grisu.rs | 14 +-- library/core/src/slice/sort.rs | 8 +- 9 files changed, 115 insertions(+), 73 deletions(-) diff --git a/library/alloc/src/collections/btree/node.rs b/library/alloc/src/collections/btree/node.rs index 772bdf357de78..1346ad19fe20a 100644 --- a/library/alloc/src/collections/btree/node.rs +++ b/library/alloc/src/collections/btree/node.rs @@ -474,11 +474,15 @@ impl<'a, K, V, Type> NodeRef, K, V, Type> { impl<'a, K: 'a, V: 'a, Type> NodeRef, K, V, Type> { fn into_key_slice(self) -> &'a [K] { - unsafe { slice::from_raw_parts(MaybeUninit::first_ptr(&self.as_leaf().keys), self.len()) } + unsafe { + slice::from_raw_parts(MaybeUninit::slice_as_ptr(&self.as_leaf().keys), self.len()) + } } fn into_val_slice(self) -> &'a [V] { - unsafe { slice::from_raw_parts(MaybeUninit::first_ptr(&self.as_leaf().vals), self.len()) } + unsafe { + slice::from_raw_parts(MaybeUninit::slice_as_ptr(&self.as_leaf().vals), self.len()) + } } } @@ -493,7 +497,7 @@ impl<'a, K: 'a, V: 'a, Type> NodeRef, K, V, Type> { // SAFETY: The keys of a node must always be initialized up to length. unsafe { slice::from_raw_parts_mut( - MaybeUninit::first_ptr_mut(&mut (*self.as_leaf_mut()).keys), + MaybeUninit::slice_as_mut_ptr(&mut (*self.as_leaf_mut()).keys), self.len(), ) } @@ -503,7 +507,7 @@ impl<'a, K: 'a, V: 'a, Type> NodeRef, K, V, Type> { // SAFETY: The values of a node must always be initialized up to length. unsafe { slice::from_raw_parts_mut( - MaybeUninit::first_ptr_mut(&mut (*self.as_leaf_mut()).vals), + MaybeUninit::slice_as_mut_ptr(&mut (*self.as_leaf_mut()).vals), self.len(), ) } @@ -519,10 +523,10 @@ impl<'a, K: 'a, V: 'a, Type> NodeRef, K, V, Type> { let leaf = self.as_leaf_mut(); // SAFETY: The keys and values of a node must always be initialized up to length. let keys = unsafe { - slice::from_raw_parts_mut(MaybeUninit::first_ptr_mut(&mut (*leaf).keys), len) + slice::from_raw_parts_mut(MaybeUninit::slice_as_mut_ptr(&mut (*leaf).keys), len) }; let vals = unsafe { - slice::from_raw_parts_mut(MaybeUninit::first_ptr_mut(&mut (*leaf).vals), len) + slice::from_raw_parts_mut(MaybeUninit::slice_as_mut_ptr(&mut (*leaf).vals), len) }; (keys, vals) } @@ -536,9 +540,9 @@ impl<'a, K: 'a, V: 'a, Type> NodeRef, K, V, Type> { let len = self.len(); let leaf = self.node.as_ptr(); // SAFETY: The keys and values of a node must always be initialized up to length. - let keys = unsafe { slice::from_raw_parts(MaybeUninit::first_ptr(&(*leaf).keys), len) }; + let keys = unsafe { slice::from_raw_parts(MaybeUninit::slice_as_ptr(&(*leaf).keys), len) }; let vals = unsafe { - slice::from_raw_parts_mut(MaybeUninit::first_ptr_mut(&mut (*leaf).vals), len) + slice::from_raw_parts_mut(MaybeUninit::slice_as_mut_ptr(&mut (*leaf).vals), len) }; (keys, vals) } @@ -617,7 +621,7 @@ impl<'a, K, V> NodeRef, K, V, marker::Internal> { slice_insert(self.vals_mut(), 0, val); slice_insert( slice::from_raw_parts_mut( - MaybeUninit::first_ptr_mut(&mut self.as_internal_mut().edges), + MaybeUninit::slice_as_mut_ptr(&mut self.as_internal_mut().edges), self.len() + 1, ), 0, @@ -675,7 +679,7 @@ impl<'a, K, V> NodeRef, K, V, marker::LeafOrInternal> { ForceResult::Internal(mut internal) => { let edge = slice_remove( slice::from_raw_parts_mut( - MaybeUninit::first_ptr_mut(&mut internal.as_internal_mut().edges), + MaybeUninit::slice_as_mut_ptr(&mut internal.as_internal_mut().edges), old_len + 1, ), 0, @@ -962,7 +966,7 @@ impl<'a, K, V> Handle, K, V, marker::Internal>, marker:: slice_insert( slice::from_raw_parts_mut( - MaybeUninit::first_ptr_mut(&mut self.node.as_internal_mut().edges), + MaybeUninit::slice_as_mut_ptr(&mut self.node.as_internal_mut().edges), self.node.len(), ), self.idx + 1, diff --git a/library/core/src/array/iter.rs b/library/core/src/array/iter.rs index 919070aadf972..2e8b6419eea1e 100644 --- a/library/core/src/array/iter.rs +++ b/library/core/src/array/iter.rs @@ -73,7 +73,7 @@ impl IntoIter { // SAFETY: We know that all elements within `alive` are properly initialized. unsafe { let slice = self.data.get_unchecked(self.alive.clone()); - MaybeUninit::slice_get_ref(slice) + MaybeUninit::slice_assume_init_ref(slice) } } @@ -82,7 +82,7 @@ impl IntoIter { // SAFETY: We know that all elements within `alive` are properly initialized. unsafe { let slice = self.data.get_unchecked_mut(self.alive.clone()); - MaybeUninit::slice_get_mut(slice) + MaybeUninit::slice_assume_init_mut(slice) } } } diff --git a/library/core/src/array/mod.rs b/library/core/src/array/mod.rs index f45c99c285c84..c1d3aca6fdd4f 100644 --- a/library/core/src/array/mod.rs +++ b/library/core/src/array/mod.rs @@ -410,7 +410,7 @@ impl [T; N] { } let mut dst = MaybeUninit::uninit_array::(); let mut guard: Guard = - Guard { dst: MaybeUninit::first_ptr_mut(&mut dst), initialized: 0 }; + Guard { dst: MaybeUninit::slice_as_mut_ptr(&mut dst), initialized: 0 }; for (src, dst) in IntoIter::new(self).zip(&mut dst) { dst.write(f(src)); guard.initialized += 1; diff --git a/library/core/src/fmt/num.rs b/library/core/src/fmt/num.rs index 7d77e33d74378..ae3d0ddd46beb 100644 --- a/library/core/src/fmt/num.rs +++ b/library/core/src/fmt/num.rs @@ -85,7 +85,10 @@ trait GenericRadix { // SAFETY: The only chars in `buf` are created by `Self::digit` which are assumed to be // valid UTF-8 let buf = unsafe { - str::from_utf8_unchecked(slice::from_raw_parts(MaybeUninit::first_ptr(buf), buf.len())) + str::from_utf8_unchecked(slice::from_raw_parts( + MaybeUninit::slice_as_ptr(buf), + buf.len(), + )) }; f.pad_integral(is_nonnegative, Self::PREFIX, buf) } @@ -192,7 +195,7 @@ macro_rules! impl_Display { // 2^128 is about 3*10^38, so 39 gives an extra byte of space let mut buf = [MaybeUninit::::uninit(); 39]; let mut curr = buf.len() as isize; - let buf_ptr = MaybeUninit::first_ptr_mut(&mut buf); + let buf_ptr = MaybeUninit::slice_as_mut_ptr(&mut buf); let lut_ptr = DEC_DIGITS_LUT.as_ptr(); // SAFETY: Since `d1` and `d2` are always less than or equal to `198`, we @@ -322,7 +325,7 @@ macro_rules! impl_Exp { // that `curr >= 0`. let mut buf = [MaybeUninit::::uninit(); 40]; let mut curr = buf.len() as isize; //index for buf - let buf_ptr = MaybeUninit::first_ptr_mut(&mut buf); + let buf_ptr = MaybeUninit::slice_as_mut_ptr(&mut buf); let lut_ptr = DEC_DIGITS_LUT.as_ptr(); // decode 2 chars at a time @@ -370,7 +373,7 @@ macro_rules! impl_Exp { // stores 'e' (or 'E') and the up to 2-digit exponent let mut exp_buf = [MaybeUninit::::uninit(); 3]; - let exp_ptr = MaybeUninit::first_ptr_mut(&mut exp_buf); + let exp_ptr = MaybeUninit::slice_as_mut_ptr(&mut exp_buf); // SAFETY: In either case, `exp_buf` is written within bounds and `exp_ptr[..len]` // is contained within `exp_buf` since `len <= 3`. let exp_slice = unsafe { diff --git a/library/core/src/mem/maybe_uninit.rs b/library/core/src/mem/maybe_uninit.rs index a79d9e25f34fc..f770df61d9c54 100644 --- a/library/core/src/mem/maybe_uninit.rs +++ b/library/core/src/mem/maybe_uninit.rs @@ -281,7 +281,7 @@ impl MaybeUninit { /// # Examples /// /// ```no_run - /// #![feature(maybe_uninit_uninit_array, maybe_uninit_extra, maybe_uninit_slice_assume_init)] + /// #![feature(maybe_uninit_uninit_array, maybe_uninit_extra, maybe_uninit_slice)] /// /// use std::mem::MaybeUninit; /// @@ -293,7 +293,7 @@ impl MaybeUninit { /// fn read(buf: &mut [MaybeUninit]) -> &[u8] { /// unsafe { /// let len = read_into_buffer(buf.as_mut_ptr() as *mut u8, buf.len()); - /// MaybeUninit::slice_get_ref(&buf[..len]) + /// MaybeUninit::slice_assume_init_ref(&buf[..len]) /// } /// } /// @@ -303,6 +303,7 @@ impl MaybeUninit { #[unstable(feature = "maybe_uninit_uninit_array", issue = "none")] #[inline(always)] pub fn uninit_array() -> [Self; LEN] { + // SAFETY: An uninitialized `[MaybeUninit<_>; LEN]` is valid. unsafe { MaybeUninit::<[MaybeUninit; LEN]>::uninit().assume_init() } } @@ -769,9 +770,13 @@ impl MaybeUninit { /// It is up to the caller to guarantee that the `MaybeUninit` elements /// really are in an initialized state. /// Calling this when the content is not yet fully initialized causes undefined behavior. - #[unstable(feature = "maybe_uninit_slice_assume_init", issue = "none")] + /// + /// See [`assume_init_ref`] for more details and examples. + /// + /// [`assume_init_ref`]: MaybeUninit::assume_init_ref + #[unstable(feature = "maybe_uninit_slice", issue = "63569")] #[inline(always)] - pub unsafe fn slice_get_ref(slice: &[Self]) -> &[T] { + pub unsafe fn slice_assume_init_ref(slice: &[Self]) -> &[T] { // SAFETY: casting slice to a `*const [T]` is safe since the caller guarantees that // `slice` is initialized, and`MaybeUninit` is guaranteed to have the same layout as `T`. // The pointer obtained is valid since it refers to memory owned by `slice` which is a @@ -786,9 +791,13 @@ impl MaybeUninit { /// It is up to the caller to guarantee that the `MaybeUninit` elements /// really are in an initialized state. /// Calling this when the content is not yet fully initialized causes undefined behavior. - #[unstable(feature = "maybe_uninit_slice_assume_init", issue = "none")] + /// + /// See [`assume_init_mut`] for more details and examples. + /// + /// [`assume_init_mut`]: MaybeUninit::assume_init_mut + #[unstable(feature = "maybe_uninit_slice", issue = "63569")] #[inline(always)] - pub unsafe fn slice_get_mut(slice: &mut [Self]) -> &mut [T] { + pub unsafe fn slice_assume_init_mut(slice: &mut [Self]) -> &mut [T] { // SAFETY: similar to safety notes for `slice_get_ref`, but we have a // mutable reference which is also guaranteed to be valid for writes. unsafe { &mut *(slice as *mut [Self] as *mut [T]) } @@ -797,14 +806,14 @@ impl MaybeUninit { /// Gets a pointer to the first element of the array. #[unstable(feature = "maybe_uninit_slice", issue = "63569")] #[inline(always)] - pub fn first_ptr(this: &[MaybeUninit]) -> *const T { + pub fn slice_as_ptr(this: &[MaybeUninit]) -> *const T { this as *const [MaybeUninit] as *const T } /// Gets a mutable pointer to the first element of the array. #[unstable(feature = "maybe_uninit_slice", issue = "63569")] #[inline(always)] - pub fn first_ptr_mut(this: &mut [MaybeUninit]) -> *mut T { + pub fn slice_as_mut_ptr(this: &mut [MaybeUninit]) -> *mut T { this as *mut [MaybeUninit] as *mut T } } diff --git a/library/core/src/num/flt2dec/mod.rs b/library/core/src/num/flt2dec/mod.rs index 1f28edb412827..e8f9d6574e2d0 100644 --- a/library/core/src/num/flt2dec/mod.rs +++ b/library/core/src/num/flt2dec/mod.rs @@ -311,10 +311,10 @@ fn digits_to_dec_str<'a>( if frac_digits > buf.len() && frac_digits - buf.len() > minus_exp { parts[3] = MaybeUninit::new(Part::Zero((frac_digits - buf.len()) - minus_exp)); // SAFETY: we just initialized the elements `..4`. - unsafe { MaybeUninit::slice_get_ref(&parts[..4]) } + unsafe { MaybeUninit::slice_assume_init_ref(&parts[..4]) } } else { // SAFETY: we just initialized the elements `..3`. - unsafe { MaybeUninit::slice_get_ref(&parts[..3]) } + unsafe { MaybeUninit::slice_assume_init_ref(&parts[..3]) } } } else { let exp = exp as usize; @@ -326,10 +326,10 @@ fn digits_to_dec_str<'a>( if frac_digits > buf.len() - exp { parts[3] = MaybeUninit::new(Part::Zero(frac_digits - (buf.len() - exp))); // SAFETY: we just initialized the elements `..4`. - unsafe { MaybeUninit::slice_get_ref(&parts[..4]) } + unsafe { MaybeUninit::slice_assume_init_ref(&parts[..4]) } } else { // SAFETY: we just initialized the elements `..3`. - unsafe { MaybeUninit::slice_get_ref(&parts[..3]) } + unsafe { MaybeUninit::slice_assume_init_ref(&parts[..3]) } } } else { // the decimal point is after rendered digits: [1234][____0000] or [1234][__][.][__]. @@ -339,10 +339,10 @@ fn digits_to_dec_str<'a>( parts[2] = MaybeUninit::new(Part::Copy(b".")); parts[3] = MaybeUninit::new(Part::Zero(frac_digits)); // SAFETY: we just initialized the elements `..4`. - unsafe { MaybeUninit::slice_get_ref(&parts[..4]) } + unsafe { MaybeUninit::slice_assume_init_ref(&parts[..4]) } } else { // SAFETY: we just initialized the elements `..2`. - unsafe { MaybeUninit::slice_get_ref(&parts[..2]) } + unsafe { MaybeUninit::slice_assume_init_ref(&parts[..2]) } } } } @@ -393,7 +393,7 @@ fn digits_to_exp_str<'a>( parts[n + 1] = MaybeUninit::new(Part::Num(exp as u16)); } // SAFETY: we just initialized the elements `..n + 2`. - unsafe { MaybeUninit::slice_get_ref(&parts[..n + 2]) } + unsafe { MaybeUninit::slice_assume_init_ref(&parts[..n + 2]) } } /// Sign formatting options. @@ -487,24 +487,30 @@ where FullDecoded::Nan => { parts[0] = MaybeUninit::new(Part::Copy(b"NaN")); // SAFETY: we just initialized the elements `..1`. - Formatted { sign, parts: unsafe { MaybeUninit::slice_get_ref(&parts[..1]) } } + Formatted { sign, parts: unsafe { MaybeUninit::slice_assume_init_ref(&parts[..1]) } } } FullDecoded::Infinite => { parts[0] = MaybeUninit::new(Part::Copy(b"inf")); // SAFETY: we just initialized the elements `..1`. - Formatted { sign, parts: unsafe { MaybeUninit::slice_get_ref(&parts[..1]) } } + Formatted { sign, parts: unsafe { MaybeUninit::slice_assume_init_ref(&parts[..1]) } } } FullDecoded::Zero => { if frac_digits > 0 { // [0.][0000] parts[0] = MaybeUninit::new(Part::Copy(b"0.")); parts[1] = MaybeUninit::new(Part::Zero(frac_digits)); - // SAFETY: we just initialized the elements `..2`. - Formatted { sign, parts: unsafe { MaybeUninit::slice_get_ref(&parts[..2]) } } + Formatted { + sign, + // SAFETY: we just initialized the elements `..2`. + parts: unsafe { MaybeUninit::slice_assume_init_ref(&parts[..2]) }, + } } else { parts[0] = MaybeUninit::new(Part::Copy(b"0")); - // SAFETY: we just initialized the elements `..1`. - Formatted { sign, parts: unsafe { MaybeUninit::slice_get_ref(&parts[..1]) } } + Formatted { + sign, + // SAFETY: we just initialized the elements `..1`. + parts: unsafe { MaybeUninit::slice_assume_init_ref(&parts[..1]) }, + } } } FullDecoded::Finite(ref decoded) => { @@ -557,12 +563,12 @@ where FullDecoded::Nan => { parts[0] = MaybeUninit::new(Part::Copy(b"NaN")); // SAFETY: we just initialized the elements `..1`. - Formatted { sign, parts: unsafe { MaybeUninit::slice_get_ref(&parts[..1]) } } + Formatted { sign, parts: unsafe { MaybeUninit::slice_assume_init_ref(&parts[..1]) } } } FullDecoded::Infinite => { parts[0] = MaybeUninit::new(Part::Copy(b"inf")); // SAFETY: we just initialized the elements `..1`. - Formatted { sign, parts: unsafe { MaybeUninit::slice_get_ref(&parts[..1]) } } + Formatted { sign, parts: unsafe { MaybeUninit::slice_assume_init_ref(&parts[..1]) } } } FullDecoded::Zero => { parts[0] = if dec_bounds.0 <= 0 && 0 < dec_bounds.1 { @@ -571,7 +577,7 @@ where MaybeUninit::new(Part::Copy(if upper { b"0E0" } else { b"0e0" })) }; // SAFETY: we just initialized the elements `..1`. - Formatted { sign, parts: unsafe { MaybeUninit::slice_get_ref(&parts[..1]) } } + Formatted { sign, parts: unsafe { MaybeUninit::slice_assume_init_ref(&parts[..1]) } } } FullDecoded::Finite(ref decoded) => { let (buf, exp) = format_shortest(decoded, buf); @@ -648,12 +654,12 @@ where FullDecoded::Nan => { parts[0] = MaybeUninit::new(Part::Copy(b"NaN")); // SAFETY: we just initialized the elements `..1`. - Formatted { sign, parts: unsafe { MaybeUninit::slice_get_ref(&parts[..1]) } } + Formatted { sign, parts: unsafe { MaybeUninit::slice_assume_init_ref(&parts[..1]) } } } FullDecoded::Infinite => { parts[0] = MaybeUninit::new(Part::Copy(b"inf")); // SAFETY: we just initialized the elements `..1`. - Formatted { sign, parts: unsafe { MaybeUninit::slice_get_ref(&parts[..1]) } } + Formatted { sign, parts: unsafe { MaybeUninit::slice_assume_init_ref(&parts[..1]) } } } FullDecoded::Zero => { if ndigits > 1 { @@ -661,12 +667,18 @@ where parts[0] = MaybeUninit::new(Part::Copy(b"0.")); parts[1] = MaybeUninit::new(Part::Zero(ndigits - 1)); parts[2] = MaybeUninit::new(Part::Copy(if upper { b"E0" } else { b"e0" })); - // SAFETY: we just initialized the elements `..3`. - Formatted { sign, parts: unsafe { MaybeUninit::slice_get_ref(&parts[..3]) } } + Formatted { + sign, + // SAFETY: we just initialized the elements `..3`. + parts: unsafe { MaybeUninit::slice_assume_init_ref(&parts[..3]) }, + } } else { parts[0] = MaybeUninit::new(Part::Copy(if upper { b"0E0" } else { b"0e0" })); - // SAFETY: we just initialized the elements `..1`. - Formatted { sign, parts: unsafe { MaybeUninit::slice_get_ref(&parts[..1]) } } + Formatted { + sign, + // SAFETY: we just initialized the elements `..1`. + parts: unsafe { MaybeUninit::slice_assume_init_ref(&parts[..1]) }, + } } } FullDecoded::Finite(ref decoded) => { @@ -716,24 +728,30 @@ where FullDecoded::Nan => { parts[0] = MaybeUninit::new(Part::Copy(b"NaN")); // SAFETY: we just initialized the elements `..1`. - Formatted { sign, parts: unsafe { MaybeUninit::slice_get_ref(&parts[..1]) } } + Formatted { sign, parts: unsafe { MaybeUninit::slice_assume_init_ref(&parts[..1]) } } } FullDecoded::Infinite => { parts[0] = MaybeUninit::new(Part::Copy(b"inf")); // SAFETY: we just initialized the elements `..1`. - Formatted { sign, parts: unsafe { MaybeUninit::slice_get_ref(&parts[..1]) } } + Formatted { sign, parts: unsafe { MaybeUninit::slice_assume_init_ref(&parts[..1]) } } } FullDecoded::Zero => { if frac_digits > 0 { // [0.][0000] parts[0] = MaybeUninit::new(Part::Copy(b"0.")); parts[1] = MaybeUninit::new(Part::Zero(frac_digits)); - // SAFETY: we just initialized the elements `..2`. - Formatted { sign, parts: unsafe { MaybeUninit::slice_get_ref(&parts[..2]) } } + Formatted { + sign, + // SAFETY: we just initialized the elements `..2`. + parts: unsafe { MaybeUninit::slice_assume_init_ref(&parts[..2]) }, + } } else { parts[0] = MaybeUninit::new(Part::Copy(b"0")); - // SAFETY: we just initialized the elements `..1`. - Formatted { sign, parts: unsafe { MaybeUninit::slice_get_ref(&parts[..1]) } } + Formatted { + sign, + // SAFETY: we just initialized the elements `..1`. + parts: unsafe { MaybeUninit::slice_assume_init_ref(&parts[..1]) }, + } } } FullDecoded::Finite(ref decoded) => { @@ -754,12 +772,18 @@ where // [0.][0000] parts[0] = MaybeUninit::new(Part::Copy(b"0.")); parts[1] = MaybeUninit::new(Part::Zero(frac_digits)); - // SAFETY: we just initialized the elements `..2`. - Formatted { sign, parts: unsafe { MaybeUninit::slice_get_ref(&parts[..2]) } } + Formatted { + sign, + // SAFETY: we just initialized the elements `..2`. + parts: unsafe { MaybeUninit::slice_assume_init_ref(&parts[..2]) }, + } } else { parts[0] = MaybeUninit::new(Part::Copy(b"0")); - // SAFETY: we just initialized the elements `..1`. - Formatted { sign, parts: unsafe { MaybeUninit::slice_get_ref(&parts[..1]) } } + Formatted { + sign, + // SAFETY: we just initialized the elements `..1`. + parts: unsafe { MaybeUninit::slice_assume_init_ref(&parts[..1]) }, + } } } else { Formatted { sign, parts: digits_to_dec_str(buf, exp, frac_digits, parts) } diff --git a/library/core/src/num/flt2dec/strategy/dragon.rs b/library/core/src/num/flt2dec/strategy/dragon.rs index 8cb6763cdbe45..8ced5971ec2f9 100644 --- a/library/core/src/num/flt2dec/strategy/dragon.rs +++ b/library/core/src/num/flt2dec/strategy/dragon.rs @@ -246,7 +246,7 @@ pub fn format_shortest<'a>( // it seems that this condition is very hard to satisfy (possibly impossible), // but we are just being safe and consistent here. // SAFETY: we initialized that memory above. - if let Some(c) = round_up(unsafe { MaybeUninit::slice_get_mut(&mut buf[..i]) }) { + if let Some(c) = round_up(unsafe { MaybeUninit::slice_assume_init_mut(&mut buf[..i]) }) { buf[i] = MaybeUninit::new(c); i += 1; k += 1; @@ -254,7 +254,7 @@ pub fn format_shortest<'a>( } // SAFETY: we initialized that memory above. - (unsafe { MaybeUninit::slice_get_ref(&buf[..i]) }, k) + (unsafe { MaybeUninit::slice_assume_init_ref(&buf[..i]) }, k) } /// The exact and fixed mode implementation for Dragon. @@ -332,7 +332,7 @@ pub fn format_exact<'a>( *c = MaybeUninit::new(b'0'); } // SAFETY: we initialized that memory above. - return (unsafe { MaybeUninit::slice_get_ref(&buf[..len]) }, k); + return (unsafe { MaybeUninit::slice_assume_init_ref(&buf[..len]) }, k); } let mut d = 0; @@ -371,7 +371,7 @@ pub fn format_exact<'a>( // if rounding up changes the length, the exponent should also change. // but we've been requested a fixed number of digits, so do not alter the buffer... // SAFETY: we initialized that memory above. - if let Some(c) = round_up(unsafe { MaybeUninit::slice_get_mut(&mut buf[..len]) }) { + if let Some(c) = round_up(unsafe { MaybeUninit::slice_assume_init_mut(&mut buf[..len]) }) { // ...unless we've been requested the fixed precision instead. // we also need to check that, if the original buffer was empty, // the additional digit can only be added when `k == limit` (edge case). @@ -384,5 +384,5 @@ pub fn format_exact<'a>( } // SAFETY: we initialized that memory above. - (unsafe { MaybeUninit::slice_get_ref(&buf[..len]) }, k) + (unsafe { MaybeUninit::slice_assume_init_ref(&buf[..len]) }, k) } diff --git a/library/core/src/num/flt2dec/strategy/grisu.rs b/library/core/src/num/flt2dec/strategy/grisu.rs index ed1dd654a3add..a4cb51c6297af 100644 --- a/library/core/src/num/flt2dec/strategy/grisu.rs +++ b/library/core/src/num/flt2dec/strategy/grisu.rs @@ -276,7 +276,7 @@ pub fn format_shortest_opt<'a>( let ten_kappa = (ten_kappa as u64) << e; // scale 10^kappa back to the shared exponent return round_and_weed( // SAFETY: we initialized that memory above. - unsafe { MaybeUninit::slice_get_mut(&mut buf[..i]) }, + unsafe { MaybeUninit::slice_assume_init_mut(&mut buf[..i]) }, exp, plus1rem, delta1, @@ -327,7 +327,7 @@ pub fn format_shortest_opt<'a>( let ten_kappa = 1 << e; // implicit divisor return round_and_weed( // SAFETY: we initialized that memory above. - unsafe { MaybeUninit::slice_get_mut(&mut buf[..i]) }, + unsafe { MaybeUninit::slice_assume_init_mut(&mut buf[..i]) }, exp, r, threshold, @@ -701,7 +701,7 @@ pub fn format_exact_opt<'a>( // `10^kappa` did not overflow after all, the second check is fine. if ten_kappa - remainder > remainder && ten_kappa - 2 * remainder >= 2 * ulp { // SAFETY: our caller initialized that memory. - return Some((unsafe { MaybeUninit::slice_get_ref(&buf[..len]) }, exp)); + return Some((unsafe { MaybeUninit::slice_assume_init_ref(&buf[..len]) }, exp)); } // :<------- remainder ------>| : @@ -722,8 +722,10 @@ pub fn format_exact_opt<'a>( // as `10^kappa` is never zero). also note that `remainder - ulp <= 10^kappa`, // so the second check does not overflow. if remainder > ulp && ten_kappa - (remainder - ulp) <= remainder - ulp { - // SAFETY: our caller must have initialized that memory. - if let Some(c) = round_up(unsafe { MaybeUninit::slice_get_mut(&mut buf[..len]) }) { + if let Some(c) = + // SAFETY: our caller must have initialized that memory. + round_up(unsafe { MaybeUninit::slice_assume_init_mut(&mut buf[..len]) }) + { // only add an additional digit when we've been requested the fixed precision. // we also need to check that, if the original buffer was empty, // the additional digit can only be added when `exp == limit` (edge case). @@ -734,7 +736,7 @@ pub fn format_exact_opt<'a>( } } // SAFETY: we and our caller initialized that memory. - return Some((unsafe { MaybeUninit::slice_get_ref(&buf[..len]) }, exp)); + return Some((unsafe { MaybeUninit::slice_assume_init_ref(&buf[..len]) }, exp)); } // otherwise we are doomed (i.e., some values between `v - 1 ulp` and `v + 1 ulp` are diff --git a/library/core/src/slice/sort.rs b/library/core/src/slice/sort.rs index 972a33d6489e9..4a00124fcff3e 100644 --- a/library/core/src/slice/sort.rs +++ b/library/core/src/slice/sort.rs @@ -299,8 +299,8 @@ where if start_l == end_l { // Trace `block_l` elements from the left side. - start_l = MaybeUninit::first_ptr_mut(&mut offsets_l); - end_l = MaybeUninit::first_ptr_mut(&mut offsets_l); + start_l = MaybeUninit::slice_as_mut_ptr(&mut offsets_l); + end_l = MaybeUninit::slice_as_mut_ptr(&mut offsets_l); let mut elem = l; for i in 0..block_l { @@ -325,8 +325,8 @@ where if start_r == end_r { // Trace `block_r` elements from the right side. - start_r = MaybeUninit::first_ptr_mut(&mut offsets_r); - end_r = MaybeUninit::first_ptr_mut(&mut offsets_r); + start_r = MaybeUninit::slice_as_mut_ptr(&mut offsets_r); + end_r = MaybeUninit::slice_as_mut_ptr(&mut offsets_r); let mut elem = r; for i in 0..block_r { From 35068326b5966530225c8fc01bcdaa0fb4041138 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 2 Sep 2020 10:00:08 +0200 Subject: [PATCH 14/14] document remaining unsafety in maybe_uninit.rs --- library/core/src/mem/maybe_uninit.rs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/library/core/src/mem/maybe_uninit.rs b/library/core/src/mem/maybe_uninit.rs index f770df61d9c54..b64abf68c5e4a 100644 --- a/library/core/src/mem/maybe_uninit.rs +++ b/library/core/src/mem/maybe_uninit.rs @@ -3,8 +3,6 @@ use crate::fmt; use crate::intrinsics; use crate::mem::ManuallyDrop; -// ignore-tidy-undocumented-unsafe - /// A wrapper type to construct uninitialized instances of `T`. /// /// # Initialization invariant @@ -355,6 +353,7 @@ impl MaybeUninit { #[rustc_diagnostic_item = "maybe_uninit_zeroed"] pub fn zeroed() -> MaybeUninit { let mut u = MaybeUninit::::uninit(); + // SAFETY: `u.as_mut_ptr()` points to allocated memory. unsafe { u.as_mut_ptr().write_bytes(0u8, 1); } @@ -368,10 +367,9 @@ impl MaybeUninit { #[unstable(feature = "maybe_uninit_extra", issue = "63567")] #[inline(always)] pub fn write(&mut self, val: T) -> &mut T { - unsafe { - self.value = ManuallyDrop::new(val); - self.assume_init_mut() - } + *self = MaybeUninit::new(val); + // SAFETY: We just initialized this value. + unsafe { self.assume_init_mut() } } /// Gets a pointer to the contained value. Reading from this pointer or turning it