[swift-evolution] Subclass Existentials

Xiaodi Wu xiaodi.wu at gmail.com
Sun Jan 29 12:13:52 CST 2017


As Matthew mentioned, the rules can certainly later be relaxed, but given
that this proposal has the compiler generating fix-its for subclasses in
second position, is there a reason other than stylistic for demanding
MyClass & MyProtocol instead of MyProtocol & MyClass?

>From a naive perspective, it seems that if the compiler understands my
meaning perfectly, it should just accept that spelling rather than complain.
On Sun, Jan 29, 2017 at 11:30 Matthew Johnson via swift-evolution <
swift-evolution at swift.org> wrote:

> Hi David,
>
> This looks like a great start.
>
> One thing we should consider is whether we tie this proposal so tightly to
> classes or whether it might be better to call these supertype constraints.
> The feature might also be useful for value types if / when Swift gets value
> subtyping.
>
> One enhancement that might be worth considering.  Specifically, allowing
> protocols to declare a specific supertype requirement in the place where a
> `class` constraint would usually be found.  After this proposal we could
> already do something similar using a `class` constraint to define a
> protocol and a typealias to bind it to the supertype requirement.  It seems
> like allowing users to state this more directly would be a good idea.
>
> As only the first element in the existential composition syntax can be a
> class type, and by extending this rule to typealias expansions, we can make
> sure that we only need to read the first element to know if it contains a
> class requirement.
>
> I think this is unnecessarily limiting in a couple of ways.  I agree that
> a class should come first if it is mentioned explicitly***.  I am less sure
> we should require this when the type is part of a typealias combined with
> other protocol requirements.
>
> For example, one use case I remember discussing with Austin is refining
> supertype requirements.  If I have a typealias which requires a superclass
> `Base` I should be able to form an existential using that typealias that
> *refines* that requirement to some type *Derived* which is a non-final
> subtype of `Base`.  This would require syntax that allows us to put a class
> name in the first position, but also mention a typealias with a supertype
> requirement in a subsequent position.
>
> Matthew
>
> *** One argument against requiring a class to come first is that we could
> conceptualize `&` as a type operator with a handful of overloads.  This
> would include both lhs and rhs are “protocol only kinds” as well as
> overloads with a “protocol only kind” in either lhs or rhs and a “supertype
> kind” in the other position.  The tricky part of pulling this off would be
> including an overload where both lhs and rhs have a “supertype kind”, but
> only when the operands have a subtype / supertype relationship with each
> other.
>
> I suspect this conceptualization isn’t worth the complexity it brings, but
> it is tempting to try and view `&` as a type operator.  As long as this
> only involves a loosening of restrictions it could probably be introduced
> as an additive change down the road.
>
> On Jan 29, 2017, at 10:39 AM, David Hart <david at hartbit.com> wrote:
>
> Hello,
>
> As promised, I wrote the first draft of a proposal to add class
> requirements to the existential syntax. Please let me know what you think.
>
>
> https://github.com/hartbit/swift-evolution/blob/subclass-existentials/proposals/XXXX-subclass-existentials.md
>
> Regards,
> David.
>
> Existentials for classes conforming to protocols
>
>    - 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/proposals#introduction>
> Introduction
>
> This proposal brings more expressive power to the type system by allowing
> Swift to represent existentials of classes and subclasses which conform to
> protocols.
>
> <https://github.com/hartbit/swift-evolution/tree/subclass-existentials/proposals#motivation>
> Motivation
>
> Currently, the only existentials which can be represented in Swift are
> conformances to a set of protocols, using the &syntax:
>
> let existential: Hashable & CustomStringConvertible
>
> On the other hand, Objective-C is capable of expressing existentials of
> subclasses conforming to protocols with the following syntax:
>
> UIViewController<UITableViewDataSource, UITableViewDelegate>* existential;
>
> 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/proposals#proposed-solution>Proposed
> solution
>
> The proposal keeps the existing & syntax but allows the first element,
> and only the first, to be of class type. The equivalent declaration to the
> above Objective-C declaration would look like this:
>
> let existential: UIViewController & UITableViewDataSource & UITableViewDelegate
>
> As in Objective-C, this existential represents classes which have
> UIViewController in their parent inheritance hierarchy and which also
> conform to the UITableViewDataSource and UITableViewDelegate protocols.
>
> As only the first element in the existential composition syntax can be a
> class type, and by extending this rule to typealias expansions, we can make
> sure that we only need to read the first element to know if it contains a
> class requirement. As a consequence, here is a list of valid and invalid
> code and the reasons for them:
>
> let a: Hashable & CustomStringConvertible// VALID: This is still valid, as beforelet b: MyObject & Hashable// VALID: This is the new rule which allows an object type in first positionlet c: CustomStringConvertible & MyObject// INVALID: MyObject is not allowed in second position. A fix-it should help transform it to:// let c: MyObject & CustomStringConvertibletypealias MyObjectStringConvertible = MyObject & CustomStringConvertiblelet d: Hashable & MyObjectStringConvertible// INVALID: The typealias expansion means that the type of d expands to Hashable & MyObject & CustomStringConvertible, which has the class in the wrong position. A fix-it should help transform it to:// let d: MyObjectStringConvertible & Hashabletypealias MyObjectStringConvertible = MyObject & CustomStringConvertiblelet e: MyOtherObject & MyObjectStringConvertible// INVALID: The typealias expansion would allow an existential with two class requirements, which is invalid
>
> The following examples could technically be legal, but we believe we
> should keep them invalid to keep the rules simple:
>
> let a: MyObject & MyObject & CustomStringConvertible// This is equivalent to MyObject & CustomStringConvertiblelet b: MyObjectSubclass & MyObject & Hashable// This is equivalent to MyObjectSubclass & Hashabletypealias MyObjectStringConvertible = MyObject & CustomStringConvertiblelet d: MyObject & MyObjectStringConvertible// This is equivalent to MyObject & CustomStringConvertible
>
>
> <https://github.com/hartbit/swift-evolution/tree/subclass-existentials/proposals#source-compatibility>Source
> compatibility
>
> This is a source breaking change. All types bridged from Objective-C which
> use the equivalent Objective-C feature import without the protocol
> conformances in Swift 3. This change would increase the existential's
> requirement and break on 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 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 would have worked as long as the Objective-C code did
> not call any method of UITableViewDataSource or UITableViewDelegate. But
> if this proposal is accepted and implemented as-is, the Objective-C code
> would now be imported as:
>
> class MyViewController {
>     func setup(tableViewController: UIViewController & UITableViewDataSource & UITableViewDelegate) {}
> }
>
> That would then cause the Swift code to fail to compile with an error
> which states that UIViewController does not conform to the
> UITableViewDataSource and UITableViewDelegate protocols.
>
> It is a source-breaking change, but should have a minimal impact for the
> following reasons:
>
>    - Not many Objective-C code used the existential syntax in practice.
>    - There generated errors are a good thing because they point out
>    potential crashes which would have gone un-noticed.
>
>
> <https://github.com/hartbit/swift-evolution/tree/subclass-existentials/proposals#alternatives-considered>Alternatives
> considered
>
> None.
>
> <https://github.com/hartbit/swift-evolution/tree/subclass-existentials/proposals#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.
>
>
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20170129/4c6b1254/attachment.html>


More information about the swift-evolution mailing list