> 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.
(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.
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.))
* 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
}
--
Brent Royal-Gordon
Architechies
_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution