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 < [email protected]> 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 <[email protected]> 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 > [email protected] > https://lists.swift.org/mailman/listinfo/swift-evolution >
_______________________________________________ swift-evolution mailing list [email protected] https://lists.swift.org/mailman/listinfo/swift-evolution
