0

Given the following code:

struct Foo<T> {
    let value: T
}

let bar: Foo<Any> = Foo<Bool>(value: true) // ERROR

I get the following error:

Cannot convert value of type 'Foo' to specified type 'Foo'

With a slight adjustment to this code:

struct Foo<T> {
    let value: T
}

let bar = Foo<Any>(value: true)
print(bar as? Foo<Bool>) // WARNING

I get this warning:

Cast from 'Foo' to unrelated type 'Foo' always fails

Why do I get this error? These two types seem to be related to each other considering the type of Bool can, in fact, be converted to Any as shown in the following example:

let bar: Any = Bool(true)

While this example could be solved by removing out the specified type,

let bar = Foo<Bool>(value: true)
let bar: Foo<Any> = Foo(value: true)

This does not give me the results I want as either Foo.value or bar are the wrong type.

Given a more complex situation where the type must be explicitly specified this solution does not work. Could anyone help explain why this is happening and provide a solution?

grahamcracker1234
  • 591
  • 1
  • 7
  • 27
  • Could it be that you cannot change the value type because `value` is a `let` constant? – Daniel Mar 05 '19 at 16:46
  • 3
    Generics (and all languages I can think of) are not covariant. `Foo` is not a subtype of `Foo`, even if `B` is a subtype of `A`. – Alexander Mar 05 '19 at 16:49
  • @Alexander In Scala, you can express covariance (and contravariance) in generics. Some day you may be able to do the same in Swift. (But as you say, today they are not covariant.) – Rob Napier Mar 05 '19 at 16:52
  • @RobNapier Oh cool, I'll have to look into that! – Alexander Mar 05 '19 at 16:52
  • @Alexander Take a look at https://stackoverflow.com/questions/663254/why-doesnt-the-example-compile-aka-how-does-co-contra-and-in-variance-w for a quick intro for how Scala does it. But as a rule, it cannot work with mutable data, so it would likely be much more limited in Swift even if added. – Rob Napier Mar 05 '19 at 16:53

0 Answers0