Skip to content

Commit 6a91782

Browse files
committed
Auto merge of #61515 - shepmaster:boxed-slice-to-array, r=cramertj
Add implementations for converting boxed slices into boxed arrays This mirrors the implementations of reference slices into arrays. # Discussion - [x] Should we use const generics? ([probably not](#61515 (comment))) - [ ] [What's the safety rationale here](#61515 (comment))? - [ ] [Should the errors return the original object](#61515 (comment))? # Remaining - [ ] Implement `Error` - [ ] Create a tracking issue
2 parents 188ab5c + 32324d2 commit 6a91782

File tree

9 files changed

+195
-6
lines changed

9 files changed

+195
-6
lines changed

src/liballoc/boxed.rs

+18-1
Original file line numberDiff line numberDiff line change
@@ -76,9 +76,10 @@
7676
#![stable(feature = "rust1", since = "1.0.0")]
7777

7878
use core::any::Any;
79+
use core::array::LengthAtMost32;
7980
use core::borrow;
8081
use core::cmp::Ordering;
81-
use core::convert::From;
82+
use core::convert::{From, TryFrom};
8283
use core::fmt;
8384
use core::future::Future;
8485
use core::hash::{Hash, Hasher};
@@ -612,6 +613,22 @@ impl From<Box<str>> for Box<[u8]> {
612613
}
613614
}
614615

616+
#[unstable(feature = "boxed_slice_try_from", issue = "0")]
617+
impl<T, const N: usize> TryFrom<Box<[T]>> for Box<[T; N]>
618+
where
619+
[T; N]: LengthAtMost32,
620+
{
621+
type Error = Box<[T]>;
622+
623+
fn try_from(boxed_slice: Box<[T]>) -> Result<Self, Self::Error> {
624+
if boxed_slice.len() == N {
625+
Ok(unsafe { Box::from_raw(Box::into_raw(boxed_slice) as *mut [T; N]) })
626+
} else {
627+
Err(boxed_slice)
628+
}
629+
}
630+
}
631+
615632
impl Box<dyn Any> {
616633
#[inline]
617634
#[stable(feature = "rust1", since = "1.0.0")]

src/liballoc/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -82,9 +82,9 @@
8282
#![feature(box_syntax)]
8383
#![feature(cfg_target_has_atomic)]
8484
#![feature(coerce_unsized)]
85-
#![cfg_attr(not(bootstrap), feature(const_in_array_repeat_expressions))]
8685
#![feature(const_generic_impls_guard)]
8786
#![feature(const_generics)]
87+
#![cfg_attr(not(bootstrap), feature(const_in_array_repeat_expressions))]
8888
#![feature(dispatch_from_dyn)]
8989
#![feature(core_intrinsics)]
9090
#![feature(dropck_eyepatch)]

src/liballoc/rc.rs

+18-1
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,7 @@ use crate::boxed::Box;
232232
use std::boxed::Box;
233233

234234
use core::any::Any;
235+
use core::array::LengthAtMost32;
235236
use core::borrow;
236237
use core::cell::Cell;
237238
use core::cmp::Ordering;
@@ -245,7 +246,7 @@ use core::ops::{Deref, Receiver, CoerceUnsized, DispatchFromDyn};
245246
use core::pin::Pin;
246247
use core::ptr::{self, NonNull};
247248
use core::slice::{self, from_raw_parts_mut};
248-
use core::convert::From;
249+
use core::convert::{From, TryFrom};
249250
use core::usize;
250251

251252
use crate::alloc::{Global, Alloc, Layout, box_free, handle_alloc_error};
@@ -1257,6 +1258,22 @@ impl<T> From<Vec<T>> for Rc<[T]> {
12571258
}
12581259
}
12591260

1261+
#[unstable(feature = "boxed_slice_try_from", issue = "0")]
1262+
impl<T, const N: usize> TryFrom<Rc<[T]>> for Rc<[T; N]>
1263+
where
1264+
[T; N]: LengthAtMost32,
1265+
{
1266+
type Error = Rc<[T]>;
1267+
1268+
fn try_from(boxed_slice: Rc<[T]>) -> Result<Self, Self::Error> {
1269+
if boxed_slice.len() == N {
1270+
Ok(unsafe { Rc::from_raw(Rc::into_raw(boxed_slice) as *mut [T; N]) })
1271+
} else {
1272+
Err(boxed_slice)
1273+
}
1274+
}
1275+
}
1276+
12601277
#[stable(feature = "shared_from_iter", since = "1.37.0")]
12611278
impl<T> iter::FromIterator<T> for Rc<[T]> {
12621279
/// Takes each element in the `Iterator` and collects it into an `Rc<[T]>`.

src/liballoc/rc/tests.rs

+13-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use std::option::Option::{self, None, Some};
66
use std::result::Result::{Err, Ok};
77
use std::mem::drop;
88
use std::clone::Clone;
9-
use std::convert::From;
9+
use std::convert::{From, TryInto};
1010

1111
#[test]
1212
fn test_clone() {
@@ -425,3 +425,15 @@ fn test_downcast() {
425425
assert!(r2str.is_ok());
426426
assert_eq!(r2str.unwrap(), Rc::new("abc"));
427427
}
428+
429+
#[test]
430+
fn test_array_from_slice() {
431+
let v = vec![1, 2, 3];
432+
let r: Rc<[u32]> = Rc::from(v);
433+
434+
let a: Result<Rc<[u32; 3]>, _> = r.clone().try_into();
435+
assert!(a.is_ok());
436+
437+
let a: Result<Rc<[u32; 2]>, _> = r.clone().try_into();
438+
assert!(a.is_err());
439+
}

src/liballoc/sync.rs

+18-1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
//! [arc]: struct.Arc.html
88
99
use core::any::Any;
10+
use core::array::LengthAtMost32;
1011
use core::sync::atomic;
1112
use core::sync::atomic::Ordering::{Acquire, Relaxed, Release, SeqCst};
1213
use core::borrow;
@@ -21,7 +22,7 @@ use core::ptr::{self, NonNull};
2122
use core::marker::{Unpin, Unsize, PhantomData};
2223
use core::hash::{Hash, Hasher};
2324
use core::{isize, usize};
24-
use core::convert::From;
25+
use core::convert::{From, TryFrom};
2526
use core::slice::{self, from_raw_parts_mut};
2627

2728
use crate::alloc::{Global, Alloc, Layout, box_free, handle_alloc_error};
@@ -1826,6 +1827,22 @@ impl<T> From<Vec<T>> for Arc<[T]> {
18261827
}
18271828
}
18281829

1830+
#[unstable(feature = "boxed_slice_try_from", issue = "0")]
1831+
impl<T, const N: usize> TryFrom<Arc<[T]>> for Arc<[T; N]>
1832+
where
1833+
[T; N]: LengthAtMost32,
1834+
{
1835+
type Error = Arc<[T]>;
1836+
1837+
fn try_from(boxed_slice: Arc<[T]>) -> Result<Self, Self::Error> {
1838+
if boxed_slice.len() == N {
1839+
Ok(unsafe { Arc::from_raw(Arc::into_raw(boxed_slice) as *mut [T; N]) })
1840+
} else {
1841+
Err(boxed_slice)
1842+
}
1843+
}
1844+
}
1845+
18291846
#[stable(feature = "shared_from_iter", since = "1.37.0")]
18301847
impl<T> iter::FromIterator<T> for Arc<[T]> {
18311848
/// Takes each element in the `Iterator` and collects it into an `Arc<[T]>`.

src/liballoc/sync/tests.rs

+13-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use std::option::Option::{self, None, Some};
99
use std::sync::atomic::{self, Ordering::{Acquire, SeqCst}};
1010
use std::thread;
1111
use std::sync::Mutex;
12-
use std::convert::From;
12+
use std::convert::{From, TryInto};
1313

1414
use crate::vec::Vec;
1515

@@ -478,3 +478,15 @@ fn test_downcast() {
478478
assert!(r2str.is_ok());
479479
assert_eq!(r2str.unwrap(), Arc::new("abc"));
480480
}
481+
482+
#[test]
483+
fn test_array_from_slice() {
484+
let v = vec![1, 2, 3];
485+
let r: Arc<[u32]> = Arc::from(v);
486+
487+
let a: Result<Arc<[u32; 3]>, _> = r.clone().try_into();
488+
assert!(a.is_ok());
489+
490+
let a: Result<Arc<[u32; 2]>, _> = r.clone().try_into();
491+
assert!(a.is_err());
492+
}

src/liballoc/tests.rs

+13
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
//! Test for `boxed` mod.
22
33
use core::any::Any;
4+
use core::convert::TryInto;
45
use core::ops::Deref;
56
use core::result::Result::{Err, Ok};
67
use core::clone::Clone;
@@ -138,3 +139,15 @@ fn boxed_slice_from_iter() {
138139
assert_eq!(boxed.len(), 100);
139140
assert_eq!(boxed[7], 7);
140141
}
142+
143+
#[test]
144+
fn test_array_from_slice() {
145+
let v = vec![1, 2, 3];
146+
let r: Box<[u32]> = v.into_boxed_slice();
147+
148+
let a: Result<Box<[u32; 3]>, _> = r.clone().try_into();
149+
assert!(a.is_ok());
150+
151+
let a: Result<Box<[u32; 2]>, _> = r.clone().try_into();
152+
assert!(a.is_err());
153+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// ignore-tidy-linelength
2+
3+
use std::{convert::TryFrom, rc::Rc, sync::Arc};
4+
5+
pub fn no_box() {
6+
let boxed_slice = Box::new([0; 33]) as Box<[i32]>;
7+
let boxed_array = <Box<[i32; 33]>>::try_from(boxed_slice);
8+
//~^ ERROR the trait bound `std::boxed::Box<[i32; 33]>: std::convert::From<std::boxed::Box<[i32]>>` is not satisfied
9+
//~^^ ERROR the trait bound `std::boxed::Box<[i32; 33]>: std::convert::TryFrom<std::boxed::Box<[i32]>>` is not satisfied
10+
}
11+
12+
pub fn no_rc() {
13+
let boxed_slice = Rc::new([0; 33]) as Rc<[i32]>;
14+
let boxed_array = <Rc<[i32; 33]>>::try_from(boxed_slice);
15+
//~^ ERROR the trait bound `std::rc::Rc<[i32; 33]>: std::convert::From<std::rc::Rc<[i32]>>` is not satisfied
16+
//~^^ ERROR the trait bound `std::rc::Rc<[i32; 33]>: std::convert::TryFrom<std::rc::Rc<[i32]>>` is not satisfied
17+
}
18+
19+
pub fn no_arc() {
20+
let boxed_slice = Arc::new([0; 33]) as Arc<[i32]>;
21+
let boxed_array = <Arc<[i32; 33]>>::try_from(boxed_slice);
22+
//~^ ERROR the trait bound `std::sync::Arc<[i32; 33]>: std::convert::From<std::sync::Arc<[i32]>>` is not satisfied
23+
//~^^ ERROR the trait bound `std::sync::Arc<[i32; 33]>: std::convert::TryFrom<std::sync::Arc<[i32]>>` is not satisfied
24+
}
25+
26+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
error[E0277]: the trait bound `std::boxed::Box<[i32; 33]>: std::convert::From<std::boxed::Box<[i32]>>` is not satisfied
2+
--> $DIR/alloc-types-no-impls-length-33.rs:7:23
3+
|
4+
LL | let boxed_array = <Box<[i32; 33]>>::try_from(boxed_slice);
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::convert::From<std::boxed::Box<[i32]>>` is not implemented for `std::boxed::Box<[i32; 33]>`
6+
|
7+
= help: the following implementations were found:
8+
<std::boxed::Box<(dyn std::error::Error + 'a)> as std::convert::From<E>>
9+
<std::boxed::Box<(dyn std::error::Error + 'static)> as std::convert::From<&str>>
10+
<std::boxed::Box<(dyn std::error::Error + 'static)> as std::convert::From<std::borrow::Cow<'a, str>>>
11+
<std::boxed::Box<(dyn std::error::Error + 'static)> as std::convert::From<std::string::String>>
12+
and 16 others
13+
= note: required because of the requirements on the impl of `std::convert::Into<std::boxed::Box<[i32; 33]>>` for `std::boxed::Box<[i32]>`
14+
= note: required because of the requirements on the impl of `std::convert::TryFrom<std::boxed::Box<[i32]>>` for `std::boxed::Box<[i32; 33]>`
15+
16+
error[E0277]: the trait bound `std::boxed::Box<[i32; 33]>: std::convert::TryFrom<std::boxed::Box<[i32]>>` is not satisfied
17+
--> $DIR/alloc-types-no-impls-length-33.rs:7:23
18+
|
19+
LL | let boxed_array = <Box<[i32; 33]>>::try_from(boxed_slice);
20+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::convert::TryFrom<std::boxed::Box<[i32]>>` is not implemented for `std::boxed::Box<[i32; 33]>`
21+
|
22+
= help: the following implementations were found:
23+
<std::boxed::Box<[T; _]> as std::convert::TryFrom<std::boxed::Box<[T]>>>
24+
25+
error[E0277]: the trait bound `std::rc::Rc<[i32; 33]>: std::convert::From<std::rc::Rc<[i32]>>` is not satisfied
26+
--> $DIR/alloc-types-no-impls-length-33.rs:14:23
27+
|
28+
LL | let boxed_array = <Rc<[i32; 33]>>::try_from(boxed_slice);
29+
| ^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::convert::From<std::rc::Rc<[i32]>>` is not implemented for `std::rc::Rc<[i32; 33]>`
30+
|
31+
= help: the following implementations were found:
32+
<std::rc::Rc<T> as std::convert::From<T>>
33+
<std::rc::Rc<T> as std::convert::From<std::boxed::Box<T>>>
34+
<std::rc::Rc<[T]> as std::convert::From<&[T]>>
35+
<std::rc::Rc<[T]> as std::convert::From<std::vec::Vec<T>>>
36+
and 8 others
37+
= note: required because of the requirements on the impl of `std::convert::Into<std::rc::Rc<[i32; 33]>>` for `std::rc::Rc<[i32]>`
38+
= note: required because of the requirements on the impl of `std::convert::TryFrom<std::rc::Rc<[i32]>>` for `std::rc::Rc<[i32; 33]>`
39+
40+
error[E0277]: the trait bound `std::rc::Rc<[i32; 33]>: std::convert::TryFrom<std::rc::Rc<[i32]>>` is not satisfied
41+
--> $DIR/alloc-types-no-impls-length-33.rs:14:23
42+
|
43+
LL | let boxed_array = <Rc<[i32; 33]>>::try_from(boxed_slice);
44+
| ^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::convert::TryFrom<std::rc::Rc<[i32]>>` is not implemented for `std::rc::Rc<[i32; 33]>`
45+
|
46+
= help: the following implementations were found:
47+
<std::rc::Rc<[T; _]> as std::convert::TryFrom<std::rc::Rc<[T]>>>
48+
49+
error[E0277]: the trait bound `std::sync::Arc<[i32; 33]>: std::convert::From<std::sync::Arc<[i32]>>` is not satisfied
50+
--> $DIR/alloc-types-no-impls-length-33.rs:21:23
51+
|
52+
LL | let boxed_array = <Arc<[i32; 33]>>::try_from(boxed_slice);
53+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::convert::From<std::sync::Arc<[i32]>>` is not implemented for `std::sync::Arc<[i32; 33]>`
54+
|
55+
= help: the following implementations were found:
56+
<std::sync::Arc<T> as std::convert::From<T>>
57+
<std::sync::Arc<T> as std::convert::From<std::boxed::Box<T>>>
58+
<std::sync::Arc<[T]> as std::convert::From<&[T]>>
59+
<std::sync::Arc<[T]> as std::convert::From<std::vec::Vec<T>>>
60+
and 8 others
61+
= note: required because of the requirements on the impl of `std::convert::Into<std::sync::Arc<[i32; 33]>>` for `std::sync::Arc<[i32]>`
62+
= note: required because of the requirements on the impl of `std::convert::TryFrom<std::sync::Arc<[i32]>>` for `std::sync::Arc<[i32; 33]>`
63+
64+
error[E0277]: the trait bound `std::sync::Arc<[i32; 33]>: std::convert::TryFrom<std::sync::Arc<[i32]>>` is not satisfied
65+
--> $DIR/alloc-types-no-impls-length-33.rs:21:23
66+
|
67+
LL | let boxed_array = <Arc<[i32; 33]>>::try_from(boxed_slice);
68+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::convert::TryFrom<std::sync::Arc<[i32]>>` is not implemented for `std::sync::Arc<[i32; 33]>`
69+
|
70+
= help: the following implementations were found:
71+
<std::sync::Arc<[T; _]> as std::convert::TryFrom<std::sync::Arc<[T]>>>
72+
73+
error: aborting due to 6 previous errors
74+
75+
For more information about this error, try `rustc --explain E0277`.

0 commit comments

Comments
 (0)