Closures currently cannot return references to captured variables. For instance the following code produces an error saying "references to captured variables can't escape the closure".
fn foo() {
let arr = [1, 2, 3];
let c = move |i: usize| &arr[i];
}
However, with GATs an alternate Fn
trait could be defined like this:
trait LendingFn<Args> {
type Output<'s>;
fn call(&self, arg: Args) -> Self::Output<'_>;
}
This would allow return types that are tied to the lifetime of self
and is similar to the discussed lending variants of Iterator
and Stream
.
In my opinion it would also be useful to provide a GAT variants of Fn
and FnMut
once GATs are stable. The compiler could then accept the function foo
from above creating a closure implementing LendingFn
.
A downside of including Lending*
variants for the closure and iterator traits is a further increase in complexity, considering there are already three different traits for closures.
Since non-lending closures can be implemented in terms of the lending trait variants, I wonder if it were possible to change the existing traits instead, by adding a generic lifetime parameter to their associated types.
While, currently, this would be a breaking change, it might be possible to add the lifetime parameter in a compatibility-friendly way.
The compiler could accept "downgraded" implementations of traits with GATs.
In implementations not using the generic parameters of the associated type, the compiler could allow referring to the associated type without specifying generic arguments.
This could work since such implementations constitute "special cases" of implementations that do use the GAT parameters.
Thus all existing implementations of the non-GAT traits would still be accepted after adding the lifetime parameter, making it a non-breaking change.
This would also be beneficial for the Iterator
and Stream
traits, avoiding redundancy with potential LendingIterator
or LendingStream
variants.
Do you think closure traits using GATs would be useful?
Is is realistic to change the existing closure and iterator traits?