Implement `trap`
With structured concurrency, a child thread may throw an exception which, by default, will terminate execution of the thread, but will be lost. A method should be provided to ensure that exceptions are never "lost" in this way.
Whatever method is used for defining the exception handling, it should be hierarchical, and conform to the concurrent structure. In particular, stack safety should be maintained. It should not be possible to smuggle a resource outside of its bounded stack using an exception. If an exception is not handled in one thread then it should be handled by that thread's parent.
At the top level, a Supervisor must handle the exception one way or another, but this should be determined by a contextual value.
A typical usage would be:
async:
val x = 1
trap/*(using Monitor)*/:
case error: Exception => Out.println(error)
.within: // using monitor =>
val y = 2
async(calc(x, y))
trap will take a partial function, with return type Unit. It will capture the Monitor from the surrounding scope (so it will only be usable in an async context), and supply a new Monitor to the within body. If that body throws an exception, it will be matched against the partial function, or passed up to the parent Monitor. At the top of the chain, the supervisor will handle the uncaught exception according to a contextual value.
trap is implemented, but it's not clear yet whether it works reliably.