-
Notifications
You must be signed in to change notification settings - Fork 10.5k
[stdlib] Fix Set/Dictionary casting issues #23683
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
- Fix Set/Dictionary up/downcasting with String keys. - Improve error handling.
@swift-ci test |
Build failed |
🤔 |
@swift-ci please test linux platform |
@swift-ci benchmark |
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.
This looks great overall (sorry for breaking part of it!). Two questions/comments, but not things that need to block merging it.
/// Insert a new element into uniquely held storage. Storage must be uniquely | ||
/// referenced with adequate capacity. If `allowingDuplicates` is false, | ||
/// `element` must not be already present in the dictionary. | ||
@_alwaysEmitIntoClient @inlinable // Introduced in 5.1 |
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.
Does this get specialized enough that the unused code path gets DCE'd if the type is known to the client? It'd be a shame to inline stuff they don't need.
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.
The flag gets folded into a constant, but the branch on it doesn't get eliminated unless the insertWithGuaranteedCapacity
call is inlined -- unfortunately it normally isn't.
In the latest commit, I reorganized the code to move the branch out of the loop, ensuring dead code elimination will trigger.
Performance: -O
Performance: -Osize
Code size: -Osize
Performance: -Onone
How to read the dataThe tables contain differences in performance which are larger than 8% and differences in code size which are larger than 1%.If you see any unexpected regressions, you should consider fixing the Noise: Sometimes the performance results (not code size!) contain false Hardware Overview
|
Is this GTM? |
@swift-ci please test |
@swift-ci benchmark |
This comment has been minimized.
This comment has been minimized.
stdlib/public/core/NativeSet.swift
Outdated
@@ -351,7 +362,7 @@ extension _NativeSet { // Insertions | |||
/// The `element` must not be already present in the Set. | |||
@inlinable | |||
internal func _unsafeInsertNew(_ element: __owned Element) { | |||
_internalInvariant(count + 1 <= capacity) |
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.
Ah, this change doesn't belong here; I'll remove it in a followup commit.
@Catfish-Man Could you please review again? The last commit replaced most of the implementation. |
This comment has been minimized.
This comment has been minimized.
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.
Love it
This comment has been minimized.
This comment has been minimized.
@swift-ci benchmark |
@swift-ci smoke test and merge |
Performance: -O
Code size: -O
Performance: -Osize
Code size: -Osize
Performance: -Onone
How to read the dataThe tables contain differences in performance which are larger than 8% and differences in code size which are larger than 1%.If you see any unexpected regressions, you should consider fixing the Noise: Sometimes the performance results (not code size!) contain false Hardware Overview
|
@swift-ci smoke test and merge |
@swift-ci smoke test linux platform |
@swift-ci please test |
This comment has been minimized.
This comment has been minimized.
Linux failure was unrelated; it's fixed on latest master. @swift-ci please test and merge |
@swift-ci test linux platform |
Build failed |
😔 @swift-ci smoke test linux platform |
@lorentey All the linux incremental bots are failing with "cannot load underlying module". But I think a clean test will work. |
@swift-ci clean test linux platform |
Build failed |
Merging. While the full tests have unrelated issues on Linux, the smoke test did pass there, too. I intend to cherry-pick this on 5.1, and we can run the tests there. |
This PR fixes
Set
/Dictionary
casts to correctly handle casting betweenString
andNSString
keys. (String
has a more permissive concept of equality thanNSString
, which can lead to duplicate entries when we convertNSString
-keyed hash tables toString
.)Bridging was fixed to handle this in the Swift 4 era, but the same issue can occur during casting between Swift-native
Set
andDictionary
types.Set
upcasts have been failing since Swift 4.2:(The trap is not guaranteed to happen immediately, or at all.)
Dictionary
upcasts worked well up to and including Swift 5.0, but since #20911, they have the same issue:These traps can also occur in downcasting situations, e.g., when casting from
NSObject
toString
keys.Additionally, this PR changes the forced-downcast code for sets and dictionaries to fail with a clear runtime error instead of a generic nil unwrap.
rdar://49444002