I love Borrow
and BorrowMut
but algorithms frequently want to borrow a “view” into a data structure. It’d be very cool if closures could be used like mutable borrows, but they cannot because you cannot make FnOnce::Output
dependent on the lifetime of the &mut self
parameter of FnMut::call_mut
.
Would this even be possible? Maybe:
pub trait FnOnce<Args> {
type Output<'fn>;
extern "rust-call" fn call_once(self, args: Args) -> Self::Output<'static>;
}
pub trait FnMut<Args>: FnOnce<Args> {
extern "rust-call" fn call_mut<'fn>(&'fn mut self, args: Args) -> Self::Output<'fn>;
}
pub trait Fn<Args>: FnMut<Args> {
extern "rust-call" fn call<'fn>(&'fn self, args: Args) -> Self::Output<'fn>;
}
Is this doable? I.e. can FnOnce::call_once
actually call FnMut::call_mut
? I’d think no because consumed as self
is not quite the same as 'static
.
Instead, we might consider a second hierarchy, maybe named View*
, but maybe FnBorrow*
explains them better:
pub trait FnBorrowMut<Args<'borrow>> {
type Output<'borrow>;
extern "rust-call" fn borrow_mut<'borrow>(&'fn mut self, args: Args<'borrow>) -> Self::Output<'borrow>;
}
pub trait FnBorrow<Args<'borrow>>: FnBorrowMut<Args<'borrow>> {
extern "rust-call" fn borrow<'borrow>(&'borrow self, args: Args<'borrow>) -> Self::Output<'borrow>;
}
These traits could be specified by the syntax
FnBorrow([Args]<'borrow>) -> [Output]<'borrow>
FnBorrowMut([Args]<'borrow>) -> [Output]<'borrow>
where [Args]
and [Output]
work like with Fn*
traits, but now admit a special lifetime 'borrow
to reference the lifetime of 'self
.
We might create types satisfying these traits with the familiar |..| ...
syntax, which now satisfies both Fn*
and FnBorrow*
traits when possible, but may only satisfy the FnBorrow*
variant. Is this workable? I think so, but it’s tricky:
If v : &'a mut [T]
then || v.iter_mut()
satisfies FnBorrowMut() -> IterMut<'borrow,T>
, but also satisfies FnOnce() -> IterMut<'a,T>
. That’s okay, but we might want a borrow |..| ...
syntax to distinguish, not sure.