@@ -989,6 +989,115 @@ ProtocolConformanceRef ModuleDecl::lookupConformance(Type type,
989
989
getASTContext ().evaluator , request, ProtocolConformanceRef::forInvalid ());
990
990
}
991
991
992
+ // / Synthesize a builtin tuple type conformance to the given protocol, if
993
+ // / appropriate.
994
+ static ProtocolConformanceRef getBuiltinTupleTypeConformance (
995
+ Type type, const TupleType *tupleType, ProtocolDecl *protocol) {
996
+ // Tuple type are Sendable when all of their element types are Sendable.
997
+ if (protocol->isSpecificProtocol (KnownProtocolKind::Sendable)) {
998
+ ASTContext &ctx = protocol->getASTContext ();
999
+
1000
+ // Create the pieces for a generic tuple type (T1, T2, ... TN) and a
1001
+ // generic signature <T1, T2, ..., TN>.
1002
+ SmallVector<GenericTypeParamType *, 4 > genericParams;
1003
+ SmallVector<Type, 4 > typeSubstitutions;
1004
+ SmallVector<TupleTypeElt, 4 > genericElements;
1005
+ SmallVector<Requirement, 4 > conditionalRequirements;
1006
+ for (const auto &elt : tupleType->getElements ()) {
1007
+ auto genericParam = GenericTypeParamType::get (0 , genericParams.size (), ctx);
1008
+ genericParams.push_back (genericParam);
1009
+ typeSubstitutions.push_back (elt.getRawType ());
1010
+ genericElements.push_back (elt.getWithType (genericParam));
1011
+ conditionalRequirements.push_back (
1012
+ Requirement (RequirementKind::Conformance, genericParam,
1013
+ protocol->getDeclaredType ()));
1014
+ }
1015
+
1016
+ // If there were no generic parameters, just form the builtin conformance.
1017
+ if (genericParams.empty ()) {
1018
+ return ProtocolConformanceRef (
1019
+ ctx.getBuiltinConformance (type, protocol, GenericSignature (), { }));
1020
+ }
1021
+
1022
+ // Form a generic conformance of (T1, T2, ..., TN): Sendable with signature
1023
+ // <T1, T2, ..., TN> and conditional requirements T1: Sendable,
1024
+ // T2: Sendable, ..., TN: Sendable.
1025
+ auto genericTupleType = TupleType::get (genericElements, ctx);
1026
+ auto genericSig = GenericSignature::get (genericParams, { });
1027
+ auto genericConformance = ctx.getBuiltinConformance (
1028
+ genericTupleType, protocol, genericSig, conditionalRequirements);
1029
+
1030
+ // Compute the substitution map from the generic parameters of the
1031
+ // generic conformance to actual types that were in the tuple type.
1032
+ // Form a specialized conformance from that.
1033
+ auto subMap = SubstitutionMap::get (genericSig, typeSubstitutions, { });
1034
+ return ProtocolConformanceRef (
1035
+ ctx.getSpecializedConformance (type, genericConformance, subMap));
1036
+ }
1037
+
1038
+ return ProtocolConformanceRef::forInvalid ();
1039
+ }
1040
+
1041
+ // / Whether the given function type conforms to Sendable.
1042
+ static bool isSendableFunctionType (const FunctionType *functionType) {
1043
+ if (functionType->isSendable ())
1044
+ return true ;
1045
+
1046
+ // C and thin function types have no captures, so they are Sendable.
1047
+ switch (functionType->getExtInfo ().getRepresentation ()) {
1048
+ case FunctionTypeRepresentation::Block:
1049
+ case FunctionTypeRepresentation::Swift:
1050
+ return false ;
1051
+
1052
+ case FunctionTypeRepresentation::CFunctionPointer:
1053
+ case FunctionTypeRepresentation::Thin:
1054
+ return true ;
1055
+ }
1056
+ }
1057
+
1058
+ // / Synthesize a builtin function type conformance to the given protocol, if
1059
+ // / appropriate.
1060
+ static ProtocolConformanceRef getBuiltinFunctionTypeConformance (
1061
+ Type type, const FunctionType *functionType, ProtocolDecl *protocol) {
1062
+ // @Sendable function types are Sendable.
1063
+ if (protocol->isSpecificProtocol (KnownProtocolKind::Sendable) &&
1064
+ isSendableFunctionType (functionType)) {
1065
+ ASTContext &ctx = protocol->getASTContext ();
1066
+ return ProtocolConformanceRef (
1067
+ ctx.getBuiltinConformance (type, protocol, GenericSignature (), { }));
1068
+ }
1069
+
1070
+ return ProtocolConformanceRef::forInvalid ();
1071
+ }
1072
+
1073
+ // / Synthesize a builtin metatype type conformance to the given protocol, if
1074
+ // / appropriate.
1075
+ static ProtocolConformanceRef getBuiltinMetaTypeTypeConformance (
1076
+ Type type, const AnyMetatypeType *metatypeType, ProtocolDecl *protocol) {
1077
+ // All metatypes are Sendable.
1078
+ if (protocol->isSpecificProtocol (KnownProtocolKind::Sendable)) {
1079
+ ASTContext &ctx = protocol->getASTContext ();
1080
+ return ProtocolConformanceRef (
1081
+ ctx.getBuiltinConformance (type, protocol, GenericSignature (), { }));
1082
+ }
1083
+
1084
+ return ProtocolConformanceRef::forInvalid ();
1085
+ }
1086
+
1087
+ // / Synthesize a builtin type conformance to the given protocol, if
1088
+ // / appropriate.
1089
+ static ProtocolConformanceRef getBuiltinBuiltinTypeConformance (
1090
+ Type type, const BuiltinType *builtinType, ProtocolDecl *protocol) {
1091
+ // All builtin are Sendable.
1092
+ if (protocol->isSpecificProtocol (KnownProtocolKind::Sendable)) {
1093
+ ASTContext &ctx = protocol->getASTContext ();
1094
+ return ProtocolConformanceRef (
1095
+ ctx.getBuiltinConformance (type, protocol, GenericSignature (), { }));
1096
+ }
1097
+
1098
+ return ProtocolConformanceRef::forInvalid ();
1099
+ }
1100
+
992
1101
ProtocolConformanceRef
993
1102
LookupConformanceInModuleRequest::evaluate (
994
1103
Evaluator &evaluator, LookupConformanceDescriptor desc) const {
@@ -1043,6 +1152,26 @@ LookupConformanceInModuleRequest::evaluate(
1043
1152
if (type->is <UnresolvedType>() || type->is <PlaceholderType>())
1044
1153
return ProtocolConformanceRef (protocol);
1045
1154
1155
+ // Tuple types can conform to protocols.
1156
+ if (auto tupleType = type->getAs <TupleType>()) {
1157
+ return getBuiltinTupleTypeConformance (type, tupleType, protocol);
1158
+ }
1159
+
1160
+ // Function types can conform to protocols.
1161
+ if (auto functionType = type->getAs <FunctionType>()) {
1162
+ return getBuiltinFunctionTypeConformance (type, functionType, protocol);
1163
+ }
1164
+
1165
+ // Metatypes can conform to protocols.
1166
+ if (auto metatypeType = type->getAs <AnyMetatypeType>()) {
1167
+ return getBuiltinMetaTypeTypeConformance (type, metatypeType, protocol);
1168
+ }
1169
+
1170
+ // Builtin types can conform to protocols.
1171
+ if (auto builtinType = type->getAs <BuiltinType>()) {
1172
+ return getBuiltinBuiltinTypeConformance (type, builtinType, protocol);
1173
+ }
1174
+
1046
1175
auto nominal = type->getAnyNominal ();
1047
1176
1048
1177
// If we don't have a nominal type, there are no conformances.
0 commit comments