[swift-evolution] [swift-evolution-announce] [Review] SE-0125: Remove NonObjectiveCBase and isUniquelyReferenced

Arnold Schwaighofer aschwaighofer at apple.com
Wed Jul 20 08:04:53 CDT 2016

> On Jul 20, 2016, at 5:03 AM, Haravikk via swift-evolution <swift-evolution at swift.org> wrote:
>> On 20 Jul 2016, at 11:13, Brent Royal-Gordon via swift-evolution <swift-evolution at swift.org> wrote:
>>> On Jul 19, 2016, at 11:06 PM, Dmitri Gribenko via swift-evolution <swift-evolution at swift.org> wrote:
>>> - I find it a little strange to see a mention of Objective-C, and a
>>> negation in `isUniquelyReferencedNonObjC`.  For example, if we get C++
>>> import, would we need to rename it to
>>> `isUniquelyReferencedNonObjCAndNonCXX`?  I think that is the issue
>>> with negation.  If we want to emphasize that the API will work only
>>> with Swift types, we can do something
>>> `isUniquelyReferencedSwiftReference`.  But I would probably suggest
>>> that we just go with just `isUniquelyReferenced` and mention the
>>> Swift-only requirement in the documentation.
>> I agree.
>> What is the reason that isUniquelyReferenced(_:) doesn't work with Objective-C? It doesn't seem like it'd be difficult to implement—you'd either call -retainCount, or get it from the Objective-C runtime somehow, and then test it against 1—so I assume there's a reason we don't.
>> I ask because knowing that may help us figure out how to name it. For instance, if the issue is that we can't rely on Objective-C reference counts, we might reverse the sense of the call and name it `mayBeShared(_:)` or `mayHaveOtherReferences(_:)`.
> I'm kind of undecided too; in fact it's never been clear to me why this is even a global function at all. In my mind the best solution would be some kind of ReferenceCounted class protocol with a .isUniquelyReferenced computed property, thus eliminating the global function entirely. The pure-Swift base type would conform to this protocol and provide the ability to test its uniqueness directly, though a static method could also be provided for testing unknown types as well (but I feel this is a relatively uncommon case), and the protocol conformance could be added to an Objective-C, C++ and so-on base-types whenever these are possible.
> It also strikes me as odd that we have to specify a NonObjectiveCBase in any form (extension or function, doesn't really matter); I would think that a pure Swift base should be the default in most cases, with a distinction having to be made only when declaring public classes in a module with Objective-C bridging headers. In other words it feels strange that non-Objective-C is the exception, when the goal should be trying to write pure Swift code wherever possible.
> I don't know about anyone else, but I mostly only use NonObjectiveCBase on private types implementing copy-on-write behaviour, so my only use-case for isUniquelyReferenced is private to the module anyway, so shouldn't really raise an issue of whether it's Objective-C compatible.

As mentioned in the other emails isUniquelyReferencedNonObjC works on @objc classes.

What has been misunderstood is the answer it returns. It returns false for @objc classes. Also see my other answers.

 var y = SwiftKlazz()
 var z = [Any]

The reason for this combination is data structures like Array which might hold an objc class which is not mutable. On a mutating operation you check is it uniquely reference and a swift class - if the answer is yes and you have enough storage you store to the current instance.

isUniquelyReferencedNonObjC <T: NonObjectiveBase> was there as a separate function historically. Because it was faster. This has changed and there  is no need to have both anymore.

As mentioned in the proposal you can use isUniquelyReferencedNonObjC where you are using isUniquelyReferencedNonObjC today. And it is semantically equivalent and has the same performance.

More information about the swift-evolution mailing list