> On Feb 14, 2017, at 5:28 AM, David Hart <[email protected]> wrote:
>
>
> On 14 Feb 2017, at 10:24, Slava Pestov <[email protected]
> <mailto:[email protected]>> wrote:
>
>>
>>> On Feb 12, 2017, at 12:32 PM, David Hart via swift-evolution
>>> <[email protected] <mailto:[email protected]>> wrote:
>>>
>>> Hi Matthew,
>>>
>>> Your arguments made sense to me. I modified the proposal to choose strategy
>>> number 3: deprecating and removing class over several versions to favour
>>> AnyObject. Mind having another proof read?
>>>
>>> https://github.com/hartbit/swift-evolution/blob/subclass-existentials/proposals/XXXX-subclass-existentials.md
>>>
>>> <https://github.com/hartbit/swift-evolution/blob/subclass-existentials/proposals/XXXX-subclass-existentials.md>
>>>
>>> Anybody has counter arguments?
>>>
>>> Class and Subtype existentials
>>>
>>> Proposal: SE-XXXX
>>> <https://github.com/hartbit/swift-evolution/blob/subclass-existentials/proposals/XXXX-subclass-existentials.md>
>>> Authors: David Hart <http://github.com/hartbit/>, Austin Zheng
>>> <http://github.com/austinzheng>
>>> Review Manager: TBD
>>> Status: TBD
>>>
>>> <https://github.com/hartbit/swift-evolution/tree/subclass-existentials#introduction>Introduction
>>>
>>> This proposal brings more expressive power to the type system by allowing
>>> Swift to represent existentials of classes and subtypes which conform to
>>> protocols.
>>>
>>>
>>> <https://github.com/hartbit/swift-evolution/tree/subclass-existentials#motivation>Motivation
>>>
>>> Currently, the only existentials which can be represented in Swift are
>>> conformances to a set of protocols, using the &protocol composition syntax:
>>>
>>> Protocol1 & Protocol2
>>> On the other hand, Objective-C is capable of expressing existentials of
>>> classes and subclasses conforming to protocols with the following syntax:
>>>
>>> id<Protocol1, Protocol2>
>>> Base<Protocol>*
>>> We propose to provide similar expressive power to Swift, which will also
>>> improve the bridging of those types from Objective-C.
>>>
>>>
>>> <https://github.com/hartbit/swift-evolution/tree/subclass-existentials#proposed-solution>Proposed
>>> solution
>>>
>>> The proposal keeps the existing & syntax but allows the first element, and
>>> only the first, to be either the AnyObjectkeyword or of class type. The
>>> equivalent to the above Objective-C types would look like this:
>>>
>>> AnyObject & Protocol1 & Protocol2
>>> Base & Protocol
>>> As in Objective-C, the first line is an existential of classes which
>>> conform to Protocol1 and Protocol2, and the second line is an existential
>>> of subtypes of Base which conform to Protocol.
>>>
>>> Here are the new proposed rules for what is valid in a existential
>>> conjunction syntax:
>>>
>>>
>>> <https://github.com/hartbit/swift-evolution/tree/subclass-existentials#1-the-first-element-in-the-protocol-composition-syntax-can-be-the-anyobject-keyword-to-enforce-a-class-constraint>1.
>>> The first element in the protocol composition syntax can be the AnyObject
>>> keyword to enforce a class constraint:
>>>
>>> protocol P {}
>>> struct S : P {}
>>> class C : P {}
>>> let t: P & AnyObject // Compiler error: AnyObject requirement must be in
>>> first position
>>> let u: AnyObject & P = S() // Compiler error: S is not of class type
>>> let v: AnyObject & P = C() // Compiles successfully
>>>
>>> <https://github.com/hartbit/swift-evolution/tree/subclass-existentials#2-the-first-element-in-the-protocol-composition-syntax-can-be-a-class-type-to-enforce-the-existential-to-be-a-subtype-of-the-class>2.
>>> The first element in the protocol composition syntax can be a class type
>>> to enforce the existential to be a subtype of the class:
>>>
>>> protocol P {}
>>> struct S {}
>>> class C {}
>>> class D : P {}
>>> class E : C, P {}
>>> let t: P & C // Compiler error: subclass constraint must be in first
>>> position
>>> let u: S & P // Compiler error: S is not of class type
>>> let v: C & P = D() // Compiler error: D is not a subtype of C
>>> let w: C & P = E() // Compiles successfully
>>>
>>> <https://github.com/hartbit/swift-evolution/tree/subclass-existentials#3-when-a-protocol-composition-type-contains-a-typealias-the-validity-of-the-type-is-determined-using-the-following-steps>3.
>>> When a protocol composition type contains a typealias, the validity of the
>>> type is determined using the following steps:
>>>
>>> Expand the typealias
>>> Normalize the type by removing duplicate constraints and replacing less
>>> specific constraints by more specific constraints (a class constraint is
>>> less specific than a class type constraint, which is less specific than a
>>> constraint of a subclass of that class).
>>> Check that the type does not contain two class-type constraints
>>
>> You could generalize this and instead say that if the type contains two
>> class-type constraints, the resulting existential type is the common base
>> class of the two classes, or AnyObject if they do not share a common base
>> class.
>
> But if they share a common base class, the existential is invalid. Did I
> misunderstand your generalization?
Did you mean to say if they *don’t* share a common base class?
>
>> Also, I’d like to see some discussion about class-constrained existentials
>> appearing in the inheritance clause of a protocol. IMHO, we should ban this:
>>
>> typealias MyType = SomeClass & SomeProtocol
>>
>> protocol SomeOtherProtocol : MyType {}
>
> Yep, I'll make that clear. It should be disallowed IMHO. Thanks!
>
>> Slava
>>
>>> class C {}
>>> class D : C {}
>>> class E {}
>>> protocol P1 {}
>>> protocol P2 {}
>>> typealias TA1 = AnyObject & P1
>>> typealias TA2 = AnyObject & P2
>>> typealias TA3 = C & P2
>>> typealias TA4 = D & P2
>>> typealias TA5 = E & P2
>>>
>>> typealias TA5 = TA1 & TA2
>>> // Expansion: typealias TA5 = AnyObject & P1 & AnyObject & P2
>>> // Normalization: typealias TA5 = AnyObject & P1 & P2
>>> // TA5 is valid
>>>
>>> typealias TA6 = TA1 & TA3
>>> // Expansion: typealias TA6 = AnyObject & P1 & C & P2
>>> // Normalization (AnyObject < C): typealias TA6 = C & P1 & P2
>>> // TA6 is valid
>>>
>>> typealias TA7 = TA3 & TA4
>>> // Expansion: typealias TA7 = C & P2 & D & P2
>>> // Normalization (C < D): typealias TA7 = D & P2
>>> // TA7 is valid
>>>
>>> typealias TA8 = TA4 & TA5
>>> // Expansion: typealias TA8 = D & P2 & E & P2
>>> // Normalization: typealias TA8 = D & E & P2
>>> // TA8 is invalid because the D and E constraints are incompatible
>>>
>>> <https://github.com/hartbit/swift-evolution/tree/subclass-existentials#class-and-anyobject>class
>>> and AnyObject
>>>
>>> This proposal merges the concepts of class and AnyObject, which now have
>>> the same meaning: they represent an existential for classes. To get rid of
>>> the duplication, we suggest only keeping AnyObject around. To reduce
>>> source-breakage to a minimum, class could be redefined as typealias class =
>>> AnyObject and give a deprecation warning on class for the first version of
>>> Swift this proposal is implemented in. Later, class could be removed in a
>>> subsequent version of Swift.
>>>
>>>
>>> <https://github.com/hartbit/swift-evolution/tree/subclass-existentials#source-compatibility>Source
>>> compatibility
>>>
>>> This change will not break Swift 3 compability mode because Objective-C
>>> types will continue to be imported as before. But in Swift 4 mode, all
>>> types bridged from Objective-C which use the equivalent Objective-C
>>> existential syntax could break code which does not meet the new protocol
>>> requirements. For example, the following Objective-C code:
>>>
>>> @interface MyViewController
>>> - (void)setup:(nonnull
>>> UIViewController<UITableViewDataSource,UITableViewDelegate>*)tableViewController;
>>> @end
>>> is imported into Swift-3 mode as:
>>>
>>> class MyViewController {
>>> func setup(tableViewController: UIViewController) {}
>>> }
>>> which allows calling the function with an invalid parameter:
>>>
>>> let myViewController: MyViewController()
>>> myViewController.setup(UIViewController())
>>> The previous code continues to compile but still crashs if the Objective-C
>>> code calls a method of UITableViewDataSource or UITableViewDelegate. But if
>>> this proposal is accepted and implemented as-is, the Objective-C code will
>>> be imported in Swift 4 mode as:
>>>
>>> class MyViewController {
>>> func setup(tableViewController: UIViewController &
>>> UITableViewDataSource & UITableViewDelegate) {}
>>> }
>>> That would then cause the Swift code run in version 4 mode to fail to
>>> compile with an error which states that UIViewController does not conform
>>> to the UITableViewDataSource and UITableViewDelegate protocols.
>>>
>>>
>>> <https://github.com/hartbit/swift-evolution/tree/subclass-existentials#alternatives-considered>Alternatives
>>> considered
>>>
>>> An alternative solution to the class/AnyObject duplication was to keep
>>> both, redefine AnyObject as typealias AnyObject = class and favor the
>>> latter when used as a type name.
>>>
>>>
>>> <https://github.com/hartbit/swift-evolution/tree/subclass-existentials#acknowledgements>Acknowledgements
>>>
>>> Thanks to Austin Zheng <http://github.com/austinzheng> and Matthew Johnson
>>> <https://github.com/anandabits> who brought a lot of attention to
>>> existentials in this mailing-list and from whom most of the ideas in the
>>> proposal come from.
>>>
>>>> On 9 Feb 2017, at 21:50, Matthew Johnson <[email protected]
>>>> <mailto:[email protected]>> wrote:
>>>>
>>>>
>>>>> On Feb 9, 2017, at 2:44 PM, David Hart <[email protected]
>>>>> <mailto:[email protected]>> wrote:
>>>>>
>>>>>
>>>>> On 9 Feb 2017, at 20:43, Matthew Johnson via swift-evolution
>>>>> <[email protected] <mailto:[email protected]>> wrote:
>>>>>
>>>>>>
>>>>>>
>>>>>> Sent from my iPad
>>>>>>
>>>>>> On Feb 9, 2017, at 1:30 PM, Hooman Mehr via swift-evolution
>>>>>> <[email protected] <mailto:[email protected]>> wrote:
>>>>>>
>>>>>>>
>>>>>>>> On Feb 9, 2017, at 10:47 AM, Joe Groff via swift-evolution
>>>>>>>> <[email protected] <mailto:[email protected]>> wrote:
>>>>>>>>> On Feb 9, 2017, at 4:26 AM, Step Christopher via swift-evolution
>>>>>>>>> <[email protected] <mailto:[email protected]>> wrote:
>>>>>>>>> Looks good. Minor comments below:
>>>>>>>>> The typealias 'T5' is repeated as both an initial composition, and as
>>>>>>>>> a demonstration of combining typealiases.
>>>>>>>>>
>>>>>>>>>> This proposal merges the concepts of class and AnyObject, which now
>>>>>>>>>> have the same meaning: they represent an existential for classes.
>>>>>>>>>> They are four solutions to this dilemna:
>>>>>>>>>> Do nothing.
>>>>>>>>>> Replace all uses of AnyObject by class, breaking source
>>>>>>>>>> compatibility.
>>>>>>>>>> Replace all uses of class by AnyObject, breaking source
>>>>>>>>>> compatibility.
>>>>>>>>>> Redefine AnyObject as typealias AnyObject = class.
>>>>>>>>> I agree with other comments on recommending 4 here, and covering the
>>>>>>>>> others as alternatives
>>>>>>>>>>
>>>>>>>>>> <https://github.com/hartbit/swift-evolution/blob/e6411d8a9e7924bbd8a48fc292bf08d58a8d1199/proposals/XXXX-subclass-existentials.md#source-compatibility>I
>>>>>>>>>> agree that we need the typealias for compatibility. I think it's
>>>>>>>>>> still worth discussing whether the `AnyObject` typealias should
>>>>>>>>>> *only* be there for compatibility; it could be deprecated or
>>>>>>>>>> obsoleted in Swift 4 or future language versions.
>>>>>>>
>>>>>>> I think it might be worth keeping to provide a more sensible
>>>>>>> capitalization alternative than lower case “class” when used as a type
>>>>>>> name:
>>>>>>>
>>>>>>> var obj: class // this looks weird because of capitalization.
>>>>>>>
>>>>>>> var obj: AnyObject // this looks better.
>>>>>>
>>>>>> I agree that it looks better and would choose AnyObject if source
>>>>>> compatibility weren't an issue. One option that wasn't listed was to
>>>>>> drop 'class' but use a multi-release deprecation strategy and a fix-it
>>>>>> to facilitate a smooth transition. If the community is willing to adopt
>>>>>> this approach it would be my first choice.
>>>>>
>>>>> You mean option 3?
>>>>
>>>> Pretty much, but option 3 does not make it clear that it won’t break
>>>> source immediately in Swift 4. I think it becomes much more reasonable if
>>>> Swift 3.1 code still compiles in Swift 4 mode, but with a deprecation
>>>> warning.
>>>>
>>>> The reason I prefer `AnyObject` to `class` is because I think it’s ugly to
>>>> have `class` as the name of an existential type. Type names are uppercase
>>>> in Swift. It is also used to compose with protocols which also use
>>>> uppercase names in Swift. Because it appears in contexts which use an
>>>> uppercase convention it makes sense for this to have an uppercase name.
>>>> `AnyObject` seems like the obvious choice if we’re going to go in that
>>>> direction.
>>>>
>>>>>
>>>>>>>
>>>>>>>>
>>>>>>>> -Joe
>>>>>>>> _______________________________________________
>>>>>>>> swift-evolution mailing list
>>>>>>>> [email protected] <mailto:[email protected]>
>>>>>>>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>>>>>>> <https://lists.swift.org/mailman/listinfo/swift-evolution>
>>>>>>> _______________________________________________
>>>>>>> swift-evolution mailing list
>>>>>>> [email protected] <mailto:[email protected]>
>>>>>>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>>>>>> <https://lists.swift.org/mailman/listinfo/swift-evolution>
>>>>>> _______________________________________________
>>>>>> swift-evolution mailing list
>>>>>> [email protected] <mailto:[email protected]>
>>>>>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>>>>> <https://lists.swift.org/mailman/listinfo/swift-evolution>
>>>
>>> _______________________________________________
>>> swift-evolution mailing list
>>> [email protected] <mailto:[email protected]>
>>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>> <https://lists.swift.org/mailman/listinfo/swift-evolution>
>>
_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution