Without this change, the Hashable synthesizer attempts to add hash(into:) methods directly on CF types, which (somewhat unsurprisingly) fails with assertion below. (This situation is unique to CF types, which are imported with an implicit _CFObject conformance; we usually have an extension context or a non-imported type decl in which to put the derived methods.)
Assertion failed: (!decl->isForeign() && "Use getForeignMetadataLayout()"), function getClassMetadataLayout, file /Users/klorentey/Swift/swift/lib/IRGen/MetadataLayout.cpp, line 83.
0 swift 0x000000010ccd29c8 llvm::sys::PrintStackTrace(llvm::raw_ostream&) + 40
1 swift 0x000000010ccd30d6 SignalHandler(int) + 694
2 libsystem_platform.dylib 0x00007fff600e0d9a _sigtramp + 26
3 swift 0x000000010e04f1ed cmark_strbuf__initbuf + 122440
4 libsystem_c.dylib 0x00007fff5ffa6f79 abort + 127
5 libsystem_c.dylib 0x00007fff5ff6f090 basename_r + 0
6 swift 0x00000001096e8f95 swift::irgen::IRGenModule::getClassMetadataLayout(swift::ClassDecl*) + 53
7 swift 0x00000001095b9e25 swift::irgen::emitVirtualMethodValue(swift::irgen::IRGenFunction&, llvm::Value*, swift::SILDeclRef, swift::CanTypeWrapper<swift::SILFunctionType>) + 133
8 swift 0x00000001095ba252 swift::irgen::emitVirtualMethodValue(swift::irgen::IRGenFunction&, llvm::Value*, swift::SILType, swift::SILDeclRef, swift::CanTypeWrapper<swift::SILFunctionType>, bool) + 690
9 swift 0x00000001096bef49 swift::SILInstructionVisitor<(anonymous namespace)::IRGenSILFunction, void>::visit(swift::SILInstruction*) + 33497
10 swift 0x00000001096b3067 swift::irgen::IRGenModule::emitSILFunction(swift::SILFunction*) + 8055
11 swift 0x00000001095c8d8b swift::irgen::IRGenerator::emitLazyDefinitions() + 1051
12 swift 0x000000010968eb16 performIRGeneration(swift::IRGenOptions&, swift::ModuleDecl*, std::__1::unique_ptr<swift::SILModule, std::__1::default_delete<swift::SILModule> >, llvm::StringRef, swift::PrimarySpecificPaths const&, llvm::LLVMContext&, swift::SourceFile*, llvm::GlobalVariable**, unsigned int) + 1382
13 swift 0x000000010968f05e swift::performIRGeneration(swift::IRGenOptions&, swift::SourceFile&, std::__1::unique_ptr<swift::SILModule, std::__1::default_delete<swift::SILModule> >, llvm::StringRef, swift::PrimarySpecificPaths const&, llvm::LLVMContext&, unsigned int, llvm::GlobalVariable**) + 94
14 swift 0x000000010952cfc0 performCompile(swift::CompilerInstance&, swift::CompilerInvocation&, llvm::ArrayRef<char const*>, int&, swift::FrontendObserver*, swift::UnifiedStatsReporter*) + 15488
15 swift 0x0000000109528332 swift::performFrontend(llvm::ArrayRef<char const*>, char const*, void*, swift::FrontendObserver*) + 2962
16 swift 0x00000001094e4848 main + 2328
17 libdyld.dylib 0x00007fff5feecc41 start + 1
Stack dump:
[…]
1. While emitting IR SIL function "@$SSo10CGColorRefas8HashableSCsACP4hash4intoys6HasherVz_tFTW".
for 'hash(into:)' in module 'CoreGraphics'
Like NSObject, CFType has primitive operations CFEqual and CFHash,
so Swift should allow those types to show up in Hashable positions
(like dictionaries). The most general way to do this was to
introduce a new protocol, _CFObject, and then have the importer
automatically make all CF types conform to it.
This did require one additional change: the == implementation that
calls through to CFEqual is in a new CoreFoundation overlay, but the
conformance is in the underlying Clang module. Therefore, operator
lookup for conformances has been changed to look in the overlay for
an imported declaration (if there is one).
This re-applies 361ab62454, reverted in
f50b1e73dc, after a /very/ long interval
where we decided if it was worth breaking people who've added these
conformances on their own. Since the workaround isn't too difficult---
use `#if swift(>=3.2)` to guard the extension introducing the
conformance---it was deemed acceptable.
https://bugs.swift.org/browse/SR-2388
Like NSObject, CFType has primitive operations CFEqual and CFHash,
so Swift should allow those types to show up in Hashable positions
(like dictionaries). The most general way to do this was to
introduce a new protocol, _CFObject, and then have the importer
automatically make all CF types conform to it.
This did require one additional change: the == implementation that
calls through to CFEqual is in a new CoreFoundation overlay, but the
conformance is in the underlying Clang module. Therefore, operator
lookup for conformances has been changed to look in the overlay for
an imported declaration (if there is one).
https://bugs.swift.org/browse/SR-2388