Skip to content

Commit 6b3726e

Browse files
committed
iter -> gen
1 parent 1cbbe3c commit 6b3726e

File tree

1 file changed

+34
-24
lines changed

1 file changed

+34
-24
lines changed

text/0000-iter-fn.md renamed to text/0000-gen-fn.md

Lines changed: 34 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
1-
- Feature Name: `iter-fn`
1+
- Feature Name: `gen-fn`
22
- Start Date: 2023-10-10
33
- RFC PR: [rust-lang/rfcs#0000](https://github.com/rust-lang/rfcs/pull/0000)
44
- Rust Issue: [rust-lang/rust#0000](https://github.com/rust-lang/rust/issues/0000)
55

66
# Summary
77
[summary]: #summary
88

9-
Add `iter {}` blocks to the language. These blocks implement `Iterator` and
9+
Add `gen {}` blocks to the language. These blocks implement `Iterator` and
1010
enable writing iterators in regular code by `yield`ing elements instead of having
1111
to implement `Iterator` for a custom struct and manually writing an `Iterator::next`
1212
method body. This is a change similar to adding `async {}` blocks that implement
1313
`Future` instead of having to manually write futures and their state machines.
1414

15-
Furthermore, add `iter fn` to the language. `iter fn foo(arg: X) -> Y` desugars to
15+
Furthermore, add `gen fn` to the language. `gen fn foo(arg: X) -> Y` desugars to
1616
`fn foo(arg: X) -> impl Iterator<Item = Y>`.
1717

1818
# Motivation
@@ -49,9 +49,9 @@ fn odd_dup(values: impl Iterator<Item = u32>) -> impl Iterator<Item = u32> {
4949
}
5050
Foo(values)
5151
}
52-
// `iter block`
52+
// `gen block`
5353
fn odd_dup(values: impl Iterator<Item = u32>) -> impl Iterator<Item = u32> {
54-
iter {
54+
gen {
5555
for value in values {
5656
if value.is_odd() {
5757
yield value * 2;
@@ -60,8 +60,8 @@ fn odd_dup(values: impl Iterator<Item = u32>) -> impl Iterator<Item = u32> {
6060
}
6161
}
6262

63-
// `iter fn`
64-
iter fn odd_dup(values: impl Iterator<Item = u32>) -> u32 {
63+
// `gen fn`
64+
gen fn odd_dup(values: impl Iterator<Item = u32>) -> u32 {
6565
for value in values {
6666
if value.is_odd() {
6767
yield value * 2;
@@ -82,34 +82,38 @@ iter fn odd_dup(values: impl Iterator<Item = u32>) -> u32 {
8282

8383
For implementation-oriented RFCs (e.g. for compiler internals), this section should focus on how compiler contributors should think about the change, and give examples of its concrete impact. For policy RFCs, this section should provide an example-driven introduction to the policy, and explain its impact in concrete terms.
8484

85+
## New keyword
86+
87+
Starting in the 2024 edition, `gen` is a keyword that cannot be used for naming any items or bindings. This means during the migration to the 2024 edition, all variables, functions, modules, types, ... named `gen` must be renamed.
88+
8589
## Returning/finishing an iterator
8690

87-
`iter` blocks' trailing expression must be of unit type or the block must diverge before reaching its end.
91+
`gen` blocks' trailing expression must be of unit type or the block must diverge before reaching its end.
8892

8993
### Diverging iterators
9094

91-
For example, an `iter` block that produces the sequence `0, 1, 0, 1, 0, 1, ...`, will never return `None`
95+
For example, an `gen` block that produces the sequence `0, 1, 0, 1, 0, 1, ...`, will never return `None`
9296
from `next`, and only drop its captured data when the iterator is dropped.
9397

9498
```rust
95-
iter {
99+
gen {
96100
loop {
97101
yield 0;
98102
yield 1;
99103
}
100104
}
101105
```
102106

103-
If an `iter` panics, the behavior is very similar to `return`, except that `next` doesn't return `None`, but unwinds.
107+
If an `gen` panics, the behavior is very similar to `return`, except that `next` doesn't return `None`, but unwinds.
104108

105109
## Error handling
106110

107-
Within `iter` blocks, the `?` operator desugars differently from how it desugars outside of `iter` blocks.
111+
Within `gen` blocks, the `?` operator desugars differently from how it desugars outside of `gen` blocks.
108112
Instead of returning the `Err` variant, `foo?` yields the `Err` variant and then `return`s immediately afterwards.
109113
This has the effect of it being an iterator with `Iterator::Item`'s type being `Result<T, E>`, and once a `Some(Err(e))`
110114
is produced via `?`, the iterator returns `None` next.
111115

112-
`iter` blocks do not need to have a trailing `Ok(x)` expression, because returning from an `iter` block will make the `Iterator` return `None` from now, which needs no value.
116+
`gen` blocks do not need to have a trailing `Ok(x)` expression, because returning from an `gen` block will make the `Iterator` return `None` from now, which needs no value.
113117

114118
# Reference-level explanation
115119
[reference-level-explanation]: #reference-level-explanation
@@ -141,34 +145,40 @@ Why should we *not* do this?
141145

142146
## Keyword
143147

144-
We could also use `gen` (for `generator`) as a keyword. The reason I chose `iter` in this RFC, is that people (including me) connect generators with a more powerful
148+
We could also use `iter` as a keyword. I would prefer `iter` in because I connect generators with a more powerful
145149
scheme than just plain `Iterator`s. The `Generator` trait can do everything that `iter` blocks and `async` blocks can do, and more. I believe connecting the `Iterator`
146-
trait with `iter` blocks is the right choice, but I also don't feel too strongly about it.
150+
trait with `iter` blocks is the right choice, but that would require us to carve out many exceptions for this keyword,
151+
as `iter` is used for module names and method names everywhere (including libstd/libcore).
152+
153+
## Contextual keyword
154+
155+
We allow `gen` as an identifier for function names and module names, without that conflicting with `gen` blocks, but that makes the syntax more complicated than necessary, for not too much gain.
156+
157+
## 2021 edition
147158

148-
## Non-Contextual keyword
159+
We could allow `gen` blocks on the 2021 edition via `k#gen {}` syntax.
160+
We can allow `gen fn` on all editions.
149161

150-
We could forbid `iter` from being used as an identifier anywhere.
162+
## `gen` identifiers on 2024 edition
151163

152-
I believe blocking `iter` (or even just `gen`) from being used as module, type and function names is not feasible.
153-
The standard library contains an `iter` module and many
154-
data structures have `iter` methods implemented for them.
164+
We can allow `i#gen` identifiers in the 2024 edition in order to refer to items named `gen` in previous edition crates.
155165

156166
## Do not do this
157167

158168
The alternative is to keep adding more helper methods to `Iterator`. It is already rather hard for new Rustaceans to get a hold of all the options they have on `Iterator`.
159169
Some such methods would also need to be very generic (not an `Iterator` example, but https://doc.rust-lang.org/std/primitive.array.html#method.try_map on arrays is something
160170
that has very complex diagnostics that are hard to improve, even if it's nice once it works).
161171

162-
Users can use crates like [`genawaiter`](https://crates.io/crates/genawaiter) instead, which work on stable and give you `gen!` blocks that behave pretty mostly
163-
like `iter` blocks, but don't have compiler support for nice diagnostics or language support for the `?` operator.
172+
Users can use crates like [`genawagen`](https://crates.io/crates/genawagen) instead, which work on stable and give you `gen!` blocks that behave pretty mostly
173+
like `gen` blocks, but don't have compiler support for nice diagnostics or language support for the `?` operator.
164174

165175
# Prior art
166176
[prior-art]: #prior-art
167177

168178
## Python
169179

170-
Python has `iter fn`: any funciton that uses `yield` internally.
171-
These work pretty much like the `iter` functions proposed in this PR. The main difference is that raising an
180+
Python has `gen fn`: any function that uses `yield` internally.
181+
These work pretty much like the `gen` functions proposed in this PR. The main difference is that raising an
172182
exception automatically passes the exception outwards, instead of yielding an `Err()` element.
173183

174184
```python

0 commit comments

Comments
 (0)