Skip to content

Commit c353180

Browse files
committed
RFC: Extend and stabilize the FixedSizeArray trait
1 parent b23226f commit c353180

File tree

1 file changed

+146
-0
lines changed

1 file changed

+146
-0
lines changed

text/0000-array-trait.md

Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
- Feature Name: array-trait
2+
- Start Date: 2017-02-21
3+
- RFC PR:
4+
- Rust Issue:
5+
6+
# Summary
7+
[summary]: #summary
8+
9+
Extend and stabilize the `FixedSizeArray` trait,
10+
as a stop-gap solution for integer parameters in generics.
11+
12+
13+
# Motivation
14+
[motivation]: #motivation
15+
16+
One of Rust’s basic families of types is fixed-size arrays:
17+
`[T; N]` where `T` is any (statically-sized) type, and `N` is an (`usize`) integer.
18+
Arrays with the same `T` item type but of different sizes are themselves different types.
19+
20+
A [long-standing](https://github.com/rust-lang/rfcs/pull/884)
21+
feature [request](https://github.com/rust-lang/rfcs/issues/1038)
22+
it the ability to write code that is generic over the size of an array.
23+
The solution typically proposed for this it “type-level integers”,
24+
where generic items can have integers as a new *kind* of type-level parameters,
25+
in addition to lifetime parameters and type parameters.
26+
27+
However, every RFC on the subject so far has been postponed:
28+
[1](https://github.com/rust-lang/rfcs/pull/884),
29+
[2](https://github.com/rust-lang/rfcs/pull/1062),
30+
[3](https://github.com/rust-lang/rfcs/pull/1520),
31+
[4](https://github.com/rust-lang/rfcs/issues/1557),
32+
[5](https://github.com/rust-lang/rfcs/pull/1657).
33+
34+
This RFC propose an addition to the language that,
35+
although less theoretically pleasing,
36+
is much smaller and therefore hopefully more likely to be accepted.
37+
Additionally, it does not prevent a more general solution from also happening in the future.
38+
39+
Arrays are the only case where integers occur in types, in current Rust.
40+
Therefore a solution specifically for arrays
41+
hopefully covers many of the use cases for type-level integers.
42+
43+
44+
# Detailed design
45+
[design]: #detailed-design
46+
47+
The `core::array` module currently contains a `FixedSizeArray` trait.
48+
Both are unstable.
49+
This RFC proposes three changes:
50+
51+
* Extend the `FixedSizeArray`. (This is optional, see alternatives.)
52+
* Reexport the module as `std::array`.
53+
* Stabilize both the module an the trait.
54+
55+
The current definition of the trait is:
56+
57+
```rust
58+
pub unsafe trait FixedSizeArray<T> {
59+
/// Converts the array to immutable slice
60+
fn as_slice(&self) -> &[T];
61+
/// Converts the array to mutable slice
62+
fn as_mut_slice(&mut self) -> &mut [T];
63+
}
64+
65+
unsafe impl<T, A: Unsize<[T]>> FixedSizeArray<T> for A {
66+
#[inline]
67+
fn as_slice(&self) -> &[T] {
68+
self
69+
}
70+
#[inline]
71+
fn as_mut_slice(&mut self) -> &mut [T] {
72+
self
73+
}
74+
}
75+
```
76+
77+
A single `impl` applies to array of all sizes, thanks to the `Unsize` trait.
78+
That trait is also unstable.
79+
It exists to support for [DST coercions](https://github.com/rust-lang/rust/issues/27732),
80+
itself a somewhat complex feature that might take some time to stabilize.
81+
82+
This trait is already useful as-is,
83+
but it would be nice to extend it to include the array’s length and item type
84+
as an associated constant
85+
and an associated type (which replaces the type parameter):
86+
87+
```rust
88+
pub unsafe trait FixedSizeArray {
89+
// Added:
90+
type Item;
91+
const LENGTH: usize;
92+
93+
// Unchanged:
94+
fn as_slice(&self) -> &[Self::Item];
95+
fn as_mut_slice(&mut self) -> &mut [Self::Item];
96+
}
97+
```
98+
99+
However these can not be provided by in `impl` based on `Unsize<[T]>` like the current one.
100+
Instead, this RFC proposes that all array types implement the trait through “compiler magic”.
101+
There would be no corresponding `impl` block in libcore or other library crates,
102+
the existence of these implementations would be part of the definition of the Rust language.
103+
There is precedent for such “magic” implementations in the language of other traits:
104+
105+
* `Unsize`
106+
* `Sized`
107+
* `Fn`, `FnMut`, `FnMove` (for closures types, which are very magical themselves)
108+
* `Copy`, `Drop` (not implemented implicitly, but `impl`s have “magical” requirements)
109+
110+
111+
# How We Teach This
112+
[how-we-teach-this]: #how-we-teach-this
113+
114+
The `array` module and `FixedSizeArray` trait already have rustdoc documentation
115+
that seems appropriate.
116+
117+
The trait could be mentioned in the *Primitive Types* or *Generics* chapter of the book.
118+
119+
120+
# Drawbacks
121+
[drawbacks]: #drawbacks
122+
123+
This an ad-hoc work-around for something that could be solved with a more general mechanism
124+
in the future.
125+
126+
127+
# Alternatives
128+
[alternatives]: #alternatives
129+
130+
* Stabilize the `FixedSizeArray` trait as-is
131+
(without an associated type or associated constant, with a type parameter).
132+
133+
* Figure out type-level integers, and deprecate / remove the `FixedSizeArray` trait.
134+
135+
136+
# Unresolved questions
137+
[unresolved]: #unresolved-questions
138+
139+
* To extend or not to extend. (See [Alternatives](#alternatives).)
140+
141+
* Should the compiler prevent other implementations of the trait?
142+
There is precedent for that with the `Unsize` trait and error number E0328.
143+
144+
* Rename `FixedSizeArray` to `Array`?
145+
All arrays in Rust are fixed-size.
146+
The things similar to arrays that are not fixed-size are called slices or vectors.

0 commit comments

Comments
 (0)