Default values for arguments that rethrow

I've just stumbled upon a peculiarity with rethrows:

func foo(_ bar: () throws -> Void = { }) rethrows {
foo() // Call can throw but is not marked `try`

Even making the default explicit doesn't work:

let doesNotThrow: () -> Void = { }
func foo(_ bar: () throws -> Void = doesNotThrow) rethrows {
foo() // Call can throw but is not marked `try`

Only explicitly specifying the closure works:

func foo(_ bar: () throws -> Void = { }) rethrows {
foo({ })

I have 2 questions:

  1. Is there a way to work around this that isn't writing two separate functions?
  2. Can this be fixed? It seems simply fixing this may not be entirely source compatible since if you wrote try foo() before the fix it would now emit a warning that "no throwing functions occur within try expression". Maybe this can be mitigated by simply not emitting the warning if it is the result of a non-throwing default argument to a rethrows function?

The following works, but unfortunately makes the closure @escaping:

func foo(_ bar: Optional<() throws -> Void> = nil) rethrows {

It looks very much like a bug, since the first and the second errors are incongruent (call can throw vs no throwing functions occur). I'd say that the workaround is to use try! since that'd also stop the throws propagation.

For the record, this is tracked as SR-1534. It's an older bug, presumably unfixed because you can work around it with try!, but hopefully someone will get to it at some point!

Terms of Service

Privacy Policy

Cookie Policy