Skip to content

CEP-0005: Fallible Iterator Families

Draft

Draft proposal for iterator contracts whose step operation can fail. V1 canonical Iterator(Item) remains infallible and context-free.

Summary

Catalyst should add a separate fallible iterator contract family instead of making canonical Iterator(Item).next return errors.

Example

Possible future shape:

fn FallibleIterator(comptime Item: Type, comptime E: Error) => contract {
  fn next(self: *Self) (?Item)!E
}

The exact spelling depends on final error-return precedence, but the semantic distinction is fixed: an iterator step may yield an item, return null for done, or return an error.

Motivation

V1 Iterator(Item) is intentionally minimal: next(self) returns ?Item, and end-of-iteration is not an error. Adding errors to that contract would infect every ordinary loop and dynamic iterator with fallibility even when iteration cannot fail.

A separate fallible family lets APIs opt into per-step errors while keeping infallible loops simple.

Proposed Direction

Fallible iteration should use its own contract family, such as FallibleIterator(Item, E).

Dynamic fallible iteration should also use that family explicitly:

Box(dyn FallibleIterator(Item, E))

Loop syntax for fallible iteration is not part of this proposal unless a later design explicitly chooses to integrate fallible steps with for.

V1 Compatibility

V1 for lowering only calls infallible operations: iter, iter_mut, or next. Fallible setup must happen before the loop, and fallible per-step iteration is not modeled by canonical Iterator(Item).