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
catch_unwind is severely restricted: it’s not possible to mutably borrow (or pass a reference to a
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.
my_iterator.map(f) doesn’t actually do anything; it just returns an iterator adapter (
Map) that applies
f to items produced by
Map::next is called. So, to make this work, you’d either have to:
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