New Issue: When to halt upon an unhandled error?

19388, "vasslitvinov", "When to halt upon an unhandled error?", "2022-03-08T22:57:01Z"

The prototype error handling mode allows a throwing function to be invoked outside of a try/try! block or another throwing function.

This issue asks how this happens when the throwing function is invoked within a task- or data-parallel construct. For example:

proc throwingFunction() throws {
  throw new MyError();
}
// OK in the prototype mode
proc test() {
  writeln("start test");
  forall i in 1000000000 {
    if i == 55 then
      throwingFunction();
    doSomeWork();
  }
  writeln("finish test");
}
test();

Here are some ways to think about it.

(immediate) Since there is no surrounding try/try! block, then each call to a throwing function is implicitly prefixed by a try!. The above example can be written equivalently as follows. The program halts immediately when iteration 55 is executed.

......
    if i == 55 then
      try! throwingFunction();
......

(forall) The forall loop serves as an implicit exception handler in the same way as it does when it is inside a try block or a function that throws, as per the spec. Namely, it collects all errors thrown in its body and throws a single TaskErrors error. The program halts immediately once the forall loop finishes. This is the case even if the forall loop is lexically inside another task construct. The above example can be written equivalently as follows:

......
 try! {
  forall i in 1000000000 {
    if i == 55 then
      throwingFunction();
    doSomeWork();
  }
 }
......

(function) The errors propagate within the body of the function in the same way they do when the function is marked with throws. The error that would be thrown by the function if it were marked with throws causes the program to halt. The function can be written equivalently as follows:

proc test() {
  try! {
    ...... the function body ......
  }
}