-
Notifications
You must be signed in to change notification settings - Fork 10.5k
Make SwiftValue hash/equality work the same as SwiftObject #69618
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
Conversation
Update PR swiftlang#68720 with lessons learned in reviewing swiftlang#69464 Background: * SwiftValue can expose Swift value types (structs/enums) to ObjC by wrapping them in an Obj-C object on the heap * SwiftObject is the Obj-C type that Swift class objects all inherit from (when viewed from Obj-C). This allows arbitrary Swift class objects to be passed into Obj-C. History: * PR swiftlang#4124 made Obj-C `-hash` and `-isEqual:` work for SwiftValue for Hashable Swift types * PR swiftlang#68720 extended SwiftValue to also support Equatable Swift types * PR swiftlang#69464 added similar support to SwiftObject In the process of working through swiftlang#69464, we found a better way to handle an ObjC request for `-hash` for a type that is Swift Equatable but not Hashable. This PR updates SwiftValue to use the same approach. The approach considers three cases: 1. A Hashable type can forward both `-hash` and `-isEqual:` to the Swift object. 2. A type that is neither Equatable nor Hashable can implement `-isEqual:` as the identity check and `-hash` as returning the address of the object in memory. 3. A type is that Equatable but not Hashable is more complex. In this last case, we can easily forward `-isEqual:` to the Equatable conformance but ObjC also requires us to always provide a compatible `-hash` implementation. The only way to do this is to have `-hash` return a constant, but that is a very bad idea in general, so we're also including a log message whenever we see a request for `-hash` on a Swift value that is Equatable but not Hashable. To limit performance problems from the logging itself, we emit the log message only once for each type.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems like a good change. I did wonder briefly whether it should be a fatal error to send -hash
to a Swift object that is Equatable
but not Hashable
, but I think on balance the warning approach makes sense.
@swift-ci please test |
This entire suite was copied wholesale from SwiftObjectNSObject. Some of it may not apply, very little of it has been critically evaluated. But it should help avoid unexpected changes in SwiftValue behavior.
The overly-expansive SwiftValueNSObject test suite had a few cases that aren't really ready. I commented those out. |
@swift-ci Please test |
@swift-ci Please test Windows platform |
@swift-ci Please test Windows |
1 similar comment
@swift-ci Please test Windows |
TL;DR: Update PR #68720 with lessons learned in reviewing #69464
Background:
SwiftValue can expose Swift value types (structs/enums) to ObjC by wrapping them in an Obj-C object on the heap
SwiftObject is the Obj-C type that Swift class objects all inherit from (when viewed from Obj-C). This allows arbitrary Swift class objects to be passed into Obj-C.
History:
PR stdlib and runtime: a bunch of fixes for AnyHashable and id-as-Any #4124 made Obj-C
-hash
and-isEqual:
work for SwiftValue for Hashable Swift typesPR Make ObjC isEqual: delegate to Equatable when Hashable isn't available #68720 extended SwiftValue to also support Equatable Swift types
PR Use Swift Equatable and Hashable conformances from ObjC #69464 added similar support to SwiftObject
In the process of working through #69464, we found a better way to handle an ObjC request for
-hash
for a type that is Swift Equatable but not Hashable. This PR updates SwiftValue to use the same approach. The approach considers three cases:A Hashable type can forward both
-hash
and-isEqual:
to the Swift object.A type that is neither Equatable nor Hashable can implement
-isEqual:
as the identity check and-hash
as returning the address of the object in memory.A type is that Equatable but not Hashable is more complex.
In this last case, we can easily forward
-isEqual:
to the Equatable conformance but ObjC also requires us to always provide a compatible-hash
implementation. The only way to do this is to have-hash
return a constant, but that is a very bad idea in general, so we're also including a log message whenever we see a request for-hash
on a Swift value that is Equatable but not Hashable.To limit performance problems from the logging itself, we emit the log message only once for each type.
Testing: I copied the fairly extensive SwiftObjectNSObject test suite over as SwiftValueNSObject in order to verify the new behaviors and help guard against future regressions.