[swift-users] question about covariant subtyping
Michael Roitzsch
reactorcontrol at icloud.com
Wed Feb 22 10:50:46 CST 2017
Hi all,
I am fairly new to Swift, so this may very well be a simple misunderstanding on my part.
I was exploring the subtyping rules of Swift, especially regarding covariance. I came across two examples where the outcome puzzles me and I would appreciate if someone could explain this to me.
First I tried the covariance for the standard container types. Here is an excerpt from a REPL session:
Michael at carpo:~ > swift
Welcome to Apple Swift version 3.0.2 (swiftlang-800.0.63 clang-800.0.42.1). Type :help for assistance.
1> open class Super {}; class Sub: Super {}
2> print([Sub()] is [Sub])
true
3> print([Sub()] is [Super])
true
4> print(Array<Sub>(arrayLiteral: Sub()) is [Sub])
true
5> print(Array<Sub>(arrayLiteral: Sub()) is [Super])
error: repl.swift:5:39: error: 'Super' is not a subtype of 'Sub'
print(Array<Sub>(arrayLiteral: Sub()) is [Super])
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~
Why does it matter for subtyping against [Super] whether I express an array as [Sub] or Array<Sub>(arrayLiteral: Sub())?
Then I tried combining array covariance with function argument type contravariance:
Michael at carpo:~ > swift
Welcome to Apple Swift version 3.0.2 (swiftlang-800.0.63 clang-800.0.42.1). Type :help for assistance.
1> open class Super {}; class Sub: Super {}
2> func f(_: [Super]) {}
3> let test: ([Sub]) -> Void = f
error: repl.swift:3:29: error: cannot convert value of type '([Super]) -> ()' to specified type '([Sub]) -> Void'
let test: ([Sub]) -> Void = f
^
Why is this assignment not possible? It works fine (as expected) when using plain Super and Sub instead of arrays.
Michael
More information about the swift-users
mailing list