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