currently, the Mutex type's locking method has the following signature:
public borrowing func withLock<Result: ~Copyable, E: Error>(
_ body: (inout sending Value) throws(E) -> sending Result
) throws(E) -> sending Result
i'd like to focus on the Result: ~Copyable generic constraint, as i don't quite understand its motivation, nor the current apparent behavior. my interpretation is that this constraint implies that the value returned from the body closure must be a ~Copyable type. would this then preclude the ability to do something like make a copy of the mutex-protected data and return it from the withLock closure? e.g.
let protectedState = Mutex(1)
let doubled = protectedState.withLock { 2*$0 } // `Result` type is `Int`, which does not conform to `~Copyable`
assuming this assessment is accurate – what is the motivation for the ~Copyable constraint here?
secondly, is the ~Copyable constraint on the Result type in the prior example actually being enforced by the compiler today? it appears to compile without issue, and allows Copyable types to be returned from the closure. this is somewhat surprising since analogous formulations that require a particular conformance on their generic parameters do not behave analogously. e.g.
func returnSomeNonCopyable<Result: ~Copyable>(
_ body: () -> Result
) -> Result {
body()
}
protocol P {}
func returnSomeP<Result: P>(
_ body: () -> Result
) -> Result {
body()
}
let works = returnSomeNonCopyable { 42 }
let fails = returnSomeP { 42 } // 🛑 Global function 'returnSomeP' requires that 'Int' conform to 'P'