-
Notifications
You must be signed in to change notification settings - Fork 10.4k
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
🛑Compiler support for synthesizing Hashable._hash(into:) #15122
Closed
Closed
Conversation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This is currently blocked by SR-7156; in particular, vtable problems cause issues in swift-corelibs-foundation. |
@swift-ci smoke test |
Hashable._hash(into:)
Hashable._hash(into:)
Hashable._hash(into:)
@swift-ci smoke test |
@swift-ci please smoke test Linux |
This removes the default implementation of _hash(into:), and replaces it with automatic synthesis built into the compiler. Hashable can now be implemented by defining either hashValue or _hash(into:) -- the compiler supplies the missing half automatically, in all cases. To determine which _hash(into:) implementation to generate, the synthesizer resolves hashValue -- if it finds a synthesized definition for it, the generated _hash(into:) body implements hashing from scratch, feeding components into the hasher. Otherwise, the body implements _hash(into:) in terms of hashValue. # Conflicts: # lib/Sema/DerivedConformances.cpp
…into:) 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/lorentey/Swift/swift/lib/IRGen/MetadataLayout.cpp, line 86. 0 swift 0x0000000108e28b08 llvm::sys::PrintStackTrace(llvm::raw_ostream&) + 40 1 swift 0x0000000108e29216 SignalHandler(int) + 694 2 libsystem_platform.dylib 0x00007fff587aef5a _sigtramp + 26 3 libsystem_platform.dylib 0x0000000000003628 _sigtramp + 2810529512 4 libsystem_c.dylib 0x00007fff585571ae abort + 127 5 libsystem_c.dylib 0x00007fff5851f1ac basename_r + 0 6 swift 0x0000000105a2a460 swift::irgen::IRGenModule::getClassMetadataLayout(swift::ClassDecl*) + 96 7 swift 0x0000000105970dc8 swift::irgen::emitVirtualMethodValue(swift::irgen::IRGenFunction&, llvm::Value*, swift::SILDeclRef, swift::CanTypeWrapper<swift::SILFunctionType>) + 184 8 swift 0x000000010597121d swift::irgen::emitVirtualMethodValue(swift::irgen::IRGenFunction&, llvm::Value*, swift::SILType, swift::SILDeclRef, swift::CanTypeWrapper<swift::SILFunctionType>, bool) + 685 9 swift 0x0000000105a01482 swift::SILInstructionVisitor<(anonymous namespace)::IRGenSILFunction, void>::visit(swift::SILInstruction*) + 36562 10 swift 0x00000001059f4e4f (anonymous namespace)::IRGenSILFunction::emitSILFunction() + 6863 11 swift 0x00000001059f2e1b swift::irgen::IRGenModule::emitSILFunction(swift::SILFunction*) + 1371 12 swift 0x00000001058fccab swift::irgen::IRGenerator::emitLazyDefinitions() + 1051 13 swift 0x00000001059cf676 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) + 1366 14 swift 0x00000001059cfc5e 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 15 swift 0x000000010586d2a9 performCompile(swift::CompilerInstance&, swift::CompilerInvocation&, llvm::ArrayRef<char const*>, int&, swift::FrontendObserver*, swift::UnifiedStatsReporter*) + 15337 16 swift 0x0000000105868715 swift::performFrontend(llvm::ArrayRef<char const*>, char const*, void*, swift::FrontendObserver*) + 2869 17 swift 0x000000010581f300 main + 2832 18 libdyld.dylib 0x00007fff584ab015 start + 1
# Conflicts: # test/Sema/enum_conformance_synthesis.swift
_hash(into:) needs to be included in expectations; tests looking at synthesized Hashable implementation bodies need to be updated for resilient hashing. # Conflicts: # test/IDE/complete_enum_elements.swift
fd770da
to
05601da
Compare
Also rename Hasher.append() to Hasher.combine(). Hasher’s API is still incomplete: it currently only supports combining 32-bit and 64-bit values.
@lorentey I didn't realize the Codable vtable bug was blocking this work. I'll take a look at it soon. |
This is now incorporated into and superseded by #16073. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Labels
swift evolution approved
Flag → feature: A feature that was approved through the Swift evolution process
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
This improves compiler support for synthesizing
Hashable
implementations, to make use of the resilient hashing interface introduced by #14913. It removes the default implementation of_hash(into:)
; the requirement is now automatically synthesized as needed.Fully synthesized implementations of
Hashable
now generate a_hash(into:)
implementation that does the actual work of hashing a type's components. They also add ahashValue
implementation that simply instantiates a new hasher and feeds it to_hash(into:)
. For example, here is howHashable
conformance is derived for a simple struct:This also enables partial synthesis: when exactly one of
hashValue
or_hash(into:)
was explicitly provided, the compiler automatically synthesizes the other requirement. This works in all cases whereHashable
conformance can be implemented: in structs, enums, classes or extensions.