They may be useful in some cases but really arenāt worth the trouble in Rust. As a matter of fact, they almost certainly wouldnāt help here because iterators are composable.
Currently, the only way to do a non-local return is to panic!() and catch_unwind. However, catch_unwind is severely restricted: itās not possible to mutably borrow (or pass a reference to a RefCell, Cell, or anything with interior mutability for that matter) across a catch_unwind barrier. This restriction is necessary to avoid exposing types with violated invariants (e.g. by violating some invariant, calling something that could panic, fixing the invariant).
To make TCP preserving closures useful, youād have to drop these constraints. Then, to make them reasonably safe, youād have to label functions that can perform this type of unrestricted non-local return in the type system (so you can avoid calling them while violating invariants). Thatās where youād get into trouble with iterators.
Basically, my_iterator.map(f) doesnāt actually do anything; it just returns an iterator adapter (Map) that applies f to items produced by my_iterator whenever Map::next is called. So, to make this work, youād either have to:
- Label
Iterator::next as potentially performing a non-local return. As this would affect all iterators so itās obviously a non-starter.
- Somehow parametrize the
Iterator trait over some kind of non-local return property (something akin to a lifetime). Now youād effectively have two lifetime systems.
So, you could make this work for the very simple case where you take a closure and call it immediately but, in that case, Iād just use a macro.
Note: In your case, you might want to consider proposing RefMut::try_map.