> On Feb 20, 2017, at 4:17 PM, Jon Shier <j...@jonshier.com> wrote:
> 
> Also possibly related is the covariance in protocol requirements. The 
> following example doesn’t compile without casting the arrays or single values 
> to the exact types required in the protocols, despite being covariant through 
> protocol conformance or subclass.
> 
> protocol HasViews {
>     
>     var views: [UIView]!
>     
> }
> 
> protocol Updateable { }
> 
> extension UIView: Updateable { }
> 
> protocol HasProtocols {
>     
>     var updateables: [Updateable]!
>     
> }
> 
> class ViewController: UIViewController {
>     
>     @IBOutlet var views: [UIButton]!
>     @IBOutlet var updateables: [UIButton]!
>     
> }
> 
> extension ViewController: HasViews { } // fails without casting
> extension ViewController: HasProtocols { } // fails without casting

This kind of thing we do want to support eventually, I think.

Method overrides support a limited form of variance — you can make method 
parameters more optional in an override, or change their type to a base class; 
similarly a method return type can becomes less optional or change to a 
subclass. Overrides do not support converting to a protocol existential though.

Protocol requirements do not support variance at all, except for @objc 
protocols, which allow the same optionality changes as method overrides (but no 
class upcasts!)

This is all quite confusing to remember, and it would be great to see a 
proposal that makes the rules more general and consistent between method 
overrides in classes and protocol requirement witnesses.

Slava

> 
> 
> 
> Jon
> 
> 
>> On Feb 20, 2017, at 7:07 PM, Howard Lovatt via swift-users 
>> <swift-users@swift.org <mailto:swift-users@swift.org>> wrote:
>> 
>> It is confusing in Swift what can be covariant and what is invariant, 
>> consider:
>> 
>>     // Covarant arrays work
>>     class A {}
>>     class B: A {}
>>     let a = A() // A
>>     let b = B() // B
>>     var arrayA = [a] // Array<A>
>>     arrayA[0] = b // OK
>>     
>>     // And arrays of arrays
>>     var arrayArrayA = [arrayA] // Array<Array<A>>
>>     arrayArrayA[0][0] = b // OK
>>     let arrayB = [b] // Array<B>
>>     arrayArrayA[0] = arrayB // OK, works out that an Array<B> is a Array<A>
>>     
>>     // Covariant homebrew-collections work
>>     class C<T: AnyObject> { 
>>         var e: T
>>         init(_ e: T) { self.e = e }
>>     }
>>     var cA = C(a) // C<A>
>>     cA.e = b // OK
>>     
>>     // But not quite for homebrew-collections of homebrew-collections
>>     var cCA = C(cA) // C<C<A>>
>>     cCA.e.e = b // OK
>>     let cB = C(b) // C<B>
>>     // cCA.e = cB // Error - cannot work out that a C<B> is a C<A> but can 
>> do so for arrays
>> 
>> It is weird that the last line fails and the equivalent Array line doesn't. 
>> I suspect that there is some special typing going on for arrays, probably to 
>> make them play nice with Objective-C. However it would be simpler if 
>> everything was covariant when safe to be covariant, i.e. The last line 
>> should work.
>> 
>>  -- Howard.
>> 
>> On Mon, 20 Feb 2017 at 8:38 pm, Isaac Rivera via swift-users 
>> <swift-users@swift.org <mailto:swift-users@swift.org>> wrote:
>> I can see it is a (counter-intuitive) language design decision for type 
>> safety… but then why, in the code below I can:
>> 
>> class OtherThing: Something<UIViewController> {
>>      override func start(_ completion: SomeCallback? = nil) {
>>              // implementation details...
>>      }
>> }
>> 
>> let firstThing = OtherThing(viewController: UINavigationController())
>> 
>> OtherThing extends Something<UIViewController>… but I can instantiate it 
>> with the subtype…
>> 
>> Ok you will say, UINavigationController is a subtype of UIViewController, 
>> but that still does not make Something<UINavigationController> a subtype of 
>> Something<UIViewController>. 
>> 
>> Fair enough, but:
>> 
>> let c1: Something<UIViewController> = Something(viewController: 
>> UINavigationController())
>> // c1 is of type "Something<UIViewController>"
>> 
>> let c2 = Something(viewController: UINavigationController())
>> // c1 is of type "Something<UINavigationController>”
>> 
>> So it appears Something<UINavigationController> can be cast to type 
>> Something<UIViewController>…
>> 
>> Yet this is illegal?
>> 
>> let somethings: [Something<UIViewController>] = [c1, c2]
>> 
>> I dont know, something seems inconsistent.
>> 
>> 
>>> On Feb 16, 2017, at 10:59 PM, Slava Pestov <spes...@apple.com 
>>> <mailto:spes...@apple.com>> wrote:
>>> 
>>> Hi Isaac,
>>> 
>>> This is not about associated types. Rather, the issue is that a ‘Thing’ is 
>>> a ‘Something<UINavigationController>’, but you are casting it to 
>>> ‘Something<UIViewController>’. The two types are not related; in general, 
>>> if A is a subtype of B, then G<A> is not a subtype of G<B>.
>>> 
>>> https://en.wikipedia.org/wiki/Covariance_and_contravariance_(computer_science)
>>>  
>>> <https://en.wikipedia.org/wiki/Covariance_and_contravariance_(computer_science)>
>>> 
>>> Slava
>>> 
>>>> On Feb 16, 2017, at 9:05 AM, Isaac Rivera via swift-users 
>>>> <swift-users@swift.org <mailto:swift-users@swift.org>> wrote:
>>>> 
>>>> Hello, list!
>>>> 
>>>> I am trying to find my way around Swift’s protocol limitations. It appears 
>>>> that in general, any protocol with declared associatedtype will break 
>>>> polymorphism?
>>>> 
>>>> Take the case below which does not compile. All "Thing” instances are 
>>>> "Something<VC: UIViewController>” but they can’t be passed around or 
>>>> coerced as so.
>>>> 
>>>> How is it that I can legally write the code:
>>>> 
>>>> class Thing: Something<UINavigationController> { }
>>>> 
>>>> and instantiate it, but it is not the very thing it implements? 
>>>> 
>>>> All Thing instances conform to the public interfaces of 
>>>> Something<UIViewController> so why can’t they be recognized as such and 
>>>> coerced as such?
>>>> 
>>>> What is the work-around of this break in Polymorphism?
>>>> 
>>>> import UIKit
>>>> 
>>>> protocol Anything: class, NSObjectProtocol {
>>>>    
>>>>    associatedtype ViewControllerType: UIViewController
>>>>    
>>>>    var viewController: ViewControllerType { get }
>>>>    
>>>>    init(viewController: ViewControllerType)
>>>>    
>>>>    func addAnything(anything: Something<UIViewController>) -> Bool
>>>> }
>>>> 
>>>> class Something<VC: UIViewController>: NSObject, Anything {
>>>>    
>>>>    typealias ViewControllerType = VC
>>>>    
>>>>    private(set) var viewController: ViewControllerType
>>>>    
>>>>    required init(viewController: ViewControllerType) { self.viewController 
>>>> = viewController }
>>>>    
>>>>    final private var things = [String: Something<UIViewController>]()
>>>>    
>>>>    final internal func addAnything(anything: Something<UIViewController>) 
>>>> -> Bool {
>>>>            // implementation details...
>>>>            return true
>>>>    }
>>>> }
>>>> 
>>>> class Thing: Something<UINavigationController> { }
>>>> 
>>>> let firstThing = Thing(viewController: UINavigationController())
>>>> let secondThing = Thing(viewController: UINavigationController())
>>>> 
>>>> firstThing.addAnything(anything: secondThing)
>>>> 
>>>> // Playground execution failed: error: MyPlayground.playground:48:34: 
>>>> error: cannot convert value of type 'Thing' to expected argument type 
>>>> 'Something<UIViewController>'
>>>> 
>>>> firstThing.addAnything(anything: secondThing as 
>>>> Something<UIViewController>)
>>>> 
>>>> // Playground execution failed: error: MyPlayground.playground:48:34: 
>>>> error: cannot convert value of type 'Thing' to type 
>>>> 'Something<UIViewController>' in coercion
>>>> 
>>>> 
>>>> 
>>>> 
>>>> _______________________________________________
>>>> swift-users mailing list
>>>> swift-users@swift.org <mailto:swift-users@swift.org>
>>>> https://lists.swift.org/mailman/listinfo/swift-users 
>>>> <https://lists.swift.org/mailman/listinfo/swift-users>
>>> 
>> 
>> _______________________________________________
>> swift-users mailing list
>> swift-users@swift.org <mailto:swift-users@swift.org>
>> https://lists.swift.org/mailman/listinfo/swift-users 
>> <https://lists.swift.org/mailman/listinfo/swift-users>
>> -- 
>> -- Howard.
>> _______________________________________________
>> swift-users mailing list
>> swift-users@swift.org <mailto:swift-users@swift.org>
>> https://lists.swift.org/mailman/listinfo/swift-users
> 

_______________________________________________
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users

Reply via email to