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-7934] Hashable changes result in shifting behavior between Swift 4.1 and Swift 4.2 #50469
Comments
Yeah, I don't think it was ever safe to rely on |
We noticed during the development of SE-0194 that some sources have suggested using the hashValue to access the discriminator and even discussed casting hashValues back to the enum type using `unsafeBitCast(_:to🙂`. The more responsible sources warned that this was an implementation detail and shouldn't actually be used. For instance, Erica Sadun said:
SE-0194 handles this use case in a supported way, and for backwards compatibility users can provide an explicit `allCases` array. Personally, I think people had enough warning that they shouldn't do this in production. |
Jordan & Brent are correct; Swift documentation has always been careful to point out that the The case enumerator code relies on unstable implementation details on multiple levels – it's extremely clever, but it's much too fragile to expect it to keep working across compiler releases. Here is a (probably partial) list of its assumptions:
"Fixing" the original code to work with Swift 4.2 can be done by a one-line change; however, I highly, highly recommend switching to the new |
I'm closing this with Won't Do; the original code is using a number of overly fragile constructs that rely on unsafe assumptions about the compiler and the standard library – unfortunately it could never be expected to keep working for more than a few compiler releases. We recommend existing code that incorporates this code snippet to be updated to use |
Attachment: Download
Additional Detail from JIRA
md5: b235e0139b72a163f9bf4f9006d850ef
Issue Description:
Preface: I'm totally aware that this code is using undefined behavior and honestly I was surprised it ever worked. That being said, I figured I'd open up a bug in the off-chance this was indicative of a larger breaking change, or if this change wasn't known/intended.
In Swift 4.0 and 4.1, we were able to define a function that, given a type that conforming to
Hashable
andRawRepresentable
, could return an array containing all of the cases of that type. This served as a hacky custom implementation of what 4.2 ships withCaseIterable
.When running this same code in Swift 4.2, even in compatibility mode, the behavior of the hashing algorithm seems to change, and so this code starts returning an empty array.
I've attached a playground that includes the code to reproduce the change. You can flip between toolsets and see that small assertion pass/fail accordingly.
The text was updated successfully, but these errors were encountered: