Swift 2.1: Casting an array from an Any to that array requires 2 casts instead of the expected one to successfully work
| Originator: | amayers13 | ||
| Number: | rdar://23741928 | Date Originated: | 12/03/15 |
| Status: | Open | Resolved: | false |
| Product: | Developer Tools | Product Version: | Xcode 7.1.1 / Swift 2.1 |
| Classification: | Other Bug | Reproducible: | Always |
Summary:
In Swift 2.1 casting an array of objects of some class that actually contain objects of a subclass to an Any and then to an Array<Subclass> fails, when casting from an Any to an Array<SomeClass> then another cast to Array<Subclass> succeeds. There doesn’t seem to be any reason for this behavior. Any cast that can work by doing intermediate casts should work when you skip the intermediate cast.
Steps to Reproduce:
Easiest way is to download the attached playground, but…
1) create 2 classes (structs will work also): class BaseModel { required init() {} }, and class SubclassModel: BaseModel { required init() {} }
2) create an array: var baseArray = [BaseModel]()
3) put subclass models in the array: baseArray.append(SubclassModel())
4) cast baseArray to an Any?: let anyArray = baseArray as Any?
5) later try to cast the anyArray to an array of SubclassModels: let expectedCastArray = anyArray as? [SubclassModel]
Expected Results:
The result of step 5 would be expectedCastArray that is not nil, and who’s dynamicType == Array<SubclassModel>.type.
Actual Results:
The result of step 5: expectedCastArray == nil :(.
Regression:
This was working on Swift previously, but since you are tying Swift versions to Xcode versions, there isn’t an easy way of setting which Swift version to compile with. Perhaps you should fix that too, and make Swift versions selectable in Xcode.
Notes:
As a workaround you can do let intermediateCast = anyArray as? [BaseModel], then let finalCastArray = intermediateCast as? [SubclassModel]. However I can’t see why a cast should ever fail if that same cast can be achieved by doing 1 intermediate cast. Also this type of casting setup works fine if you aren’t casting an Array:
let subclass: BaseModel = SubclassModel()
let any = subclass as Any?
let expectedCastArray = any as? SubclassModel // This works as expected in a single cast, not needing an intermediate cast to BaseModel
Comments
Please note: Reports posted here will not necessarily be seen by Apple. All problems should be submitted at bugreport.apple.com before they are posted here. Please only post information for Radars that you have filed yourself, and please do not include Apple confidential information in your posts. Thank you!