[Proposal] Disallow `weak` for computed properties

Currently, the compiler allows marking as weak the computed properties, but since they don't store values, the weak keyword makes no sense.

class Human {
    
    var _friend: Human?
    
    weak var friend: Human? {
        set {
            self._friend = newValue
        }
        get {
            return self._friend
        }
    }
    
    deinit {
        print("deinit")
    }
    
}

var human: Human?  = Human()
var friend: Human? = Human()

human?.friend = friend
friend?.friend = human
human?.friend

human = nil
friend = nil

In the above example, as you can see, the weak have no effect, as result, we have a memory leak. If the compiler disallows the weak keyword, we can notice that the weak mark should be on another property.

The possibility of a leak is a bit of a red herring here—it's trivially easy to convert a weak reference to a strong reference in a stored weak property's didSet as well, with the same effect. Perhaps in simple cases like this it would be useful to emit a warning to the effect of "Assigning newValue to self._friend immediately forms a strong reference. Did you mean to make _friend weak?".

As to why this is allowed... I'm not sure. Perhaps it's related to the goal that replacing a stored property with a computed property be ABI compatible for resilient binaries?

See also the discussion in Can we forbid weak keyword for computed properties? and the related discussion in Should weak be a type?

4 Likes