Getter called during normal assignment?

I have this scenario code in my project. The following code works, however in my project it traps as during assignment the getter is unexpectedly called. How is this possible? Any ideas what I could check and try?

@propertyWrapper
public struct DelayedMutable<Value> {
  private var _value: Value?

  public init() {
    _value = nil
  }

  public var wrappedValue: Value {
    get {
      guard
        let value = _value
      else {
        fatalError("property accessed before being initialized")
      }
      return value
    }
    set {
      _value = newValue
    }
  }
}

protocol ValueHost: AnyObject {
  var value: Int { get set }
}

class Object: ValueHost {
  @DelayedMutable
  var value: Int
}

let object: AnyObject = Object()

if let host = object as? ValueHost {
  var value = 0
  value = 42
  host.value = value
}

It's being called when you invoke the setter.

For what purpose? This is a pure assignment. I'm aware of the bug in key-paths during a wrong instruction being used and inside property observers like didSet and such, but this one is new to me. Also as I noted the above sample works as expected and no getter is called, in my project it calls the getter. :(

What's the difference between the sample and your project? Debug versus release?

Just different kind of values. This happens on the main queue but during collectionView.performBatchUpdates, but I'm not sure if this anyhow related.

I just tested the same code as above in app delegate, and it worked. So I guess there is something else which derails.

Okay found it. The difference was that the real implementation had a didSet observer on the wrapped property which will cause the call to getter.

Can't wait for this to finally be usable: [Accepted] SE-0268: Refine didSet Semantics

2 Likes