Skip to content

Commit 4b8696d

Browse files
authored
Merge pull request #14 from BoxyUwU/master
Copy over stories from vision doc hackmd
2 parents 74691c1 + b6d0aea commit 4b8696d

File tree

11 files changed

+414
-6
lines changed

11 files changed

+414
-6
lines changed

SUMMARY.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,12 @@
55
- [🔮 The vision](./vision.md)
66
- [🙋‍♀️ Cast of characters](./vision/characters.md)
77
- [😱 Status quo](./vision/status_quo.md)
8+
- [Array defaults](./vision/status_quo/array_default.md)
9+
- [Array split first method](./vision/status_quo/split_first.md)
810
- [✨ Shiny future](./vision/shiny_future.md)
11+
- [Array defaults](./vision/shiny_future/array_default.md)
12+
- [Array split first method](./vision/shiny_future/split_first.md)
13+
- [Image type in rust-gpu](./vision/shiny_future/image_type.md)
914
- [📅 Roadmap for 2021](./vision/roadmap.md)
1015
- [❓How to vision doc](./vision/how_to_vision_doc.md)- [Meetings](./meetings/README.md)
1116
- [✏️ Draft RFCs](./draft-rfcs/README.md)

vision.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,6 @@ This section lays out a general vision and set of goals for Const Generics in Ru
1010

1111
## This is a group effort
1212

13-
As the leads of the Async Foundation group, Niko and Tyler are driving and organizing this document. But writing it and shaping it is a group effort. If you think there is a part of the async experience that is not reflected here, we want to hear from you! Check out the [How to vision doc] for more details on how to contribute.
13+
As the leads of the Const Generics group, Niko and Lcnr are driving and organizing this document. But writing it and shaping it is a group effort. If you think there is a part of the const generics experience that is not reflected here, we want to hear from you! Check out the [How to vision doc] for more details on how to contribute.
1414

1515
[How to vision doc]: ./vision/how_to_vision_doc.md

vision/characters.md

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,39 @@
11
# 🙋‍♀️ Cast of characters
2+
3+
## What is this?
4+
5+
We've created four characters that we use to guide our thinking. These characters are the protagonists of our [status quo] and [shiny future] stories, and they help us to think about the different kinds of priorities and expectations that people bring when using Const Generics in rust. Having names and personalities also makes the stories more fun and approachable.
6+
7+
[status quo]: ./status_quo.md
8+
[shiny future]: ./shiny_future.md
9+
10+
## The characters
11+
12+
* Alan: the experienced "GC'd language" developer, new to Rust
13+
* *Top priority*: performance -- that's what he is not getting from current GC'd language
14+
* *Expectations*: absence of memory safety bugs (he gets that now from his GC), strong ecosystem, great tooling
15+
* Grace: the systems programming expert, new to Rust
16+
* *Top priority*: memory safety -- that's what she is not getting from C/C++
17+
* *Expectations*: able to do all the things she's used to from C/C++
18+
* Niklaus: new programmer from an unconventional background
19+
* *Top priority*: accessibility -- he's learning a lot of new things at once
20+
* *Expectations*: community -- the community enabled him to have early success, and he is excited to have it support him and him grow more
21+
* Barbara: the experienced Rust developer
22+
* *Top priority*: overall productivity and long-term maintenance -- she loves Rust, and wants to see it extended to new areas; she has an existing code base to maintain
23+
* *Expectations*: elegance and craftsmanship, fits well with Rust
24+
25+
## 🤔 Frequently Asked Questions
26+
27+
### Where do the names come from?
28+
Famous programming language designers and theorists. [Alan Turing], [Grace Hopper], [Niklaus Wirth], and [Barbara Liskov].
29+
30+
### I don't see myself in these characters. What should I do?
31+
Come to Zulip (#project-const-generics) and talk to us about it! Maybe they need to be adjusted!
32+
33+
### I see myself in more than one of these characters!
34+
Yeah, me too.
35+
36+
[Alan Turing]: https://en.wikipedia.org/wiki/Alan_Turing
37+
[Grace Hopper]: https://en.wikipedia.org/wiki/Grace_Hopper
38+
[Niklaus Wirth]: https://en.wikipedia.org/wiki/Niklaus_Wirth
39+
[Barbara Liskov]: https://en.wikipedia.org/wiki/Barbara_Liskov

vision/how_to_vision_doc.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ This page describes the process for contributing to the vision doc.
99

1010
## Who owns this document?
1111

12-
This document is owned and maintained by the leads of the Const Generics Working Group.
12+
This document is owned and maintained by the leads of the project-const-generics group.
1313
They decide what content to accept or reject.
1414
This decision is made in consultation with the Rust teams that will be making the ultimate decisions.
1515
For example, if a design doc or part of the shiny future is describing a new language feature, the leads ought to discuss that with the language design team, since that team will ultimately have to approve the RFCs for its design.

vision/roadmap.md

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,3 @@ It is updated on a monthly basis.
1717

1818
| Plan | Owner | Status | Last updated
1919
| --- | --- | --- | --- |
20-
| [Async functions in traits] | nikomatsakis | 🥬 | 2021-02 |
21-
22-
[Async functions in traits]: ../design_docs/async_fns_in_traits.md

vision/shiny_future/array_default.md

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
# ✨ Shiny future story: Barbara implements `Default` for all array lengths
2+
3+
Shiny future of [status quo story](../status_quo/array_default.md)
4+
5+
Barbara is working on `std`. She saw that the newest version of rustc has had some improvements to const generics
6+
and decides to try implementing `Default` for all array lengths. She goes to write:
7+
8+
```rust
9+
impl<T, const N: usize> Default for [T; N]
10+
where
11+
T: Default,
12+
{
13+
fn default() -> Self {
14+
/* snip */
15+
}
16+
}
17+
```
18+
19+
The code builds just fine but then she sees a test failing:
20+
```rust
21+
fn generic<T>() -> [T; 0] {
22+
Default::default()
23+
}
24+
```
25+
26+
"Ah," she says, "I see that Default is implemented for any type [T; 0], regardless of whether T: Default. That makes sense. Argh!"
27+
28+
Next she tries to write:
29+
```rust
30+
impl<T, const N: usize> Default for [T; N]
31+
where
32+
T: Default,
33+
{ N > 0 },
34+
{
35+
fn default() -> Self {
36+
/* snip */
37+
}
38+
}
39+
40+
impl<T> Default for [T; 0] {
41+
fn default() -> Self {
42+
[]
43+
}
44+
}
45+
```
46+
47+
This compiles just fine and the test is passing. She decides to submit a PR where her reviewer asks her to
48+
add a test to make sure that `[T; N]: Default` holds when `T: Default` as this didn't used to work
49+
50+
```rust
51+
fn exhaustive_default_impl<T: Default, const N: usize>() -> [T; N] {
52+
<[T; N] as Default>::default()
53+
}
54+
```
55+
56+
This test passes just fine, "yay const generics ✨" she says

vision/shiny_future/image_type.md

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
# ✨ Shiny future story: Image type in rust-gpu
2+
Barbara is working on rust-gpu. In that project, she has a struct `Image` that represents GPU images. There are a number of constant parameters allowing this type to be heavily customized in a number of ways. In some cases, helper methods are only available for images with particular formats. She writes the struct declaration:
3+
4+
```rust
5+
struct Image<
6+
SampledType: SampleType<FORMAT>,
7+
const DIM: Dimensionality,
8+
const DEPTH: ImageDepth,
9+
const ARRAYED: Arrayed,
10+
const MULTISAMPLED: Multisampled,
11+
const SAMPLED: Sampled,
12+
const FORMAT: ImageFormat,
13+
const ACCESS_QUALIFIER: Option<AccessQualifier>,
14+
>(PhantomData<SampledType>);
15+
```
16+
17+
Barbara gets a few compile errors about her types used as a const param not implementing `StructuralEq` so she derives that and moves on.
18+
She then wants to write some methods that only work for images in some specific formats:
19+
20+
```rust
21+
impl<
22+
SampledType: SampleType<FORMAT>,
23+
const DIM: Dimensionality,
24+
const DEPTH: ImageDepth,
25+
const ARRAYED: Arrayed,
26+
const MULTISAMPLED: Multisampled,
27+
const SAMPLED: Sampled,
28+
const FORMAT: ImageFormat,
29+
const ACCESS_QUALIFIER: Option<AccessQualifier>,
30+
> Image<SampledType, DIM, DEPTH, ARRAYED, MULTISAMPLED, SAMPLED, FORMAT, ACCESS_QUALIFIER> {
31+
pub fn example_method(/* snip */)
32+
where
33+
{ some_condition(DEPTH, MULTISAMPLED) }
34+
{ /* snip */ }
35+
}
36+
37+
const fn some_condition(a: ImageDepth, m: Multisampled) -> bool {
38+
match (a, m) {
39+
/* snip */
40+
}
41+
}
42+
```
43+
44+
This compiles just fine and Barbara moves on to more complicated things

vision/shiny_future/split_first.md

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
# ✨ Shiny future story: Array split first method
2+
3+
Shiny future of [status quo story](../status_quo/split_first.md)
4+
5+
Barbara is working on her project. She has the idea to write a `split_first` function that will allow her to split out the first item from a fixed-length array; naturally, the array must be non-empty. It looks something like this:
6+
7+
```rust
8+
// Note: this method has an implied where clause that `N - 1` evaluates without
9+
// erroring because `N - 1` is in the function signature
10+
fn split_first<T, const N: usize>(arr: [T; N]) -> (T; [T; N - 1]) {
11+
// ...
12+
let tail: [T; N - 1] = // ...
13+
(head, tail)
14+
}
15+
```
16+
17+
Next she wants to write a function that uses `split_first`:
18+
19+
```rust
20+
fn some_method<const N: usize>(arr: [u8; N]) {
21+
let (first, rest) = split_first(arr);
22+
for i in rest {
23+
// ...
24+
}
25+
}
26+
```
27+
28+
The compiler gives her a compile error:
29+
```
30+
error: the constant expression `N - 1` is not known to evaluate without underflowing
31+
2 | let (first, rest) = split_first(arr);
32+
| ^^^^^^^^^^^ `N - 1` not known to be evaluatable without underflowing
33+
note: required by this expression in `split_first`'s function signature
34+
5 | fn split_first<T, const N: usize>(arr: [T; N]) -> (T; [T; N - 1]) {
35+
| ^^^^^
36+
help: add a where clause to `some_method`
37+
| fn some_method<const N: usize>(arr: [u8; N]) where { N > 0; }
38+
```
39+
40+
Barbara hits the 'quick fix' button in her IDE and it inserts the where clause for her- she immediately
41+
gets a compile error at another spot because she was calling `some_method` with an empty array:
42+
43+
```
44+
error: the constant `0` is not greater than `0`
45+
22 | some_method([])
46+
info: `0` must be greater than `0` because of this where clause
47+
| fn some_method<const N: usize>(arr: [u8; N]) where { N > 0; }
48+
| ----------
49+
```
50+
51+
Barbara has no more compile errors, even the following code is compiling:
52+
```rust
53+
fn some_other_method<const N: usize>(arr: [u8; N]) where { N > 1; } {
54+
// ...
55+
let (first, rest) = split_first(arr);
56+
// ...
57+
}
58+
```

vision/status_quo.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
## What is this
44

5-
The "status quo" stores are here to state our "theory of the case". That is, they present (and prove) our hypotheses as to what the various challenges are for users of Async I/O in Rust. These hypotheses are presented in narrative form, by telling the story of a specific [character] as they try (and typically fail in dramatic fashion) to achieve their goals.
5+
The "status quo" stores are here to state our "theory of the case". That is, they present (and prove) our hypotheses as to what the various challenges are for users of Const Generics in Rust. These hypotheses are presented in narrative form, by telling the story of a specific [character] as they try (and typically fail in dramatic fashion) to achieve their goals.
66

77
[character]: ./characters.md
88

vision/status_quo/array_default.md

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
# 😱 Status quo story: Barbara wants to implement `Default` for all array lengths
2+
3+
Barbara is working on `std`. She wants to implement `Default` for all array types. Currently, it is implemented for `N <= 32` using a macro ([link](https://doc.rust-lang.org/nightly/src/core/array/mod.rs.html#391))
4+
5+
She thinks "Ah, I can use min-const-generics for this!" and goes to write
6+
7+
```rust
8+
impl<T, const N: usize> Default for [T; N]
9+
where
10+
T: Default,
11+
{
12+
fn default() -> Self {
13+
14+
}
15+
16+
}
17+
```
18+
19+
So far so good, but then she realizes she can't figure out what to write in the body. At first she tries:
20+
21+
```rust
22+
impl<T, const N: usize> Default for [T; N]
23+
where
24+
T: Default,
25+
{
26+
fn default() -> Self {
27+
[T::default(); N]
28+
}
29+
30+
}
31+
```
32+
33+
but this won't compile:
34+
35+
```
36+
error[E0277]: the trait bound `T: Copy` is not satisfied
37+
--> src/lib.rs:10:9
38+
|
39+
10 | [T::default(); N]
40+
| ^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `T`
41+
|
42+
= note: the `Copy` trait is required because the repeated element will be copied
43+
help: consider further restricting this bound
44+
|
45+
7 | T: MyDefault + Copy,
46+
| ^^^^^^
47+
```
48+
49+
"Ah," she realizes, "this would be cloning a single value of `T`, but I want to make `N` distinct values. How can I do that?"
50+
51+
She asks on Zulip and lcnr tells her that there is this [`map` function defined on arrays](https://doc.rust-lang.org/std/primitive.array.html#method.map). She could write:
52+
53+
54+
```rust
55+
impl<T, const N: usize> Default for [T; N]
56+
where
57+
T: Default,
58+
{
59+
fn default() -> Self {
60+
[(); N].map(|()| T::default())
61+
}
62+
}
63+
```
64+
65+
"That code will build," lcnr warns her, "but we're not going to be able to ship it. Test it and see." Barbara runs the tests and finds she is getting a failure. The following test no longer builds:
66+
67+
```rust
68+
fn generic<T>() -> [T; 0] {
69+
Default::default()
70+
}
71+
```
72+
73+
"Ah," she says, "I see that `Default` is implemented for any type `[T; 0]`, regardless of whether `T: Default`. That makes sense. Argh!"
74+
75+
Next she tries (this already relies on a nightly feature)
76+
```rust
77+
impl<T: Trait, const N: usize> Default for [T; N]
78+
where
79+
T: Default,
80+
N != 0, // nightly feature!
81+
{
82+
fn default() -> Self {
83+
[(); N].map(|()| T::default())
84+
}
85+
}
86+
87+
impl<T> Trait for [T; 0] {
88+
// ...
89+
}
90+
```
91+
92+
While this does seem to compile, when trying to use it, it causes an unexpected error.
93+
94+
```rust
95+
fn foo<T: Trait, const N: usize>() -> [u8; N] {
96+
<[T; N] as Trait>::ASSOC //~ ERROR `[T; N]` does not implement `Trait`
97+
}
98+
```
99+
100+
The compiler can't tell that `N == 0 || N != 0` is true for all possible `N`, so it can't infer `[T; N]: Trait` from `T: Trait`.
101+
102+
Frustrated, Barbara gives up and goes looking for another issue to fix.
103+
104+
Even worse, Barbara notices the same problem for `serde::Deserialize` and decides to
105+
abandon backwards compatibility in favor of a brighter future.

0 commit comments

Comments
 (0)