I would like to use switch statement by matching array type. I have the following classes.
class A {}
class B : A {}
let a : A = B()
switch a {
case let b as B:
print("b = \(b)")
default:
print("unknown type")
}
let aArray : [A] = [B(), B()]
switch aArray {
case let bArray as [B] :
print("bArray = \(bArray)")
default:
print("unknown type")
}
Downcast pattern value of type '[B]' cannot be used
Note: Tested on Swift 4
In Swift 4.1, you get a better error message (thanks to #11441):
Collection downcast in cast pattern is not implemented; use an explicit downcast to '[B]' instead
In short, you're hitting a bit of the compiler that isn't fully implemented yet, the progress of which is tracked by the bug SR-5671.
You can however workaround this limitation by coercing to Any
before performing the cast:
class A {}
class B : A {}
let aArray : [A] = [B(), B()]
switch aArray /* or you could say 'as Any' here depending on the other cases */ {
case let (bArray as [B]) as Any:
print("bArray = \(bArray)")
default:
print("unknown type")
}
// bArray = [B, B]
Why does this work? Well first, a bit of background. Arrays, dictionaries and sets are treated specially by Swift's casting mechanism – despite being generic types (which are invariant by default), Swift allows you to cast between collections of different element types (see this Q&A for more info).
The functions that implement these conversions reside in the standard library (for example, Array
's implementation is here). At compile time, Swift will try to identify collection downcasts (e.g [A]
to [B]
in your example) so it can directly call the aforementioned conversion functions, and avoid having to do a full dynamic cast through the Swift runtime.
However the problem is that this specialised logic isn't implemented for collection downcasting patterns (such as in your example), so the compiler emits an error. By first coercing to Any
, we force Swift to perform a fully dynamic cast, which dispatches through the runtime, which will eventually wind up calling the aforementioned conversion functions.
Although why the compiler can't temporarily treat such casts as fully dynamic casts until the necessary specialised logic is in place, I'm not too sure.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With