@@ -192,6 +192,12 @@ FOR_KNOWN_FOUNDATION_TYPES(CACHE_FOUNDATION_DECL)
192
192
// / func ==(Int, Int) -> Bool
193
193
FuncDecl *EqualIntDecl = nullptr ;
194
194
195
+ // / func _mixForSynthesizedHashValue(Int, Int) -> Int
196
+ FuncDecl *MixForSynthesizedHashValueDecl = nullptr ;
197
+
198
+ // / func _mixInt(Int) -> Int
199
+ FuncDecl *MixIntDecl = nullptr ;
200
+
195
201
// / func append(Element) -> void
196
202
FuncDecl *ArrayAppendElementDecl = nullptr ;
197
203
@@ -935,27 +941,78 @@ static bool isBuiltinWordType(Type type) {
935
941
return false ;
936
942
}
937
943
938
- FuncDecl *ASTContext::getGetBoolDecl (LazyResolver *resolver) const {
939
- if (Impl.GetBoolDecl )
940
- return Impl.GetBoolDecl ;
944
+ // / Looks up all implementations of an operator (globally and declared in types)
945
+ // / and passes potential matches to the given callback. The search stops when
946
+ // / the callback returns true (in which case the matching function declaration
947
+ // / is returned); otherwise, nullptr is returned if there are no matches.
948
+ // / \p C The AST context.
949
+ // / \p oper The name of the operator.
950
+ // / \p contextType If the operator is declared on a type, then only operators
951
+ // / defined on this type should be considered.
952
+ // / \p callback A callback that takes as its two arguments the input type and
953
+ // / result type of a candidate function declaration and returns true if the
954
+ // / function matches the desired criteria.
955
+ // / \return The matching function declaration, or nullptr if there was no match.
956
+ template <int ExpectedCandidateCount, typename MatchFuncCallback>
957
+ static FuncDecl *lookupOperatorFunc (const ASTContext &ctx, StringRef oper,
958
+ Type contextType,
959
+ MatchFuncCallback &callback) {
960
+ SmallVector<ValueDecl *, ExpectedCandidateCount> candidates;
961
+ ctx.lookupInSwiftModule (oper, candidates);
962
+
963
+ for (auto candidate : candidates) {
964
+ // All operator declarations should be functions, but make sure.
965
+ auto *funcDecl = dyn_cast<FuncDecl>(candidate);
966
+ if (!funcDecl)
967
+ continue ;
941
968
942
- // Look for the function.
943
- Type input, output;
944
- auto decl = findLibraryIntrinsic (*this , " _getBool" , resolver);
945
- if (!decl ||
946
- !isNonGenericIntrinsic (decl, /* allowTypeMembers=*/ false , input, output))
947
- return nullptr ;
969
+ if (funcDecl->getDeclContext ()->isTypeContext ()) {
970
+ auto contextTy = funcDecl->getDeclContext ()->getDeclaredInterfaceType ();
971
+ if (!contextTy->isEqual (contextType)) continue ;
972
+ }
948
973
949
- // Input must be Builtin.Int1
950
- if (!isBuiltinInt1Type (input))
951
- return nullptr ;
974
+ if (auto resolver = ctx.getLazyResolver ())
975
+ resolver->resolveDeclSignature (funcDecl);
952
976
953
- // Output must be a global type named Bool.
954
- if (!output->isEqual (getBoolDecl ()->getDeclaredType ()))
977
+ Type inputType, resultType;
978
+ if (!isNonGenericIntrinsic (funcDecl, /* allowTypeMembers=*/ true , inputType,
979
+ resultType))
980
+ continue ;
981
+
982
+ if (callback (inputType, resultType))
983
+ return funcDecl;
984
+ }
985
+
986
+ return nullptr ;
987
+ }
988
+
989
+ // / Looks up the implementation (assumed to be singular) of a globally-defined
990
+ // / standard library intrinsic function and passes the potential match to the
991
+ // / given callback if it was found. If the callback returns true, then the
992
+ // / match is returned; otherwise, nullptr is returned.
993
+ // / \p ctx The AST context.
994
+ // / \p name The name of the function.
995
+ // / \p resolver The lazy resolver.
996
+ // / \p callback A callback that takes as its two arguments the input type and
997
+ // / result type of the candidate function declaration and returns true if
998
+ // / the function matches the desired criteria.
999
+ // / \return The matching function declaration, or nullptr if there was no match.
1000
+ template <typename MatchFuncCallback>
1001
+ static FuncDecl *lookupLibraryIntrinsicFunc (const ASTContext &ctx,
1002
+ StringRef name,
1003
+ LazyResolver *resolver,
1004
+ MatchFuncCallback &callback) {
1005
+ Type inputType, resultType;
1006
+ auto decl = findLibraryIntrinsic (ctx, name, resolver);
1007
+ if (!decl ||
1008
+ !isNonGenericIntrinsic (decl, /* allowTypeMembers=*/ false , inputType,
1009
+ resultType))
955
1010
return nullptr ;
956
1011
957
- Impl.GetBoolDecl = decl;
958
- return decl;
1012
+ if (callback (inputType, resultType))
1013
+ return decl;
1014
+
1015
+ return nullptr ;
959
1016
}
960
1017
961
1018
FuncDecl *ASTContext::getEqualIntDecl () const {
@@ -967,45 +1024,74 @@ FuncDecl *ASTContext::getEqualIntDecl() const {
967
1024
968
1025
auto intType = getIntDecl ()->getDeclaredType ();
969
1026
auto boolType = getBoolDecl ()->getDeclaredType ();
970
- SmallVector<ValueDecl *, 30 > equalFuncs;
971
- lookupInSwiftModule ( " == " , equalFuncs);
972
-
973
- // Find the overload for Int.
974
- for (ValueDecl *vd : equalFuncs) {
975
- // All "==" decls should be functions, but who knows...
976
- auto *funcDecl = dyn_cast<FuncDecl>(vd);
977
- if (!funcDecl)
978
- continue ;
1027
+ auto callback = [&](Type inputType, Type resultType) {
1028
+ // Check for the signature: (Int, Int) -> Bool
1029
+ auto tupleType = dyn_cast<TupleType>(inputType. getPointer ());
1030
+ assert (tupleType);
1031
+ return tupleType-> getNumElements () == 2 &&
1032
+ tupleType-> getElementType ( 0 )-> isEqual (intType) &&
1033
+ tupleType-> getElementType ( 1 )-> isEqual (intType) &&
1034
+ resultType-> isEqual (boolType);
1035
+ } ;
979
1036
980
- if (funcDecl-> getDeclContext ()-> isTypeContext ()) {
981
- auto contextTy = funcDecl-> getDeclContext ()-> getDeclaredInterfaceType () ;
982
- if (!contextTy-> isEqual (intType)) continue ;
983
- }
1037
+ auto decl = lookupOperatorFunc< 32 >(* this , " == " , intType, callback);
1038
+ Impl. EqualIntDecl = decl ;
1039
+ return decl ;
1040
+ }
984
1041
985
- if (auto resolver = getLazyResolver ())
986
- resolver->resolveDeclSignature (funcDecl);
1042
+ FuncDecl *ASTContext::getGetBoolDecl (LazyResolver *resolver) const {
1043
+ if (Impl.GetBoolDecl )
1044
+ return Impl.GetBoolDecl ;
987
1045
988
- Type input, resultType;
989
- if (!isNonGenericIntrinsic (funcDecl, /* allowTypeMembers=*/ true , input,
990
- resultType))
991
- continue ;
992
-
993
- // Check for the signature: (Int, Int) -> Bool
994
- auto tupleType = dyn_cast<TupleType>(input.getPointer ());
1046
+ auto callback = [&](Type inputType, Type resultType) {
1047
+ // Look for the signature (Builtin.Int1) -> Bool
1048
+ return isBuiltinInt1Type (inputType) &&
1049
+ resultType->isEqual (getBoolDecl ()->getDeclaredType ());
1050
+ };
1051
+
1052
+ auto decl = lookupLibraryIntrinsicFunc (*this , " _getBool" , resolver, callback);
1053
+ Impl.GetBoolDecl = decl;
1054
+ return decl;
1055
+ }
1056
+
1057
+ FuncDecl *ASTContext::getMixForSynthesizedHashValueDecl () const {
1058
+ if (Impl.MixForSynthesizedHashValueDecl )
1059
+ return Impl.MixForSynthesizedHashValueDecl ;
1060
+
1061
+ auto resolver = getLazyResolver ();
1062
+ auto intType = getIntDecl ()->getDeclaredType ();
1063
+
1064
+ auto callback = [&](Type inputType, Type resultType) {
1065
+ // Look for the signature (Int, Int) -> Int
1066
+ auto tupleType = dyn_cast<TupleType>(inputType.getPointer ());
995
1067
assert (tupleType);
996
- if (tupleType->getNumElements () != 2 )
997
- continue ;
1068
+ return tupleType->getNumElements () == 2 &&
1069
+ tupleType->getElementType (0 )->isEqual (intType) &&
1070
+ tupleType->getElementType (1 )->isEqual (intType) &&
1071
+ resultType->isEqual (intType);
1072
+ };
998
1073
999
- auto argType1 = tupleType->getElementType (0 );
1000
- auto argType2 = tupleType->getElementType (1 );
1001
- if (argType1->isEqual (intType) &&
1002
- argType2->isEqual (intType) &&
1003
- resultType->isEqual (boolType)) {
1004
- Impl.EqualIntDecl = funcDecl;
1005
- return funcDecl;
1006
- }
1007
- }
1008
- return nullptr ;
1074
+ auto decl = lookupLibraryIntrinsicFunc (
1075
+ *this , " _mixForSynthesizedHashValue" , resolver, callback);
1076
+ Impl.MixForSynthesizedHashValueDecl = decl;
1077
+ return decl;
1078
+ }
1079
+
1080
+ FuncDecl *ASTContext::getMixIntDecl () const {
1081
+ if (Impl.MixIntDecl )
1082
+ return Impl.MixIntDecl ;
1083
+
1084
+ auto resolver = getLazyResolver ();
1085
+ auto intType = getIntDecl ()->getDeclaredType ();
1086
+
1087
+ auto callback = [&](Type inputType, Type resultType) {
1088
+ // Look for the signature (Int) -> Int
1089
+ return inputType->isEqual (intType) && resultType->isEqual (intType);
1090
+ };
1091
+
1092
+ auto decl = lookupLibraryIntrinsicFunc (*this , " _mixInt" , resolver, callback);
1093
+ Impl.MixIntDecl = decl;
1094
+ return decl;
1009
1095
}
1010
1096
1011
1097
FuncDecl *ASTContext::getArrayAppendElementDecl () const {
0 commit comments