Description
I recently ran into a backtrace where one modules tries to pass a UIControl.State as a Dictionary hash across module boundaries. In one module there is a extension UIControl.State: Hashable {}
and the call to the init method looks like:
public extension Button {
convenience init(
action: ActionWith<UIEvent>,
titles: [UIControl.State: String] = [:],
titleColors: [UIControl.State: UIColor] = [:],
When compiling this swiftc hits a report_fatal_error conformance crash in external/swift/lib/SILGen/SILGenLazyConformance.cpp due to an invalid conformance. It turns out if you copy the extension UIControl.State: Hashable {}
line to the calling module this goes away and this happens because the names for the UIControlState are mangled differently for C++-Interop versus not and the conformance is not loaded and mapped consistently. This issue disappears of both modules are compiled with C++-Interop.
Repro:
echo "import Foundation; import UIKit; extension UIControl.State: Hashable {}" | \
/Applications/Xcode-beta.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swiftc \
-sdk /Applications/Xcode-beta.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk \
-target arm64-apple-ios12.0 -c \
-cxx-interoperability-mode=swift-5.9 \
- -o out.o; \
nm out.o | \
grep -i "uicontrol.*state.*hash"
Result With C++Interop:
00000000000001ac T _$sSo9UIControlC5StateVSH3outSH13_rawHashValue4seedS2i_tFTW
0000000000000168 T _$sSo9UIControlC5StateVSH3outSH4hash4intoys6HasherVz_tFTW
000000000000012c T _$sSo9UIControlC5StateVSH3outSH9hashValueSivgTW
Result Without C++-Interop
00000000000001ac T _$sSo14UIControlStateVSH3outSH13_rawHashValue4seedS2i_tFTW
0000000000000168 T _$sSo14UIControlStateVSH3outSH4hash4intoys6HasherVz_tFTW
000000000000012c T _$sSo14UIControlStateVSH3outSH9hashValueSivgTW
I mostly file this issue for tracking, I am working on a fix. Since this issue disappears if all modules are compiled with C++-Interop then I think we can skip the Swift 5.9 must-fix queue.