From 179f63dafcf9463b48d82e8698a844e18bf94370 Mon Sep 17 00:00:00 2001 From: Bastian Kauschke Date: Tue, 22 Sep 2020 21:35:43 +0200 Subject: [PATCH 1/3] add array from_ref --- library/core/src/array/mod.rs | 14 ++++++++++++++ library/core/tests/array.rs | 17 ++++++++++++++++- library/core/tests/lib.rs | 1 + 3 files changed, 31 insertions(+), 1 deletion(-) diff --git a/library/core/src/array/mod.rs b/library/core/src/array/mod.rs index c1d3aca6fdd4f..5730074bf2747 100644 --- a/library/core/src/array/mod.rs +++ b/library/core/src/array/mod.rs @@ -19,6 +19,20 @@ mod iter; #[unstable(feature = "array_value_iter", issue = "65798")] pub use iter::IntoIter; +/// Converts a reference to `T` into a reference to an array of length 1 (without copying). +#[unstable(feature = "array_from_ref", issue = "none")] +pub fn from_ref(s: &T) -> &[T; 1] { + // SAFETY: Converting `&T` to `&[T; 1]` is sound. + unsafe { &*(s as *const T).cast::<[T; 1]>() } +} + +/// Converts a mutable reference to `T` into a mutable reference to an array of length 1 (without copying). +#[unstable(feature = "array_from_ref", issue = "none")] +pub fn from_mut(s: &mut T) -> &mut [T; 1] { + // SAFETY: Converting `&mut T` to `&mut [T; 1]` is sound. + unsafe { &mut *(s as *mut T).cast::<[T; 1]>() } +} + /// Utility trait implemented only on arrays of fixed size /// /// This trait can be used to implement other traits on fixed-size arrays diff --git a/library/core/tests/array.rs b/library/core/tests/array.rs index 5aba1a5d958d1..dbcea2747a00d 100644 --- a/library/core/tests/array.rs +++ b/library/core/tests/array.rs @@ -1,4 +1,4 @@ -use core::array::{FixedSizeArray, IntoIter}; +use core::array::{self, FixedSizeArray, IntoIter}; use core::convert::TryFrom; #[test] @@ -19,6 +19,21 @@ fn fixed_size_array() { assert_eq!(FixedSizeArray::as_mut_slice(&mut empty_zero_sized).len(), 0); } +#[test] +fn array_from_ref() { + let value: String = "Hello World!".into(); + let arr: &[String; 1] = array::from_ref(&value); + assert_eq!(&[value.clone()], arr); +} + +#[test] +fn array_from_mut() { + let mut value: String = "Hello World".into(); + let arr: &mut [String; 1] = array::from_mut(&mut value); + arr[0].push_str("!"); + assert_eq!(&value, "Hello World!"); +} + #[test] fn array_try_from() { macro_rules! test { diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs index 7e75c7cf47bf6..d8b36beb3e085 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs @@ -1,5 +1,6 @@ #![feature(alloc_layout_extra)] #![feature(array_chunks)] +#![feature(array_from_ref)] #![feature(array_methods)] #![feature(array_map)] #![feature(array_windows)] From ed97b421059d25a86b2f947734a8ae366b68f473 Mon Sep 17 00:00:00 2001 From: Bastian Kauschke Date: Wed, 23 Sep 2020 13:48:21 +0200 Subject: [PATCH 2/3] add tracking issue --- library/core/src/array/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/core/src/array/mod.rs b/library/core/src/array/mod.rs index 5730074bf2747..966272ca11549 100644 --- a/library/core/src/array/mod.rs +++ b/library/core/src/array/mod.rs @@ -20,14 +20,14 @@ mod iter; pub use iter::IntoIter; /// Converts a reference to `T` into a reference to an array of length 1 (without copying). -#[unstable(feature = "array_from_ref", issue = "none")] +#[unstable(feature = "array_from_ref", issue = "77101")] pub fn from_ref(s: &T) -> &[T; 1] { // SAFETY: Converting `&T` to `&[T; 1]` is sound. unsafe { &*(s as *const T).cast::<[T; 1]>() } } /// Converts a mutable reference to `T` into a mutable reference to an array of length 1 (without copying). -#[unstable(feature = "array_from_ref", issue = "none")] +#[unstable(feature = "array_from_ref", issue = "77101")] pub fn from_mut(s: &mut T) -> &mut [T; 1] { // SAFETY: Converting `&mut T` to `&mut [T; 1]` is sound. unsafe { &mut *(s as *mut T).cast::<[T; 1]>() } From 5b3016134fef93d9bed343bb15da837acf50b635 Mon Sep 17 00:00:00 2001 From: Bastian Kauschke Date: Wed, 23 Sep 2020 21:33:45 +0200 Subject: [PATCH 3/3] use array::from_ref for slices --- library/core/src/slice/raw.rs | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/library/core/src/slice/raw.rs b/library/core/src/slice/raw.rs index a5811c5e47289..09209306c9d0f 100644 --- a/library/core/src/slice/raw.rs +++ b/library/core/src/slice/raw.rs @@ -1,5 +1,6 @@ //! Free functions to create `&[T]` and `&mut [T]`. +use crate::array; use crate::intrinsics::is_aligned_and_not_null; use crate::mem; use crate::ptr; @@ -140,19 +141,11 @@ pub unsafe fn from_raw_parts_mut<'a, T>(data: *mut T, len: usize) -> &'a mut [T] /// Converts a reference to T into a slice of length 1 (without copying). #[stable(feature = "from_ref", since = "1.28.0")] pub fn from_ref(s: &T) -> &[T] { - // SAFETY: a reference is guaranteed to be valid for reads. The returned - // reference cannot be mutated as it is an immutable reference. - // `mem::size_of::()` cannot be larger than `isize::MAX`. - // Thus the call to `from_raw_parts` is safe. - unsafe { from_raw_parts(s, 1) } + array::from_ref(s) } /// Converts a reference to T into a slice of length 1 (without copying). #[stable(feature = "from_ref", since = "1.28.0")] pub fn from_mut(s: &mut T) -> &mut [T] { - // SAFETY: a mutable reference is guaranteed to be valid for writes. - // The reference cannot be accessed by another pointer as it is an mutable reference. - // `mem::size_of::()` cannot be larger than `isize::MAX`. - // Thus the call to `from_raw_parts_mut` is safe. - unsafe { from_raw_parts_mut(s, 1) } + array::from_mut(s) }