Skip to content

Commit a3ac475

Browse files
committed
[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, 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
1 parent 6df8732 commit a3ac475

File tree

8 files changed

+399
-289
lines changed

8 files changed

+399
-289
lines changed

include/swift/AST/ASTContext.h

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -400,8 +400,8 @@ class ASTContext {
400400
ProtocolDecl *getErrorDecl() const;
401401
CanType getExceptionType() const;
402402

403-
#define KNOWN_STDLIB_TYPE_DECL(NAME, DECL_CLASS, NUM_GENERIC_PARAMS) \
404-
/** Retrieve the declaration of Swift.NAME. */ \
403+
#define KNOWN_STDLIB_TYPE_DECL_WITH_NAME(NAME, IDSTR, DECL_CLASS, NUM_GENERIC_PARAMS) \
404+
/** Retrieve the declaration of Swift.IDSTR. */ \
405405
DECL_CLASS *get##NAME##Decl() const;
406406
#include "swift/AST/KnownStdlibTypes.def"
407407

@@ -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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2131,6 +2131,8 @@ ERROR(broken_equatable_requirement,none,
21312131
"Equatable protocol is broken: unexpected requirement", ())
21322132
ERROR(broken_hashable_requirement,none,
21332133
"Hashable protocol is broken: unexpected requirement", ())
2134+
ERROR(broken_hashable_no_hasher,none,
2135+
"Hashable protocol is broken: _Hasher type not found", ())
21342136
ERROR(broken_errortype_requirement,none,
21352137
"Error protocol is broken: unexpected requirement", ())
21362138
ERROR(broken_int_hashable_conformance,none,

include/swift/AST/KnownIdentifiers.def

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ IDENTIFIER(alloc)
2828
IDENTIFIER(allocWithZone)
2929
IDENTIFIER(allZeros)
3030
IDENTIFIER(Any)
31+
IDENTIFIER(append)
3132
IDENTIFIER(ArrayLiteralElement)
3233
IDENTIFIER(atIndexedSubscript)
3334
IDENTIFIER_(bridgeToObjectiveC)
@@ -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

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,19 @@
1515
//
1616
//===----------------------------------------------------------------------===//
1717

18-
#ifndef KNOWN_STDLIB_TYPE_DECL
19-
/// KNOWN_STDLIB_TYPE_DECL(NAME, DECL_CLASS, NUM_GENERIC_PARAMS)
18+
#ifndef KNOWN_STDLIB_TYPE_DECL_WITH_NAME
19+
/// KNOWN_STDLIB_TYPE_DECL_WITH_NAME(NAME, IDSTR, DECL_CLASS, NUM_GENERIC_PARAMS)
2020
///
2121
/// The macro is expanded for each known standard library type. NAME is
2222
/// bound to the unqualified name of the type. DECL_CLASS is bound to the
2323
/// Decl subclass it is expected to be an instance of. NUM_GENERIC_PARAMS is
2424
/// bound to the number of generic parameters the type is expected to have.
25-
#define KNOWN_STDLIB_TYPE_DECL(NAME, DECL_CLASS, NUM_GENERIC_PARAMS)
25+
#define KNOWN_STDLIB_TYPE_DECL_WITH_NAME(NAME, IDSTR, DECL_CLASS, NUM_GENERIC_PARAMS)
2626
#endif
2727

28+
#define KNOWN_STDLIB_TYPE_DECL(NAME, DECL_CLASS, NUM_GENERIC_PARAMS) \
29+
KNOWN_STDLIB_TYPE_DECL_WITH_NAME(NAME, #NAME, DECL_CLASS, NUM_GENERIC_PARAMS)
30+
2831
KNOWN_STDLIB_TYPE_DECL(Bool, NominalTypeDecl, 0)
2932

3033
KNOWN_STDLIB_TYPE_DECL(Int, NominalTypeDecl, 0)
@@ -50,6 +53,7 @@ KNOWN_STDLIB_TYPE_DECL(Sequence, NominalTypeDecl, 1)
5053
KNOWN_STDLIB_TYPE_DECL(Dictionary, NominalTypeDecl, 2)
5154
KNOWN_STDLIB_TYPE_DECL(AnyHashable, NominalTypeDecl, 0)
5255
KNOWN_STDLIB_TYPE_DECL(MutableCollection, ProtocolDecl, 1)
56+
KNOWN_STDLIB_TYPE_DECL_WITH_NAME(Hasher, "_Hasher", NominalTypeDecl, 0)
5357

5458
KNOWN_STDLIB_TYPE_DECL(AnyKeyPath, NominalTypeDecl, 0)
5559
KNOWN_STDLIB_TYPE_DECL(PartialKeyPath, NominalTypeDecl, 1)
@@ -79,3 +83,4 @@ KNOWN_STDLIB_TYPE_DECL(KeyedDecodingContainer, NominalTypeDecl, 1)
7983
KNOWN_STDLIB_TYPE_DECL(RangeReplaceableCollection, ProtocolDecl, 1)
8084

8185
#undef KNOWN_STDLIB_TYPE_DECL
86+
#undef KNOWN_STDLIB_TYPE_DECL_WITH_NAME

lib/AST/ASTContext.cpp

Lines changed: 27 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ struct ASTContext::Implementation {
134134
/// The AnyObject type.
135135
CanType AnyObjectType;
136136

137-
#define KNOWN_STDLIB_TYPE_DECL(NAME, DECL_CLASS, NUM_GENERIC_PARAMS) \
137+
#define KNOWN_STDLIB_TYPE_DECL_WITH_NAME(NAME, IDSTR, DECL_CLASS, NUM_GENERIC_PARAMS) \
138138
/** The declaration of Swift.NAME. */ \
139139
DECL_CLASS *NAME##Decl = nullptr;
140140
#include "swift/AST/KnownStdlibTypes.def"
@@ -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

@@ -616,11 +613,11 @@ FuncDecl *ASTContext::getPlusFunctionOnString() const {
616613
return Impl.PlusFunctionOnString;
617614
}
618615

619-
#define KNOWN_STDLIB_TYPE_DECL(NAME, DECL_CLASS, NUM_GENERIC_PARAMS) \
616+
#define KNOWN_STDLIB_TYPE_DECL_WITH_NAME(NAME, IDSTR, DECL_CLASS, NUM_GENERIC_PARAMS) \
620617
DECL_CLASS *ASTContext::get##NAME##Decl() const { \
621618
if (!Impl.NAME##Decl) \
622619
Impl.NAME##Decl = dyn_cast_or_null<DECL_CLASS>( \
623-
findStdlibType(*this, #NAME, NUM_GENERIC_PARAMS)); \
620+
findStdlibType(*this, IDSTR, NUM_GENERIC_PARAMS)); \
624621
return Impl.NAME##Decl; \
625622
}
626623
#include "swift/AST/KnownStdlibTypes.def"
@@ -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)