about summary refs log tree commit diff
diff options
context:
space:
mode:
authorJake Goulding <jake.goulding@gmail.com>2019-06-04 08:15:47 -0400
committerJake Goulding <jake.goulding@gmail.com>2019-08-05 10:26:53 -0400
commit32324d22c33dda31eadf49c5f27d6e6ff38a3ef1 (patch)
tree4ceca954cd7f02dfd8000317f3021fb8e4e3dd35
parent4be067558962c004b638e4c6f162d50f7c0c98b6 (diff)
downloadrust-32324d22c33dda31eadf49c5f27d6e6ff38a3ef1.tar.gz
rust-32324d22c33dda31eadf49c5f27d6e6ff38a3ef1.zip
Add implementations for converting boxed slices into boxed arrays
This mirrors the implementations of reference slices into arrays.
-rw-r--r--src/liballoc/boxed.rs19
-rw-r--r--src/liballoc/lib.rs2
-rw-r--r--src/liballoc/rc.rs19
-rw-r--r--src/liballoc/rc/tests.rs14
-rw-r--r--src/liballoc/sync.rs19
-rw-r--r--src/liballoc/sync/tests.rs14
-rw-r--r--src/liballoc/tests.rs13
-rw-r--r--src/test/ui/const-generics/array-impls/alloc-types-no-impls-length-33.rs26
-rw-r--r--src/test/ui/const-generics/array-impls/alloc-types-no-impls-length-33.stderr75
9 files changed, 195 insertions, 6 deletions
diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs
index 488fda0b247..c92db517cad 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<Box<str>> for Box<[u8]> {
     }
 }
 
+#[unstable(feature = "boxed_slice_try_from", issue = "0")]
+impl<T, const N: usize> TryFrom<Box<[T]>> for Box<[T; N]>
+where
+    [T; N]: LengthAtMost32,
+{
+    type Error = Box<[T]>;
+
+    fn try_from(boxed_slice: Box<[T]>) -> Result<Self, Self::Error> {
+        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<dyn Any> {
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs
index 98fa754759a..deea74daa52 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 e33aac3af47..0c406a92029 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<T> From<Vec<T>> for Rc<[T]> {
     }
 }
 
+#[unstable(feature = "boxed_slice_try_from", issue = "0")]
+impl<T, const N: usize> TryFrom<Rc<[T]>> for Rc<[T; N]>
+where
+    [T; N]: LengthAtMost32,
+{
+    type Error = Rc<[T]>;
+
+    fn try_from(boxed_slice: Rc<[T]>) -> Result<Self, Self::Error> {
+        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<T> iter::FromIterator<T> 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 72816a5c120..6fd3f909357 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<Rc<[u32; 3]>, _> = r.clone().try_into();
+    assert!(a.is_ok());
+
+    let a: Result<Rc<[u32; 2]>, _> = r.clone().try_into();
+    assert!(a.is_err());
+}
diff --git a/src/liballoc/sync.rs b/src/liballoc/sync.rs
index e11873218e8..7d3b2656a7b 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<T> From<Vec<T>> for Arc<[T]> {
     }
 }
 
+#[unstable(feature = "boxed_slice_try_from", issue = "0")]
+impl<T, const N: usize> TryFrom<Arc<[T]>> for Arc<[T; N]>
+where
+    [T; N]: LengthAtMost32,
+{
+    type Error = Arc<[T]>;
+
+    fn try_from(boxed_slice: Arc<[T]>) -> Result<Self, Self::Error> {
+        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<T> iter::FromIterator<T> 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 2e0c62f50c1..9220f5e0333 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<Arc<[u32; 3]>, _> = r.clone().try_into();
+    assert!(a.is_ok());
+
+    let a: Result<Arc<[u32; 2]>, _> = r.clone().try_into();
+    assert!(a.is_err());
+}
diff --git a/src/liballoc/tests.rs b/src/liballoc/tests.rs
index 654eabd0703..ed46ba8a1b9 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<Box<[u32; 3]>, _> = r.clone().try_into();
+    assert!(a.is_ok());
+
+    let a: Result<Box<[u32; 2]>, _> = 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 00000000000..3a23b9b5832
--- /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 = <Box<[i32; 33]>>::try_from(boxed_slice);
+    //~^ ERROR the trait bound `std::boxed::Box<[i32; 33]>: std::convert::From<std::boxed::Box<[i32]>>` is not satisfied
+    //~^^ ERROR the trait bound `std::boxed::Box<[i32; 33]>: std::convert::TryFrom<std::boxed::Box<[i32]>>` is not satisfied
+}
+
+pub fn no_rc() {
+    let boxed_slice = Rc::new([0; 33]) as Rc<[i32]>;
+    let boxed_array = <Rc<[i32; 33]>>::try_from(boxed_slice);
+    //~^ ERROR the trait bound `std::rc::Rc<[i32; 33]>: std::convert::From<std::rc::Rc<[i32]>>` is not satisfied
+    //~^^ ERROR the trait bound `std::rc::Rc<[i32; 33]>: std::convert::TryFrom<std::rc::Rc<[i32]>>` is not satisfied
+}
+
+pub fn no_arc() {
+    let boxed_slice = Arc::new([0; 33]) as Arc<[i32]>;
+    let boxed_array = <Arc<[i32; 33]>>::try_from(boxed_slice);
+    //~^ ERROR the trait bound `std::sync::Arc<[i32; 33]>: std::convert::From<std::sync::Arc<[i32]>>` is not satisfied
+    //~^^ ERROR the trait bound `std::sync::Arc<[i32; 33]>: std::convert::TryFrom<std::sync::Arc<[i32]>>` 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 00000000000..193fb4c4374
--- /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<std::boxed::Box<[i32]>>` is not satisfied
+  --> $DIR/alloc-types-no-impls-length-33.rs:7:23
+   |
+LL |     let boxed_array = <Box<[i32; 33]>>::try_from(boxed_slice);
+   |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::convert::From<std::boxed::Box<[i32]>>` is not implemented for `std::boxed::Box<[i32; 33]>`
+   |
+   = help: the following implementations were found:
+             <std::boxed::Box<(dyn std::error::Error + 'a)> as std::convert::From<E>>
+             <std::boxed::Box<(dyn std::error::Error + 'static)> as std::convert::From<&str>>
+             <std::boxed::Box<(dyn std::error::Error + 'static)> as std::convert::From<std::borrow::Cow<'a, str>>>
+             <std::boxed::Box<(dyn std::error::Error + 'static)> as std::convert::From<std::string::String>>
+           and 16 others
+   = note: required because of the requirements on the impl of `std::convert::Into<std::boxed::Box<[i32; 33]>>` for `std::boxed::Box<[i32]>`
+   = note: required because of the requirements on the impl of `std::convert::TryFrom<std::boxed::Box<[i32]>>` for `std::boxed::Box<[i32; 33]>`
+
+error[E0277]: the trait bound `std::boxed::Box<[i32; 33]>: std::convert::TryFrom<std::boxed::Box<[i32]>>` is not satisfied
+  --> $DIR/alloc-types-no-impls-length-33.rs:7:23
+   |
+LL |     let boxed_array = <Box<[i32; 33]>>::try_from(boxed_slice);
+   |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::convert::TryFrom<std::boxed::Box<[i32]>>` is not implemented for `std::boxed::Box<[i32; 33]>`
+   |
+   = help: the following implementations were found:
+             <std::boxed::Box<[T; _]> as std::convert::TryFrom<std::boxed::Box<[T]>>>
+
+error[E0277]: the trait bound `std::rc::Rc<[i32; 33]>: std::convert::From<std::rc::Rc<[i32]>>` is not satisfied
+  --> $DIR/alloc-types-no-impls-length-33.rs:14:23
+   |
+LL |     let boxed_array = <Rc<[i32; 33]>>::try_from(boxed_slice);
+   |                       ^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::convert::From<std::rc::Rc<[i32]>>` is not implemented for `std::rc::Rc<[i32; 33]>`
+   |
+   = help: the following implementations were found:
+             <std::rc::Rc<T> as std::convert::From<T>>
+             <std::rc::Rc<T> as std::convert::From<std::boxed::Box<T>>>
+             <std::rc::Rc<[T]> as std::convert::From<&[T]>>
+             <std::rc::Rc<[T]> as std::convert::From<std::vec::Vec<T>>>
+           and 8 others
+   = note: required because of the requirements on the impl of `std::convert::Into<std::rc::Rc<[i32; 33]>>` for `std::rc::Rc<[i32]>`
+   = note: required because of the requirements on the impl of `std::convert::TryFrom<std::rc::Rc<[i32]>>` for `std::rc::Rc<[i32; 33]>`
+
+error[E0277]: the trait bound `std::rc::Rc<[i32; 33]>: std::convert::TryFrom<std::rc::Rc<[i32]>>` is not satisfied
+  --> $DIR/alloc-types-no-impls-length-33.rs:14:23
+   |
+LL |     let boxed_array = <Rc<[i32; 33]>>::try_from(boxed_slice);
+   |                       ^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::convert::TryFrom<std::rc::Rc<[i32]>>` is not implemented for `std::rc::Rc<[i32; 33]>`
+   |
+   = help: the following implementations were found:
+             <std::rc::Rc<[T; _]> as std::convert::TryFrom<std::rc::Rc<[T]>>>
+
+error[E0277]: the trait bound `std::sync::Arc<[i32; 33]>: std::convert::From<std::sync::Arc<[i32]>>` is not satisfied
+  --> $DIR/alloc-types-no-impls-length-33.rs:21:23
+   |
+LL |     let boxed_array = <Arc<[i32; 33]>>::try_from(boxed_slice);
+   |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::convert::From<std::sync::Arc<[i32]>>` is not implemented for `std::sync::Arc<[i32; 33]>`
+   |
+   = help: the following implementations were found:
+             <std::sync::Arc<T> as std::convert::From<T>>
+             <std::sync::Arc<T> as std::convert::From<std::boxed::Box<T>>>
+             <std::sync::Arc<[T]> as std::convert::From<&[T]>>
+             <std::sync::Arc<[T]> as std::convert::From<std::vec::Vec<T>>>
+           and 8 others
+   = note: required because of the requirements on the impl of `std::convert::Into<std::sync::Arc<[i32; 33]>>` for `std::sync::Arc<[i32]>`
+   = note: required because of the requirements on the impl of `std::convert::TryFrom<std::sync::Arc<[i32]>>` for `std::sync::Arc<[i32; 33]>`
+
+error[E0277]: the trait bound `std::sync::Arc<[i32; 33]>: std::convert::TryFrom<std::sync::Arc<[i32]>>` is not satisfied
+  --> $DIR/alloc-types-no-impls-length-33.rs:21:23
+   |
+LL |     let boxed_array = <Arc<[i32; 33]>>::try_from(boxed_slice);
+   |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::convert::TryFrom<std::sync::Arc<[i32]>>` is not implemented for `std::sync::Arc<[i32; 33]>`
+   |
+   = help: the following implementations were found:
+             <std::sync::Arc<[T; _]> as std::convert::TryFrom<std::sync::Arc<[T]>>>
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0277`.