[swift-users] returning an array of Protocol-conforming objects from a function

Austin Zheng austinzheng at gmail.com
Mon Jan 25 21:58:05 CST 2016


I'm reasonably sure Arrays and other collections are covariant, but any user-defined generic type is invariant. This came up in the discussion about making all generics covariant by default.

For some reason this works for me:

protocol MyProtocol {}
extension Float: MyProtocol {}

func foo() -> [MyProtocol] {
  let a = [Float(1), Float(2)] as [MyProtocol]
  return a
}

but this doesn't (with or without the cast):

func foo() -> [MyProtocol] {
  let a = [Float(1), Float(2)] //as [Float]
  return a as [MyProtocol]
}

Nor does this:

func foo() -> [MyProtocol] {
  let a = [Float(1), Float(2)] as [Float]
  let b = a as [MyProtocol]
  return b
}

This definitely looks like a bug, or at least something that needs a better compiler error message. (I'm running this in an OS X Xcode project with Swift 2.1, but it doesn't work with Swift 2.2 either.)

Best,
Austin

> On Jan 25, 2016, at 7:51 PM, Trent Nadeau <tanadeau at gmail.com> wrote:
> 
> I think arrays along with other generics are invariant.
> 
> On Mon, Jan 25, 2016 at 10:50 PM, Trent Nadeau <tanadeau at gmail.com <mailto:tanadeau at gmail.com>> wrote:
> That code works fine for me if I change the cast to "as [MyProtocol]".
> 
> protocol MyProtocol {}
> 
> struct Blah : MyProtocol { }
> 
> func foo() -> [MyProtocol] {
>   let a = [Blah(), Blah()] as [MyProtocol]
>   return a
> }
> 
> On Mon, Jan 25, 2016 at 10:47 PM, Austin Zheng via swift-users <swift-users at swift.org <mailto:swift-users at swift.org>> wrote:
> Hi Ryan,
> 
> Are you sure it works with user-defined struct types? I tried the following code, and got the same error:
> 
> protocol MyProtocol {}
> 
> struct Blah : MyProtocol { }
> 
> func foo() -> [MyProtocol] {
>   let a = [Blah(), Blah()] as [Blah]
>   return a
> }
> 
> 'class Blah' works fine.
> 
> Even so, this is not the behavior I would have expected. Perhaps someone else can explain why [T] can't be upcasted to [P] when T is a struct and T : P.
> 
> Best,
> Austin
> 
> 
>> On Jan 25, 2016, at 7:36 PM, Ryan Walklin via swift-users <swift-users at swift.org <mailto:swift-users at swift.org>> wrote:
>> 
>> Hi All,
>> 
>> I have a function which returns a closure, which then returns an array of objects conforming to a protocol. 
>> 
>> ie. 
>> 
>> protocol MyProtocol {}
>> 
>> extension Float: MyProtocol {}
>> extension OtherType: MyProtocol {}
>> 
>> When I try to return an array of Floats, I get the error “Cannot convert value of type '[Float]' to closure result type ‘[MyProtocol]”.
>> 
>> Other struct-based types work fine.
>> 
>> Is this not possible with standard library types?
>> 
>> Regards,
>> 
>> Ryan
>> _______________________________________________
>> swift-users mailing list
>> swift-users at swift.org <mailto:swift-users at swift.org>
>> https://lists.swift.org/mailman/listinfo/swift-users <https://lists.swift.org/mailman/listinfo/swift-users>
> 
> 
> _______________________________________________
> swift-users mailing list
> swift-users at swift.org <mailto:swift-users at swift.org>
> https://lists.swift.org/mailman/listinfo/swift-users <https://lists.swift.org/mailman/listinfo/swift-users>
> 
> 
> 
> 
> -- 
> Trent Nadeau
> 
> 
> 
> -- 
> Trent Nadeau

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-users/attachments/20160125/c7c9db16/attachment.html>


More information about the swift-users mailing list