diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index 488fda0b24738..c92db517cad36 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -76,9 +76,10 @@ #![stable(feature = "rust1", since = "1.0.0")] use core::any::Any; +use core::array::LengthAtMost32; use core::borrow; use core::cmp::Ordering; -use core::convert::From; +use core::convert::{From, TryFrom}; use core::fmt; use core::future::Future; use core::hash::{Hash, Hasher}; @@ -612,6 +613,22 @@ impl From> for Box<[u8]> { } } +#[unstable(feature = "boxed_slice_try_from", issue = "0")] +impl TryFrom> for Box<[T; N]> +where + [T; N]: LengthAtMost32, +{ + type Error = Box<[T]>; + + fn try_from(boxed_slice: Box<[T]>) -> Result { + if boxed_slice.len() == N { + Ok(unsafe { Box::from_raw(Box::into_raw(boxed_slice) as *mut [T; N]) }) + } else { + Err(boxed_slice) + } + } +} + impl Box { #[inline] #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs index 98fa754759aa4..deea74daa52d5 100644 --- a/src/liballoc/lib.rs +++ b/src/liballoc/lib.rs @@ -82,9 +82,9 @@ #![feature(box_syntax)] #![feature(cfg_target_has_atomic)] #![feature(coerce_unsized)] -#![cfg_attr(not(bootstrap), feature(const_in_array_repeat_expressions))] #![feature(const_generic_impls_guard)] #![feature(const_generics)] +#![cfg_attr(not(bootstrap), feature(const_in_array_repeat_expressions))] #![feature(dispatch_from_dyn)] #![feature(core_intrinsics)] #![feature(dropck_eyepatch)] diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index e33aac3af474e..0c406a92029a7 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -232,6 +232,7 @@ use crate::boxed::Box; use std::boxed::Box; use core::any::Any; +use core::array::LengthAtMost32; use core::borrow; use core::cell::Cell; use core::cmp::Ordering; @@ -245,7 +246,7 @@ use core::ops::{Deref, Receiver, CoerceUnsized, DispatchFromDyn}; use core::pin::Pin; use core::ptr::{self, NonNull}; use core::slice::{self, from_raw_parts_mut}; -use core::convert::From; +use core::convert::{From, TryFrom}; use core::usize; use crate::alloc::{Global, Alloc, Layout, box_free, handle_alloc_error}; @@ -1257,6 +1258,22 @@ impl From> for Rc<[T]> { } } +#[unstable(feature = "boxed_slice_try_from", issue = "0")] +impl TryFrom> for Rc<[T; N]> +where + [T; N]: LengthAtMost32, +{ + type Error = Rc<[T]>; + + fn try_from(boxed_slice: Rc<[T]>) -> Result { + if boxed_slice.len() == N { + Ok(unsafe { Rc::from_raw(Rc::into_raw(boxed_slice) as *mut [T; N]) }) + } else { + Err(boxed_slice) + } + } +} + #[stable(feature = "shared_from_iter", since = "1.37.0")] impl iter::FromIterator for Rc<[T]> { /// Takes each element in the `Iterator` and collects it into an `Rc<[T]>`. diff --git a/src/liballoc/rc/tests.rs b/src/liballoc/rc/tests.rs index 72816a5c120c8..6fd3f90935714 100644 --- a/src/liballoc/rc/tests.rs +++ b/src/liballoc/rc/tests.rs @@ -6,7 +6,7 @@ use std::option::Option::{self, None, Some}; use std::result::Result::{Err, Ok}; use std::mem::drop; use std::clone::Clone; -use std::convert::From; +use std::convert::{From, TryInto}; #[test] fn test_clone() { @@ -425,3 +425,15 @@ fn test_downcast() { assert!(r2str.is_ok()); assert_eq!(r2str.unwrap(), Rc::new("abc")); } + +#[test] +fn test_array_from_slice() { + let v = vec![1, 2, 3]; + let r: Rc<[u32]> = Rc::from(v); + + let a: Result, _> = r.clone().try_into(); + assert!(a.is_ok()); + + let a: Result, _> = r.clone().try_into(); + assert!(a.is_err()); +} diff --git a/src/liballoc/sync.rs b/src/liballoc/sync.rs index e11873218e8a4..7d3b2656a7b90 100644 --- a/src/liballoc/sync.rs +++ b/src/liballoc/sync.rs @@ -7,6 +7,7 @@ //! [arc]: struct.Arc.html use core::any::Any; +use core::array::LengthAtMost32; use core::sync::atomic; use core::sync::atomic::Ordering::{Acquire, Relaxed, Release, SeqCst}; use core::borrow; @@ -21,7 +22,7 @@ use core::ptr::{self, NonNull}; use core::marker::{Unpin, Unsize, PhantomData}; use core::hash::{Hash, Hasher}; use core::{isize, usize}; -use core::convert::From; +use core::convert::{From, TryFrom}; use core::slice::{self, from_raw_parts_mut}; use crate::alloc::{Global, Alloc, Layout, box_free, handle_alloc_error}; @@ -1826,6 +1827,22 @@ impl From> for Arc<[T]> { } } +#[unstable(feature = "boxed_slice_try_from", issue = "0")] +impl TryFrom> for Arc<[T; N]> +where + [T; N]: LengthAtMost32, +{ + type Error = Arc<[T]>; + + fn try_from(boxed_slice: Arc<[T]>) -> Result { + if boxed_slice.len() == N { + Ok(unsafe { Arc::from_raw(Arc::into_raw(boxed_slice) as *mut [T; N]) }) + } else { + Err(boxed_slice) + } + } +} + #[stable(feature = "shared_from_iter", since = "1.37.0")] impl iter::FromIterator for Arc<[T]> { /// Takes each element in the `Iterator` and collects it into an `Arc<[T]>`. diff --git a/src/liballoc/sync/tests.rs b/src/liballoc/sync/tests.rs index 2e0c62f50c167..9220f5e0333ef 100644 --- a/src/liballoc/sync/tests.rs +++ b/src/liballoc/sync/tests.rs @@ -9,7 +9,7 @@ use std::option::Option::{self, None, Some}; use std::sync::atomic::{self, Ordering::{Acquire, SeqCst}}; use std::thread; use std::sync::Mutex; -use std::convert::From; +use std::convert::{From, TryInto}; use crate::vec::Vec; @@ -478,3 +478,15 @@ fn test_downcast() { assert!(r2str.is_ok()); assert_eq!(r2str.unwrap(), Arc::new("abc")); } + +#[test] +fn test_array_from_slice() { + let v = vec![1, 2, 3]; + let r: Arc<[u32]> = Arc::from(v); + + let a: Result, _> = r.clone().try_into(); + assert!(a.is_ok()); + + let a: Result, _> = r.clone().try_into(); + assert!(a.is_err()); +} diff --git a/src/liballoc/tests.rs b/src/liballoc/tests.rs index 654eabd070326..ed46ba8a1b938 100644 --- a/src/liballoc/tests.rs +++ b/src/liballoc/tests.rs @@ -1,6 +1,7 @@ //! Test for `boxed` mod. use core::any::Any; +use core::convert::TryInto; use core::ops::Deref; use core::result::Result::{Err, Ok}; use core::clone::Clone; @@ -138,3 +139,15 @@ fn boxed_slice_from_iter() { assert_eq!(boxed.len(), 100); assert_eq!(boxed[7], 7); } + +#[test] +fn test_array_from_slice() { + let v = vec![1, 2, 3]; + let r: Box<[u32]> = v.into_boxed_slice(); + + let a: Result, _> = r.clone().try_into(); + assert!(a.is_ok()); + + let a: Result, _> = r.clone().try_into(); + assert!(a.is_err()); +} diff --git a/src/test/ui/const-generics/array-impls/alloc-types-no-impls-length-33.rs b/src/test/ui/const-generics/array-impls/alloc-types-no-impls-length-33.rs new file mode 100644 index 0000000000000..3a23b9b5832c0 --- /dev/null +++ b/src/test/ui/const-generics/array-impls/alloc-types-no-impls-length-33.rs @@ -0,0 +1,26 @@ +// ignore-tidy-linelength + +use std::{convert::TryFrom, rc::Rc, sync::Arc}; + +pub fn no_box() { + let boxed_slice = Box::new([0; 33]) as Box<[i32]>; + let boxed_array = >::try_from(boxed_slice); + //~^ ERROR the trait bound `std::boxed::Box<[i32; 33]>: std::convert::From>` is not satisfied + //~^^ ERROR the trait bound `std::boxed::Box<[i32; 33]>: std::convert::TryFrom>` is not satisfied +} + +pub fn no_rc() { + let boxed_slice = Rc::new([0; 33]) as Rc<[i32]>; + let boxed_array = >::try_from(boxed_slice); + //~^ ERROR the trait bound `std::rc::Rc<[i32; 33]>: std::convert::From>` is not satisfied + //~^^ ERROR the trait bound `std::rc::Rc<[i32; 33]>: std::convert::TryFrom>` is not satisfied +} + +pub fn no_arc() { + let boxed_slice = Arc::new([0; 33]) as Arc<[i32]>; + let boxed_array = >::try_from(boxed_slice); + //~^ ERROR the trait bound `std::sync::Arc<[i32; 33]>: std::convert::From>` is not satisfied + //~^^ ERROR the trait bound `std::sync::Arc<[i32; 33]>: std::convert::TryFrom>` is not satisfied +} + +fn main() {} diff --git a/src/test/ui/const-generics/array-impls/alloc-types-no-impls-length-33.stderr b/src/test/ui/const-generics/array-impls/alloc-types-no-impls-length-33.stderr new file mode 100644 index 0000000000000..193fb4c4374a4 --- /dev/null +++ b/src/test/ui/const-generics/array-impls/alloc-types-no-impls-length-33.stderr @@ -0,0 +1,75 @@ +error[E0277]: the trait bound `std::boxed::Box<[i32; 33]>: std::convert::From>` is not satisfied + --> $DIR/alloc-types-no-impls-length-33.rs:7:23 + | +LL | let boxed_array = >::try_from(boxed_slice); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::convert::From>` is not implemented for `std::boxed::Box<[i32; 33]>` + | + = help: the following implementations were found: + as std::convert::From> + as std::convert::From<&str>> + as std::convert::From>> + as std::convert::From> + and 16 others + = note: required because of the requirements on the impl of `std::convert::Into>` for `std::boxed::Box<[i32]>` + = note: required because of the requirements on the impl of `std::convert::TryFrom>` for `std::boxed::Box<[i32; 33]>` + +error[E0277]: the trait bound `std::boxed::Box<[i32; 33]>: std::convert::TryFrom>` is not satisfied + --> $DIR/alloc-types-no-impls-length-33.rs:7:23 + | +LL | let boxed_array = >::try_from(boxed_slice); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::convert::TryFrom>` is not implemented for `std::boxed::Box<[i32; 33]>` + | + = help: the following implementations were found: + as std::convert::TryFrom>> + +error[E0277]: the trait bound `std::rc::Rc<[i32; 33]>: std::convert::From>` is not satisfied + --> $DIR/alloc-types-no-impls-length-33.rs:14:23 + | +LL | let boxed_array = >::try_from(boxed_slice); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::convert::From>` is not implemented for `std::rc::Rc<[i32; 33]>` + | + = help: the following implementations were found: + as std::convert::From> + as std::convert::From>> + as std::convert::From<&[T]>> + as std::convert::From>> + and 8 others + = note: required because of the requirements on the impl of `std::convert::Into>` for `std::rc::Rc<[i32]>` + = note: required because of the requirements on the impl of `std::convert::TryFrom>` for `std::rc::Rc<[i32; 33]>` + +error[E0277]: the trait bound `std::rc::Rc<[i32; 33]>: std::convert::TryFrom>` is not satisfied + --> $DIR/alloc-types-no-impls-length-33.rs:14:23 + | +LL | let boxed_array = >::try_from(boxed_slice); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::convert::TryFrom>` is not implemented for `std::rc::Rc<[i32; 33]>` + | + = help: the following implementations were found: + as std::convert::TryFrom>> + +error[E0277]: the trait bound `std::sync::Arc<[i32; 33]>: std::convert::From>` is not satisfied + --> $DIR/alloc-types-no-impls-length-33.rs:21:23 + | +LL | let boxed_array = >::try_from(boxed_slice); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::convert::From>` is not implemented for `std::sync::Arc<[i32; 33]>` + | + = help: the following implementations were found: + as std::convert::From> + as std::convert::From>> + as std::convert::From<&[T]>> + as std::convert::From>> + and 8 others + = note: required because of the requirements on the impl of `std::convert::Into>` for `std::sync::Arc<[i32]>` + = note: required because of the requirements on the impl of `std::convert::TryFrom>` for `std::sync::Arc<[i32; 33]>` + +error[E0277]: the trait bound `std::sync::Arc<[i32; 33]>: std::convert::TryFrom>` is not satisfied + --> $DIR/alloc-types-no-impls-length-33.rs:21:23 + | +LL | let boxed_array = >::try_from(boxed_slice); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::convert::TryFrom>` is not implemented for `std::sync::Arc<[i32; 33]>` + | + = help: the following implementations were found: + as std::convert::TryFrom>> + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0277`.