Pitch: Fix rethrows checking and add rethrows(unsafe)

My current thinking is to actually wrap the entire idiom in a new builtin operator, analogous to withoutActuallyEscaping. Basically we want something like this:

/// Calls `fn` with a closure that evaluates `inner`, and saves the
/// result. Then after `fn` returns, forces the result.
///
/// \param fn A function taking a no-parameter, no-result closure as
///           an argument. This function must call its argument at
///           least once.
/// \param inner A function that can throw or return a 'T'.
///
/// \returns Whatever `inner` returned, or throws an error if `inner`
///          throws an error.
///
/// \fatal A fatal trap occurs if `fn` does not invoke its argument
///        at least once.
func withRethrownError<T>(_ fn: (() -> ()) -> (),
                          _ inner: () throws -> T) rethrows -> T {
  var result: Result<T, Error>!

  fn {
    result = Result(catching: inner)
  }

  return try result.get()
}

The idea is that withRethrownError is rethrows(unsafe), but it would be the only place where you'd need rethrows(unsafe) (making it an implementation detail of the compiler; either withRethrownError would be a builtin intrinsic, or it would use an underscored attribute specially for this purpose).

1 Like