From a2bf47319c3cb0a5040678dd4fea36adce082575 Mon Sep 17 00:00:00 2001 From: Travis Cross Date: Thu, 14 Mar 2024 23:49:53 +0000 Subject: [PATCH] Add unresolved question about implemented traits To give us better options for supporting self-referential generators we may not want the type returned by `gen` blocks to implement `Iterator` directly. Let's call this out as an open question and weaken claims throughout the document related to this. --- text/0000-gen-fn.md | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/text/0000-gen-fn.md b/text/0000-gen-fn.md index 3751d4832..c4ad4511d 100644 --- a/text/0000-gen-fn.md +++ b/text/0000-gen-fn.md @@ -6,14 +6,7 @@ # Summary [summary]: #summary -Reserve the `gen` keyword in the 2024 edition. - -Add `gen {}` blocks to the language. These implement `Iterator` by `yield`ing -elements. This is simpler and more intuitive than creating a custom type and -manually implementing `Iterator` for that type, which requires writing an -explicit `Iterator::next` method body. This is a change similar to adding `async -{}` blocks that implement `Future` instead of having to manually write futures -and their state machines. +This RFC reserves the `gen` keyword in the Rust 2024 edition for generators and adds `gen { .. }` blocks to the language. Similar to how `async` blocks produce values that can be awaited with `.await`, `gen` blocks produce values that can be iterated over using `for` loops. # Motivation [motivation]: #motivation @@ -78,7 +71,7 @@ fn odd_dup(values: impl Iterator) -> impl Iterator { yield value * 2; } } - } + }.into() } ``` @@ -137,13 +130,13 @@ need to be given arguments of type `Option`. ## Fusing -`Iterator`s produced by `gen` keep returning `None` when invoked again after they have returned `None` once. +Iterators produced by `gen` keep returning `None` when invoked again after they have returned `None` once. They do not implement `FusedIterator`, as that is not a language item, but may implement it in the future. ## Holding borrows across yields Since the `Iterator::next` method takes `&mut self` instead of `Pin<&mut self>`, we cannot create self-referential -`gen` blocks. Self-referential `gen` blocks occur when you hold a borrow to a local variable across a yield point: +`gen` blocks (but see the open questions). Self-referential `gen` blocks occur when you hold a borrow to a local variable across a yield point: ```rust gen { @@ -199,7 +192,7 @@ This feature is mostly implemented via existing coroutines, though there are som * ...without arguments, * ...with an additional check forbidding holding borrows across `yield` points, -* ...and with an automatic `Iterator` implementation. +* ...and with an automatic implementation of a trait allowing the type to be used in `for` loops (see the open questions). * ...do not panic if invoked again after returning # Drawbacks @@ -637,6 +630,10 @@ main = putStrLn $ show $ take 5 $ oddDup [1..20] # Unresolved questions [unresolved-questions]: #unresolved-questions +## Whether to implement `Iterator` + +There may be benefits to having the type returned by `gen` blocks *not* implement `Iterator` directly. Instead, these blocks would return a type that implements either `IntoIterator` or a new `IntoGenerator` trait. Such a design could leave us more appealing options for supporting self-referential `gen` blocks. We leave this as an open question. + ## Self-referential `gen` blocks We can allow `gen` blocks to hold borrows across `yield` points. Should this be part of the initial stabilization?