This seems to be covered by Swift Evolution proposal 0035, and is considered a bug.
The document there refers to the inout parameter to the function as "a shadow copy that is written back to the argument when the callee returns". This seems to mean that there is, in essence, a temporary variable named success in the executing context of foo(). The value of that temp is then put into the outer success only when foo() returns.
Since in your foo(), the closure has not run when foo() returns, the value of the "shadow copy" has not changed. The outer success keeps its value.
The important part is that the closure has captured the shadow copy, not the outer success as you expect. So when the closure finally runs, that variable's value does change, but it no longer has any connection to the original outer success.
The proposal uses this snippet to demonstrate:
func captureAndEscape(inout x: Int) -> () -> Void {
let closure = { x += 1 }
closure()
return closure
}
var x = 22
let closure = captureAndEscape(&x)
print(x) // => 23
closure()
print("still \(x)") // => still 23