Using an inout parameter exclusively for an asynchronous task is an abuse of inout – as when calling the function, the caller's value that is passed into the inout parameter will not be changed.

This is because inout isn't a 'pass by reference' (see this Q&A for more info), it's just a mutable shadow copy of the parameter that's written back to the caller when the function exits – and because an asynchronous function exits immediately, no changes will be written back.

You can see this in the following Swift 2 example, where an inout parameter is allowed to be captured by an escaping closure:

Because the closure that is passed to dispatch_async escapes the lifetime of the function foo, any changes it makes to val aren't written back to the caller's str – the change is only observable from being passed into the completion function.

In Swift 3, inout parameters are no longer allowed to be captured by @escaping closures, which eliminates the confusion of expecting a 'pass by reference'. Instead you have to capture the parameter by copying it, by adding it to the closure's capture list: