[swift-evolution] [Pitch] Rename `AnyObject` to `AnyClass` and drop current `AnyClass`

Dave Abrahams dabrahams at apple.com
Sun May 22 13:23:47 CDT 2016


on Fri May 20 2016, Matthew Johnson <swift-evolution at swift.org> wrote:

>> On May 20, 2016, at 7:40 PM, Brent Royal-Gordon via swift-evolution <swift-evolution at swift.org> wrote:
>> 
>>> The Any-class requirement could replace the current `AnyObject`
>>> protocol with a typealias like this: `typealias AnyObject =
>>> Any<class>`
>
>>> 
>>> Assume Swift would introduce Any-struct and Any-enum requirement
>>> one day. How would one name a typealias for these, where `AnyClass`
>>> means `AnyObject.Type`?
>>> 
>>> I suggest we drop the current `AnyClass` and rename `AnyObject` to
>>> `AnyClass`. If one would need the old `AnyClass` behavior it will
>>> become `AnyClass.Type`.
>> 
>> I propose that we deprecate `AnyObject` in favor of `Any<class>`. No
>> typealias, just directly using `Any<>`. We would also deprecate
>> `AnyClass` in favor of `Any<class>.Type`. (Presumably we would do
>> this by providing `AnyObject` and `AnyClass` typealiases in Swift 3,
>> but marking them as deprecated.)
>> 
>> I like this approach because it exposes people to `Any<>` and more
>> quickly gets them to see how it's connected to a protocol
>> declaration's conformance list. They might then guess that `Any<>`
>> has other capabilities from that list, like the ability to handle
>> multiple protocols.
>> 
>>> In the future we could have typealiases like this, which are more clear:
>>> 
>>> `typealias AnyClass = Any<class>`
>>> `typealias AnyStruct = Any<struct>`
>>> `typealias AnyEnum = Any<enum>`
>> 
>> Even in the long term, I don't see any good reason to support
>> `Any<struct>` vs. `Any<enum>`. There is no semantic distinction*
>> between a struct and an enum; you can always implement something
>> enum-y using a struct with a mode field, or something struct-y using
>> an enum with associated values. `Bool`, for instance, was once an
>> enum and was changed to a struct for implementation reasons; this
>> change made no difference to how it was used.
>> 
>> Now, there *is* a semantic distinction between struct/enum and
>> class—one is a value type, the other is a reference type. To support
>> that distinction, it might make sense to support an `Any<value>` or
>> `Any<!class>` syntax. Again, I would prefer to use the raw `Any<>`
>> syntax, though, not a typealias.
>
> You can implement reference types with value semantics and value types
> with reference semantics.  Until the compiler can verify value
> semantics I am not sure there is a benefit to `any<value>`.  The
> semantic distinction is what is important.  There has been discussion
> about strengthening the “value type == value semantics” and “reference
> type == reference semantics” relations but that hasn’t yet moved
> beyond talk.
>
>> 
>> (I've read the arguments about pure vs. non-pure value type
>> conformances and I'm not convinced. It is always possible to
>> nominally "conform" to a protocol in a way that actually undermines
>> its guarantees; for example, you could implement
>> `RangeReplaceableCollection.remove(at:)` as a no-op. The compiler
>> cannot reject all invalid conformances; it can only reject ones
>> which it can trivially show are invalid, because for instance they
>> do not even attempt to provide a required method. Similarly, the
>> compiler may not be able to prove you are providing value semantics,
>> but it *can* reject conformances of reference types to a protocol
>> requiring value semantics, since those cannot possibly be valid
>> conformances.
>
> Immutable reference types actually *can* provide valid value semantics
> (at least as long as as they can provide their own implementation of
> `==` which I believe Dave A is arguing against).

I am not making a strong argument against that, though it might be
reasonable.  I am mostly arguing in favor of a default definition of ==
for all reference types that is equivalent to ===.

> There is a big difference between semantics that the compiler *could*
> but *does not yet* verify and semantics that simply cannot be
> verified.
>
>> 
>> Incidentally, I am not convinced that it *ever* makes sense to have
>> a mutating protocol which does not specify either value or reference
>> semantics.
>> The only intentional Stdlib examples I'm aware of are
>> `IteratorProtocol` and `OutputStream`, and I think both of those
>> should be reference-only.
>> 
>> (On the other hand, it might make sense to be able to mark a struct
>> or enum as "this is actually a reference type". For instance, if you
>> import libc, UnsafeMutablePointer<FILE> is essentially a reference
>> type. But on the gripping hand, you *could*, and perhaps should,
>> just wrap it in a class, either through importer magic or a
>> manually-created type. That would permit you to conform it to
>> reference-typed mutating protocols.))
>
> This is a good example of why the semantics aren’t so simple.  
>
>> 
>> 
>> 
>> * There *are* some distinctions, particularly in pattern matching, but protocols can't model them anyway. Incidentally, it is not possible to satisfy static property/method requirements with cases, but it probably should be:
>> 
>>    protocol OptionalProtocol { 
>>        associatedtype W
>>        static var none: Self { get } 
>>        static func some(value: W) -> Self 
>>    } 
>>    extension Optional: OptionalProtocol {
>>        typealias W = Wrapped
>>    }
>
> I think there was discussion at some point about introducing enum case
> requirements into protocols.  But that is mostly tangential to this
> discussion.
>
>> 
>> 
>> -- 
>> Brent Royal-Gordon
>> Architechies
>> 
>> _______________________________________________
>> swift-evolution mailing list
>> swift-evolution at swift.org
>> https://lists.swift.org/mailman/listinfo/swift-evolution
>
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution

-- 
-Dave



More information about the swift-evolution mailing list