[Pitch #2] Property Delegates by Custom Attributes

This is a tumbled version of my two-type suggestion from earlier. There's one type for the delegate, and it contains an inner type called Storage. The delegate is stored statically while the storage is stored inline where the property is.

Unlike the previous iteration I came with in the pitch #1 thread, this one does not give access to self, but allows a subscript to be used to access the property's value instead of custom get and set functions.

@propertyDelegate 
struct Lazy<Value> {
  enum Storage {
    case uninitialized
    case initialized(Value)

    subscript (delegate: Lazy) {
      get {
        switch self {
        case .uninitialized:
          value = delegate.initialValue()
          self = .initialized(value)
          return value
        case .initialized(let value):
          return value
        }
      }
      set {
        self = .initialized(newValue)
      }
    }
  }

  var initialStorage: Storage { return .uninitialized }
  var initialValue: () -> Value

  init(initialValue: @autoclosure @escaping () -> Value) {
    self.initialValue = initialValue
  }
}

Then this code:

$Lazy var p: Int = 5

Would generate something like this:

// the delegate lives as a static variable
static var _p_delegate: Lazy<Int> = Lazy(initialValue: 5)
// the storage is an instance variable
var _p_storage: Lazy<Int>.Storage = Self._p_delegate.initialStorage
// the computed p accesses the value through the delegate
var p: Lazy<Int>.Value {
   mutating get {
      // mutating only when Lazy.get takes `self` as `inout`
      return _p_storage[_p_delegate]
   }
   set {
      // mutating only when Lazy.set takes `self` as `inout`
      _p_storage[_p_delegate] = newValue
   }
}

An approach like this could line up well in a world where custom attributes are statically stored structs: the "property delegate" attribute would be a custom attribute like others with the addition that it provides a storage type.