Read/modify, yield, and non-escaping closures

I know _read and _modify are still experimental features, but I was wondering if it should be possible to yield from within a closure so long as it's not escaping. For example, should the following non-compiling code work?

private let lock = NSLock()
private var _x: Int
var x: Int {
  _read { lock.withLock { yield _x } }     // 🛑
  _modify { lock.withLock { yield &_x } }  // 🛑
}

:stop_sign: Cannot find 'yield' in scope

We need a way to represent this sort of scoped setup in a way that's compatible with coroutines, but we can't really retrofit the ability to yield from an outer coroutine in the middle of a closure in the current representation. What I'd like to see is for single-yield coroutines to eventually be generalized to the point they can supersede withClosure style APIs, so you could write something like:

@noncopyable struct Guard {}

extension NSLock {
  var guard: Guard {
    read {
      _lock()
      yield Guard()
      _unlock()
    }
  }
}

var x: Int {
  read {
    with lock.guard {
      yield _x
    }
  }
}
11 Likes