I stumbled across an example with static || { }
in docs which works. Yet an attempt to use such an expression in my own code fails. I wonder why.
the very example from https://doc.rust-lang.org/stable/std/pin/macro.pin.html
#![feature(generators, generator_trait)]
use std::{
ops::{Generator, GeneratorState},
pin::pin,
};
fn generator_fn() -> impl Generator<Yield = usize, Return = ()> /* not Unpin */ {
// Allow generator to be self-referential (not `Unpin`)
// vvvvvv so that locals can cross yield points.
static || {
let foo = String::from("foo");
let foo_ref = &foo; // ------+
yield 0; // | <- crosses yield point!
println!("{foo_ref}"); // <--+
yield foo.len();
}
}
fn main() {
let mut generator = pin!(generator_fn());
match generator.as_mut().resume(()) {
GeneratorState::Yielded(0) => {},
_ => unreachable!(),
}
match generator.as_mut().resume(()) {
GeneratorState::Yielded(3) => {},
_ => unreachable!(),
}
match generator.resume(()) {
GeneratorState::Yielded(_) => unreachable!(),
GeneratorState::Complete(()) => {},
}
}
my attempt which fails:
fn func() -> impl Fn() {
static || {
println!("qwerty");
}
}
with the following error:
error[E0697]: closures cannot be static
--> ./ex_099.rs:2:5
|
2 | static || {
| ^^^^^^^^^
rust version:
$ rustc --version
rustc 1.70.0-nightly (88fb1b922 2023-04-10)
At the time of writing, the Rust stable toolchain does not support static closures in any way. What you are seeing is the use of the unstable feature generators, which resorts to a closure-like syntax to represent generator functions. Quoting a few relevant parts:
A generator is a "resumable function" that syntactically resembles a closure but compiles to much different semantics in the compiler itself. [...] Generators use the
yield
keyword to "return", and then the caller can resume a generator to resume execution just after the yield keyword.[...]
Generators are closure-like literals which can contain a
yield
statement. Theyield
statement takes an optional expression of a value to yield out of the generator. All generator literals implement theGenerator
trait in thestd::ops
module
As an unstable feature, any details about its functioning are subject to change. As of nightly-2023-04-02
, the syntax static || { /* ... */ }
will only work if you add the necessary feature attributes, make the function return impl Generator
instead of impl Fn
, and you include at least one yield
in the generator.
#![feature(generators, generator_trait)]
use std::ops::Generator;
fn func() -> impl Generator<Yield = (), Return = ()> {
static || {
yield;
println!("qwerty");
}
}
See also: