Can we forbid weak keyword for computed properties?

I raised this topic long time ago, in this GitHub PR.

Main concerns remain the same. You are still able to add weak attribute to a computed property and it is absolutely unclear whether it will affect anything and if yes - in what way.

Maybe we should forbid it completely or at least raise a warning about redundancy?

4 Likes

I’d be fine with making a warning with an explanation that it has no effect on computed properties. That’s granted it really has no effect.

Sure we can, it‘s just no one tackled the implementation and a formal proposal yet. And yes weak on computed properties does not have any meaning.

1 Like

Doesn’t seem like this would need a proposal, if it has no effect currently then it being allowed seems like a bug.

6 Likes

The only case where I can see it being useful is as a kind of documentation for the behavior of a computed property:

class Thing {
    private weak var _delegate: SomeDelegateType?
    
    // 'weak' here does nothing for the compiler, but it does
    // document to callers that the property is stored weakly
    weak var delegate: SomeDelegateType? {
        get { return _delegate }
        set { 
            if (self.delegateIsAcceptable(newValue)) { _delegate = newValue }
        }
    }
}

I don't know if that's a good reason to continue allowing weak on computed properties, though.

1 Like

It's at least partially one of those cases where Objective-C allows it, so Swift allows it too. As far as I know it's mostly for the reason BJ brought up.

(There's an unfortunate part where it may be required in Objective-C because a protocol requirement might specify that a property is weak, even though the implementation is computed.)

I think this is an oversight. I agree with @Chris_Lattner3 that at this stage it is best to add a warning, just like we do for weak on protocol requirements. In fact it should be easy to generalize the existing code for doing that.

I would suggest skipping the evolution proposal unless somebody objects.

Do you want to file a bug or even attempt an implementation?

1 Like

*raises hand* Until we work out the Objective-C protocol thing, we can't change this.

Excuse me if I jump here with a not-quite-about-Swift rant.

In Obj-C, there isn't really anything that could be called a "weak" or a "strong" property. The property value (in this case) is a reference to an object, and there's no such thing as a weak or strong reference. It is variables (storage locations) that are weak or strong, not references (pointer values).

Unfortunately, people rely on their intuitions and still think there are weak and strong references, and this contaminates even discussions about Swift.

The significance of "weak" or "strong" on an Obj-C property is that it affects what kind of instance variable the compiler generates if it synthesizes the property — that is to say, if the property is what Swift would call a stored property.

This is only controversial — there was a long discussion about this on the old cocoa-dev list years ago —because some people insisted that calling an Obj-C property "weak" or "strong" is a kind of API contract — that the underlying implementation really does not or really does keep an owning reference to the object, somewhere in its dark interior, and that clients of the class are allowed to make decisions based on this supposed contract.

However, this is all truly an implementation detail, and (IMO) a bad one because of the confusion it engendered in the Obj-C world.

Having said all that, I think @jrose is still correct, that we can't change this in Swift — for @objc protocol methods — for potential source compatibility reasons, though not for functional reasons. This is a case where Swift has to continue to be a little bit broken because (IMO) Obj-C is.

Could we change it in code without the @objc annotation?

3 Likes

i believe so, but it would better if an expert would confirm that.

I don't think we need to allow silly things in Swift just to allow precise control of the unnecessary annotations produced in the exported Objective-C interface.

5 Likes

Wait, is this an argument for or against?

I don't think we should allow weak on Swift properties that don't have their own storage.

13 Likes

I initially bristled at this, because memory semantics of entity relationships are definitely not an implementation detail. For example, the delegate pattern in Cocoa depends heavily on objects not owning their delegates. The zeroing-ness of zeroing weak references also has API implications here.

On the other hand, there are many entity relationships that aren’t exposed as properties. In our code base, we have a widespread addObserver/removeObserver pattern – essentially multicast delegates – where observers are held weakly through a collection, and this has to be expressed through documentation and convention rather than annotations, just as the delegate pattern used to be.

Being able to express memory semantics of entity relationships in general wouldn’t necessarily be silly, but it would require something far more expressive than property annotations. As such keeping the latter around because the former might be nice is probably a bad idea.

2 Likes

Are there any resiliency concerns here related to library evolution, as a property may change between being stored and computed in different versions?

I think this is overly pedantic hair-splitting. Not only is "weak reference" a perfectly reasonable term for the existence of a reference that does not keep the object alive (it even has a runtime representation in Swift!), but the API contract of strong vs. weak (Cocoa terminology that predates ARC or even ObjC GC) is important in reasoning about your object graph.

This is pushing me towards keeping weak on computed properties in Swift.

2 Likes

No; weakness is not part of the interface to the property as far as the language is concerned.

1 Like

I don't think the language should allow you to write things that have no semantic effect. It will only lead to confusion.

7 Likes

That also implies weak should not be visible in generated interfaces.