Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 23c1b24

Browse files
committedApr 24, 2018
[SE-0206][Sema] Update Hashable synthesizer to support hash(into:)
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, then the generated hash(into:) body implements hashing from scratch, feeding components into the hasher. Otherwise, the body implements hash(into:) in terms of hashValue.
1 parent 0fb3e88 commit 23c1b24

9 files changed

+375
-280
lines changed
 

‎include/swift/AST/ASTContext.h

+2-6
Original file line numberDiff line numberDiff line change
@@ -471,12 +471,8 @@ class ASTContext {
471471
/// Retrieve the declaration of Swift.==(Int, Int) -> Bool.
472472
FuncDecl *getEqualIntDecl() const;
473473

474-
/// Retrieve the declaration of
475-
/// Swift._combineHashValues(Int, Int) -> Int.
476-
FuncDecl *getCombineHashValuesDecl() const;
477-
478-
/// Retrieve the declaration of Swift._mixInt(Int) -> Int.
479-
FuncDecl *getMixIntDecl() const;
474+
/// Retrieve the declaration of Swift._hashValue<H>(for: H) -> Int.
475+
FuncDecl *getHashValueForDecl() const;
480476

481477
/// Retrieve the declaration of Array.append(element:)
482478
FuncDecl *getArrayAppendElementDecl() const;

‎include/swift/AST/DiagnosticsSema.def

+2
Original file line numberDiff line numberDiff line change
@@ -2161,6 +2161,8 @@ ERROR(broken_equatable_requirement,none,
21612161
"Equatable protocol is broken: unexpected requirement", ())
21622162
ERROR(broken_hashable_requirement,none,
21632163
"Hashable protocol is broken: unexpected requirement", ())
2164+
ERROR(broken_hashable_no_hasher,none,
2165+
"Hashable protocol is broken: Hasher type not found", ())
21642166
ERROR(broken_errortype_requirement,none,
21652167
"Error protocol is broken: unexpected requirement", ())
21662168
ERROR(broken_int_hashable_conformance,none,

‎include/swift/AST/KnownIdentifiers.def

+5
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ IDENTIFIER(atIndexedSubscript)
3333
IDENTIFIER_(bridgeToObjectiveC)
3434
IDENTIFIER_WITH_NAME(code_, "_code")
3535
IDENTIFIER(CodingKeys)
36+
IDENTIFIER(combine)
3637
IDENTIFIER(container)
3738
IDENTIFIER(CoreGraphics)
3839
IDENTIFIER(CoreMedia)
@@ -57,13 +58,17 @@ IDENTIFIER(error)
5758
IDENTIFIER(errorDomain)
5859
IDENTIFIER(forKeyedSubscript)
5960
IDENTIFIER(Foundation)
61+
IDENTIFIER(for)
6062
IDENTIFIER(forKey)
6163
IDENTIFIER(from)
6264
IDENTIFIER(fromRaw)
65+
IDENTIFIER(hash)
66+
IDENTIFIER(hasher)
6367
IDENTIFIER(hashValue)
6468
IDENTIFIER(initialize)
6569
IDENTIFIER(initStorage)
6670
IDENTIFIER(initialValue)
71+
IDENTIFIER(into)
6772
IDENTIFIER(intValue)
6873
IDENTIFIER(Key)
6974
IDENTIFIER(KeyedDecodingContainer)

‎include/swift/AST/KnownStdlibTypes.def

+1
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ KNOWN_STDLIB_TYPE_DECL(Sequence, NominalTypeDecl, 1)
5050
KNOWN_STDLIB_TYPE_DECL(Dictionary, NominalTypeDecl, 2)
5151
KNOWN_STDLIB_TYPE_DECL(AnyHashable, NominalTypeDecl, 0)
5252
KNOWN_STDLIB_TYPE_DECL(MutableCollection, ProtocolDecl, 1)
53+
KNOWN_STDLIB_TYPE_DECL(Hasher, NominalTypeDecl, 0)
5354

5455
KNOWN_STDLIB_TYPE_DECL(AnyKeyPath, NominalTypeDecl, 0)
5556
KNOWN_STDLIB_TYPE_DECL(PartialKeyPath, NominalTypeDecl, 1)

‎lib/AST/ASTContext.cpp

+24-42
Original file line numberDiff line numberDiff line change
@@ -188,12 +188,9 @@ FOR_KNOWN_FOUNDATION_TYPES(CACHE_FOUNDATION_DECL)
188188
/// func ==(Int, Int) -> Bool
189189
FuncDecl *EqualIntDecl = nullptr;
190190

191-
/// func _combineHashValues(Int, Int) -> Int
192-
FuncDecl *CombineHashValuesDecl = nullptr;
191+
/// func _hashValue<H: Hashable>(for: H) -> Int
192+
FuncDecl *HashValueForDecl = nullptr;
193193

194-
/// func _mixInt(Int) -> Int
195-
FuncDecl *MixIntDecl = nullptr;
196-
197194
/// func append(Element) -> void
198195
FuncDecl *ArrayAppendElementDecl = nullptr;
199196

@@ -989,44 +986,29 @@ FuncDecl *ASTContext::getGetBoolDecl(LazyResolver *resolver) const {
989986
return decl;
990987
}
991988

992-
FuncDecl *ASTContext::getCombineHashValuesDecl() const {
993-
if (Impl.CombineHashValuesDecl)
994-
return Impl.CombineHashValuesDecl;
995-
996-
auto resolver = getLazyResolver();
997-
auto intType = getIntDecl()->getDeclaredType();
998-
999-
auto callback = [&](Type inputType, Type resultType) {
1000-
// Look for the signature (Int, Int) -> Int
1001-
auto tupleType = dyn_cast<TupleType>(inputType.getPointer());
1002-
assert(tupleType);
1003-
return tupleType->getNumElements() == 2 &&
1004-
tupleType->getElementType(0)->isEqual(intType) &&
1005-
tupleType->getElementType(1)->isEqual(intType) &&
1006-
resultType->isEqual(intType);
1007-
};
1008-
1009-
auto decl = lookupLibraryIntrinsicFunc(
1010-
*this, "_combineHashValues", resolver, callback);
1011-
Impl.CombineHashValuesDecl = decl;
1012-
return decl;
1013-
}
1014-
1015-
FuncDecl *ASTContext::getMixIntDecl() const {
1016-
if (Impl.MixIntDecl)
1017-
return Impl.MixIntDecl;
989+
FuncDecl *ASTContext::getHashValueForDecl() const {
990+
if (Impl.HashValueForDecl)
991+
return Impl.HashValueForDecl;
1018992

1019-
auto resolver = getLazyResolver();
1020-
auto intType = getIntDecl()->getDeclaredType();
1021-
1022-
auto callback = [&](Type inputType, Type resultType) {
1023-
// Look for the signature (Int) -> Int
1024-
return inputType->isEqual(intType) && resultType->isEqual(intType);
1025-
};
1026-
1027-
auto decl = lookupLibraryIntrinsicFunc(*this, "_mixInt", resolver, callback);
1028-
Impl.MixIntDecl = decl;
1029-
return decl;
993+
SmallVector<ValueDecl *, 1> results;
994+
lookupInSwiftModule("_hashValue", results);
995+
for (auto result : results) {
996+
auto *fd = dyn_cast<FuncDecl>(result);
997+
if (!fd)
998+
continue;
999+
auto paramLists = fd->getParameterLists();
1000+
if (paramLists.size() != 1 || paramLists[0]->size() != 1)
1001+
continue;
1002+
auto paramDecl = paramLists[0]->get(0);
1003+
if (paramDecl->getArgumentName() != Id_for)
1004+
continue;
1005+
auto genericParams = fd->getGenericParams();
1006+
if (!genericParams || genericParams->size() != 1)
1007+
continue;
1008+
Impl.HashValueForDecl = fd;
1009+
return fd;
1010+
}
1011+
return nullptr;
10301012
}
10311013

10321014
FuncDecl *ASTContext::getArrayAppendElementDecl() const {

0 commit comments

Comments
 (0)
Please sign in to comment.