@@ -1154,8 +1154,9 @@ swift_conformsToProtocolMaybeInstantiateSuperclasses(
11541154 return {foundWitness, hasUninstantiatedSuperclass};
11551155}
11561156
1157- // / Determine if
1158- static bool isExecutingInIsolationOfConformance (
1157+ // / Determine if we are executing within the isolation domain of the global
1158+ // / actor to which the given conformance is isolated.
1159+ static bool _isExecutingInIsolationOfConformance (
11591160 const Metadata *const type,
11601161 const ProtocolConformanceDescriptor *description,
11611162 const WitnessTable *table
@@ -1198,6 +1199,164 @@ static bool isExecutingInIsolationOfConformance(
11981199 return isCurrentGlobalActor (globalActorType, globalActorWitnessTable);
11991200}
12001201
1202+ static bool _checkConformanceIsolation (
1203+ const Metadata *const type, const WitnessTable *table);
1204+
1205+ // / Check for conformance isolation for a protocol requirement within the
1206+ // / conditional requirements of a witness table.
1207+ static bool _checkConformanceIsolationOfProtocolRequirement (
1208+ const Metadata *const type, const WitnessTable *table,
1209+ const GenericRequirementDescriptor &requirement,
1210+ const WitnessTable *conditionalWitnessTable
1211+ ) {
1212+ assert (requirement.Flags .getKind () == GenericRequirementKind::Protocol);
1213+ assert (!requirement.Flags .isPackRequirement ());
1214+
1215+ // If the conditional witness table has neither a global actor nor conditional
1216+ // requirements, there's nothing to check.
1217+ auto conditionalDescription = conditionalWitnessTable->getDescription ();
1218+ if (!conditionalDescription ||
1219+ !(conditionalDescription->hasConditionalRequirements () ||
1220+ conditionalDescription->hasGlobalActorIsolation ()))
1221+ return true ;
1222+
1223+ // Recurse into this conformance.
1224+
1225+ // Resolve the conforming type.
1226+ SubstGenericParametersFromMetadata substitutions (type);
1227+ auto result = swift_getTypeByMangledName (
1228+ MetadataState::Abstract, requirement.getParam (),
1229+ /* FIXME:conditionalArgs.data()*/ { },
1230+ [&substitutions](unsigned depth, unsigned index) {
1231+ return substitutions.getMetadata (depth, index).Ptr ;
1232+ },
1233+ [&substitutions](const Metadata *type, unsigned index) {
1234+ return substitutions.getWitnessTable (type, index);
1235+ });
1236+ if (result.isError ())
1237+ return false ;
1238+
1239+ return _checkConformanceIsolation (
1240+ result.getType ().getMetadata (), conditionalWitnessTable);
1241+ }
1242+
1243+ // / Check for conformance isolation for a protocol requirement pack within the
1244+ // / conditional requirements of a witness table.
1245+ static bool _checkConformanceIsolationOfProtocolRequirementPack (
1246+ const Metadata *const type, const WitnessTable *table,
1247+ const GenericRequirementDescriptor &requirement,
1248+ WitnessTablePackPointer conditionalWitnessTables
1249+ ) {
1250+ assert (requirement.Flags .getKind () == GenericRequirementKind::Protocol);
1251+ assert (requirement.Flags .isPackRequirement ());
1252+
1253+ // Check each of the conditional witness tables. If any has neither a global
1254+ // actor nor conditional requirements, there's nothing to check for that one.
1255+ MetadataPackPointer conformingTypes;
1256+ unsigned count = conditionalWitnessTables.getNumElements ();
1257+ for (unsigned index = 0 ; index != count; ++index) {
1258+ auto conditionalWitnessTable =
1259+ conditionalWitnessTables.getElements ()[index];
1260+
1261+ // If the conditional witness table has neither a global actor nor conditional
1262+ // requirements, there's nothing to check.
1263+ auto conditionalDescription = conditionalWitnessTable->getDescription ();
1264+ if (!conditionalDescription ||
1265+ !(conditionalDescription->hasConditionalRequirements () ||
1266+ conditionalDescription->hasGlobalActorIsolation ()))
1267+ continue ;
1268+
1269+ // If we don't have it already, get the parameter pack for the
1270+ // conforming types.
1271+ if (!conformingTypes) {
1272+ // Resolve the conforming type.
1273+ SubstGenericParametersFromMetadata substitutions (type);
1274+ auto result = swift::getTypePackByMangledName (
1275+ requirement.getParam (),
1276+ /* FIXME:conditionalArgs.data()*/ { },
1277+ [&substitutions](unsigned depth, unsigned index) {
1278+ return substitutions.getMetadata (depth, index).Ptr ;
1279+ },
1280+ [&substitutions](const Metadata *type, unsigned index) {
1281+ return substitutions.getWitnessTable (type, index);
1282+ });
1283+ if (result.isError ())
1284+ return false ;
1285+
1286+ conformingTypes = result.getType ();
1287+ assert (conformingTypes.getNumElements () == count);
1288+ }
1289+
1290+ if (!_checkConformanceIsolation (
1291+ conformingTypes.getElements ()[index], conditionalWitnessTable))
1292+ return false ;
1293+ }
1294+
1295+ return true ;
1296+ }
1297+
1298+ // / Check whether all isolated conformances in the given witness table (and
1299+ // / any witness tables it depends on) are satisfied by the current execution
1300+ // / context.
1301+ // /
1302+ // / Returns false if there is an isolated conformance but we are not executing
1303+ // / in that isolation domain.
1304+ static bool _checkConformanceIsolation (const Metadata *const type, const WitnessTable *table) {
1305+ if (!table)
1306+ return true ;
1307+
1308+ auto description = table->getDescription ();
1309+ if (!description)
1310+ return true ;
1311+
1312+ // If this conformance has global actor isolation, check that we are
1313+ // running in that isolation domain.
1314+ if (description->hasGlobalActorIsolation () &&
1315+ !_isExecutingInIsolationOfConformance (type, description, table)) {
1316+ return false ;
1317+ }
1318+
1319+ // Check any witness tables that are part of a conditional conformance.
1320+ unsigned instantiationArgIndex = 0 ;
1321+ for (const auto &requirement: description->getConditionalRequirements ()) {
1322+ if (!requirement.Flags .hasKeyArgument ())
1323+ continue ;
1324+
1325+ switch (requirement.Flags .getKind ()) {
1326+ case GenericRequirementKind::Protocol: {
1327+ auto instantiationArg =
1328+ ((void * const *)table)[-1 - (int )instantiationArgIndex];
1329+ if (requirement.Flags .isPackRequirement ()) {
1330+ if (!_checkConformanceIsolationOfProtocolRequirementPack (
1331+ type, table, requirement,
1332+ WitnessTablePackPointer (instantiationArg)))
1333+ return false ;
1334+ } else {
1335+ if (!_checkConformanceIsolationOfProtocolRequirement (
1336+ type, table, requirement,
1337+ (const WitnessTable *)instantiationArg)) {
1338+ return false ;
1339+ }
1340+ }
1341+
1342+ break ;
1343+ }
1344+
1345+ case GenericRequirementKind::SameType:
1346+ case GenericRequirementKind::BaseClass:
1347+ case GenericRequirementKind::SameConformance:
1348+ case GenericRequirementKind::SameShape:
1349+ case GenericRequirementKind::InvertedProtocols:
1350+ case GenericRequirementKind::Layout:
1351+ break ;
1352+ }
1353+
1354+ ++instantiationArgIndex;
1355+ }
1356+
1357+ return true ;
1358+ }
1359+
12011360static const WitnessTable *
12021361swift_conformsToProtocolCommonImpl (const Metadata *const type,
12031362 const ProtocolDescriptor *protocol) {
@@ -1222,17 +1381,9 @@ swift_conformsToProtocolCommonImpl(const Metadata *const type,
12221381 swift_conformsToProtocolMaybeInstantiateSuperclasses (
12231382 type, protocol, true /* instantiateSuperclassMetadata*/ );
12241383
1225- // If the conformance is isolated to a global actor, check whether we are
1226- // currently executing on that global actor. Otherwise, the type does not
1227- // conform.
1228- if (table) {
1229- if (auto description = table->getDescription ()) {
1230- if (description->hasGlobalActorIsolation () &&
1231- !isExecutingInIsolationOfConformance (type, description, table)) {
1232- return nullptr ;
1233- }
1234- }
1235- }
1384+ // Check for isolated conformances.
1385+ if (!_checkConformanceIsolation (type, table))
1386+ return nullptr ;
12361387
12371388 return table;
12381389}
0 commit comments