New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[SR-7738] Empty array type casting always succeeds #3699
Comments
Comment by Romain Vincens (JIRA) What's even stranger is that if you try to cast to a concrete type (not a protocol) you get a compiler warning but it runs and behaves incorrectly if let myArray = myArray as? [Int] {
print("Type casting succeeded")
} else {
print("Type casting failed")
} --> «Cast from '[Foo]' to unrelated type '[Int]' always fails» And you get the «Type casting succeeded» output |
Related: SR-6192 |
Comment by Romain Vincens (JIRA) Even though it's counter-intuitive I could accept that an empty array of something can be cast in any kind of array with unrelated type. However it can cause crashes if we're using KVC when mix and matching with ObjC, even though we have a fence on the array being of type `[Identifiable]` import Foundation
protocol Identifiable {
var `id`: String { get set }
}
protocol Base { }
@objc
class Foo: NSObject, Base { }
@objc
class Bar: NSObject, Base, Identifiable {
@objc var id: String
init(id: String) {
self.id = id
}
}
class Receiver<O: Base> {
let store: [O]
init(store: [O]) {
self.store = store
}
@discardableResult
func filterOut(_ objects: [O]) -> [O] {
if let objects = objects as? [Identifiable] {
let objectIds = objects.compactMap { $0.id }
let predicate = NSPredicate(format: "NOT (id IN %@)", objectIds)
let filtered = store.filter {
predicate.evaluate(with: $0)
}
return filtered
} else {
return store
}
}
}
let barReceiver = Receiver(store: [Bar(id: "toto"), Bar(id: "tutu")])
print(barReceiver.filterOut([Bar(id: "toto")])) // [<Toto.Bar: 0x608000038540>]
print(barReceiver.filterOut([])) // [<Toto.Bar: 0x608000036920>, <Toto.Bar: 0x608000038540>]
let fooReceiver = Receiver(store: [Foo(), Foo()])
print(fooReceiver.filterOut([Foo()])) // [<Toto.Foo: 0x60400001c8e0>, <Toto.Foo: 0x60400001c8d0>]
print(fooReceiver.filterOut([])) // CRASH -> `Foo` is not KVC compliant with `id` It's an example. The code is not very logical since we should check that `store` can be cast to `[Identifiable]` instead of the passed-in objects (that we only use for ids), but it's an example. Things like this can happen. |
Fixed on master romrom (JIRA User) can you please test using the next available snapshot and close. Thanks |
Environment
Tested in Xcode 9.3 / Swift 4.1
Additional Detail from JIRA
md5: 419ef5984a76850c45061699b14d3f04
relates to:
Issue Description:
Given the following snippet
I get "Type casting succeeded" and I'm expecting the opposite.
The array is empty, however if we declare it with at least one element, like so
I get the expected behavior.
Trying to cast an empty array, whatever its type declaration is, to an array of any kind always succeeds.
Either it's a bug, or something I don't get because it is very counter-intuitive. For now my only workaround is to check for emptiness of the array
The text was updated successfully, but these errors were encountered: