Skip to content

Commit cefc4a2

Browse files
authored
Rollup merge of rust-lang#97594 - WaffleLapkin:array_tuple_conv, r=ChrisDenton
Implement tuple<->array convertions via `From` This PR adds the following impls that convert between homogeneous tuples and arrays of the corresponding lengths: ```rust impl<T> From<[T; 1]> for (T,) { ... } impl<T> From<[T; 2]> for (T, T) { ... } /* ... */ impl<T> From<[T; 12]> for (T, T, T, T, T, T, T, T, T, T, T, T) { ... } impl<T> From<(T,)> for [T; 1] { ... } impl<T> From<(T, T)> for [T; 2] { ... } /* ... */ impl<T> From<(T, T, T, T, T, T, T, T, T, T, T, T)> for [T; 12] { ... } ``` IMO these are quite uncontroversial but note that they are, just like any other trait impls, insta-stable.
2 parents 9b99ff7 + de10516 commit cefc4a2

File tree

5 files changed

+78
-5
lines changed

5 files changed

+78
-5
lines changed

library/core/src/primitive_docs.rs

+20
Original file line numberDiff line numberDiff line change
@@ -610,6 +610,9 @@ mod prim_pointer {}
610610
/// if the element type allows it. As a stopgap, trait implementations are
611611
/// statically generated up to size 32.
612612
///
613+
/// Arrays of sizes from 1 to 12 (inclusive) implement [`From<Tuple>`], where `Tuple`
614+
/// is a homogenous [prim@tuple] of appropriate length.
615+
///
613616
/// Arrays coerce to [slices (`[T]`)][slice], so a slice method may be called on
614617
/// an array. Indeed, this provides most of the API for working with arrays.
615618
///
@@ -672,6 +675,13 @@ mod prim_pointer {}
672675
/// move_away(roa);
673676
/// ```
674677
///
678+
/// Arrays can be created from homogenous tuples of appropriate length:
679+
///
680+
/// ```
681+
/// let tuple: (u32, u32, u32) = (1, 2, 3);
682+
/// let array: [u32; 3] = tuple.into();
683+
/// ```
684+
///
675685
/// # Editions
676686
///
677687
/// Prior to Rust 1.53, arrays did not implement [`IntoIterator`] by value, so the method call
@@ -774,6 +784,7 @@ mod prim_pointer {}
774784
/// [`Borrow`]: borrow::Borrow
775785
/// [`BorrowMut`]: borrow::BorrowMut
776786
/// [slice pattern]: ../reference/patterns.html#slice-patterns
787+
/// [`From<Tuple>`]: convert::From
777788
#[stable(feature = "rust1", since = "1.0.0")]
778789
mod prim_array {}
779790

@@ -1000,7 +1011,9 @@ mod prim_str {}
10001011
/// * [`Debug`]
10011012
/// * [`Default`]
10021013
/// * [`Hash`]
1014+
/// * [`From<[T; N]>`][from]
10031015
///
1016+
/// [from]: convert::From
10041017
/// [`Debug`]: fmt::Debug
10051018
/// [`Hash`]: hash::Hash
10061019
///
@@ -1051,6 +1064,13 @@ mod prim_str {}
10511064
/// assert_eq!(y, 5);
10521065
/// ```
10531066
///
1067+
/// Homogenous tuples can be created from arrays of appropriate length:
1068+
///
1069+
/// ```
1070+
/// let array: [u32; 3] = [1, 2, 3];
1071+
/// let tuple: (u32, u32, u32) = array.into();
1072+
/// ```
1073+
///
10541074
#[stable(feature = "rust1", since = "1.0.0")]
10551075
mod prim_tuple {}
10561076

library/core/src/tuple.rs

+20
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,26 @@ macro_rules! tuple_impls {
100100
}
101101
}
102102
}
103+
104+
#[stable(feature = "array_tuple_conv", since = "1.63.0")]
105+
impl<T> From<[T; ${count(T)}]> for ($(${ignore(T)} T,)+) {
106+
#[inline]
107+
#[allow(non_snake_case)]
108+
fn from(array: [T; ${count(T)}]) -> Self {
109+
let [$($T,)+] = array;
110+
($($T,)+)
111+
}
112+
}
113+
114+
#[stable(feature = "array_tuple_conv", since = "1.63.0")]
115+
impl<T> From<($(${ignore(T)} T,)+)> for [T; ${count(T)}] {
116+
#[inline]
117+
#[allow(non_snake_case)]
118+
fn from(tuple: ($(${ignore(T)} T,)+)) -> Self {
119+
let ($($T,)+) = tuple;
120+
[$($T,)+]
121+
}
122+
}
103123
}
104124
}
105125

library/std/src/primitive_docs.rs

+20
Original file line numberDiff line numberDiff line change
@@ -610,6 +610,9 @@ mod prim_pointer {}
610610
/// if the element type allows it. As a stopgap, trait implementations are
611611
/// statically generated up to size 32.
612612
///
613+
/// Arrays of sizes from 1 to 12 (inclusive) implement [`From<Tuple>`], where `Tuple`
614+
/// is a homogenous [prim@tuple] of appropriate length.
615+
///
613616
/// Arrays coerce to [slices (`[T]`)][slice], so a slice method may be called on
614617
/// an array. Indeed, this provides most of the API for working with arrays.
615618
///
@@ -672,6 +675,13 @@ mod prim_pointer {}
672675
/// move_away(roa);
673676
/// ```
674677
///
678+
/// Arrays can be created from homogenous tuples of appropriate length:
679+
///
680+
/// ```
681+
/// let tuple: (u32, u32, u32) = (1, 2, 3);
682+
/// let array: [u32; 3] = tuple.into();
683+
/// ```
684+
///
675685
/// # Editions
676686
///
677687
/// Prior to Rust 1.53, arrays did not implement [`IntoIterator`] by value, so the method call
@@ -774,6 +784,7 @@ mod prim_pointer {}
774784
/// [`Borrow`]: borrow::Borrow
775785
/// [`BorrowMut`]: borrow::BorrowMut
776786
/// [slice pattern]: ../reference/patterns.html#slice-patterns
787+
/// [`From<Tuple>`]: convert::From
777788
#[stable(feature = "rust1", since = "1.0.0")]
778789
mod prim_array {}
779790

@@ -1000,7 +1011,9 @@ mod prim_str {}
10001011
/// * [`Debug`]
10011012
/// * [`Default`]
10021013
/// * [`Hash`]
1014+
/// * [`From<[T; N]>`][from]
10031015
///
1016+
/// [from]: convert::From
10041017
/// [`Debug`]: fmt::Debug
10051018
/// [`Hash`]: hash::Hash
10061019
///
@@ -1051,6 +1064,13 @@ mod prim_str {}
10511064
/// assert_eq!(y, 5);
10521065
/// ```
10531066
///
1067+
/// Homogenous tuples can be created from arrays of appropriate length:
1068+
///
1069+
/// ```
1070+
/// let array: [u32; 3] = [1, 2, 3];
1071+
/// let tuple: (u32, u32, u32) = array.into();
1072+
/// ```
1073+
///
10541074
#[stable(feature = "rust1", since = "1.0.0")]
10551075
mod prim_tuple {}
10561076

tests/ui/issues/issue-32709.stderr

+10-3
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,16 @@ LL | Err(5)?;
77
| ^ the trait `From<{integer}>` is not implemented for `()`
88
|
99
= note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait
10-
= help: the following other types implement trait `FromResidual<R>`:
11-
<Result<T, F> as FromResidual<Result<Infallible, E>>>
12-
<Result<T, F> as FromResidual<Yeet<E>>>
10+
= help: the following other types implement trait `From<T>`:
11+
<(T, T) as From<[T; 2]>>
12+
<(T, T, T) as From<[T; 3]>>
13+
<(T, T, T, T) as From<[T; 4]>>
14+
<(T, T, T, T, T) as From<[T; 5]>>
15+
<(T, T, T, T, T, T) as From<[T; 6]>>
16+
<(T, T, T, T, T, T, T) as From<[T; 7]>>
17+
<(T, T, T, T, T, T, T, T) as From<[T; 8]>>
18+
<(T, T, T, T, T, T, T, T, T) as From<[T; 9]>>
19+
and 4 others
1320
= note: required for `Result<i32, ()>` to implement `FromResidual<Result<Infallible, {integer}>>`
1421

1522
error: aborting due to previous error

tests/ui/suggestions/issue-71394-no-from-impl.stderr

+8-2
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,14 @@ LL | let _: &[i8] = data.into();
66
|
77
= help: the following other types implement trait `From<T>`:
88
<&'input [u8] as From<gimli::read::endian_slice::EndianSlice<'input, Endian>>>
9-
<[T; LANES] as From<Simd<T, LANES>>>
10-
<[bool; LANES] as From<Mask<T, LANES>>>
9+
<[T; 10] as From<(T, T, T, T, T, T, T, T, T, T)>>
10+
<[T; 11] as From<(T, T, T, T, T, T, T, T, T, T, T)>>
11+
<[T; 12] as From<(T, T, T, T, T, T, T, T, T, T, T, T)>>
12+
<[T; 1] as From<(T,)>>
13+
<[T; 2] as From<(T, T)>>
14+
<[T; 3] as From<(T, T, T)>>
15+
<[T; 4] as From<(T, T, T, T)>>
16+
and 7 others
1117
= note: required for `&[u8]` to implement `Into<&[i8]>`
1218

1319
error: aborting due to previous error

0 commit comments

Comments
 (0)