@@ -1090,15 +1090,16 @@ class ValueIsolationRegionInfo {
10901090 }
10911091
10921092 bool hasActorIsolation () const {
1093- return std::holds_alternative<std::optional<ActorIsolation>>(data);
1093+ return kind == Actor &&
1094+ std::holds_alternative<std::optional<ActorIsolation>>(data);
10941095 }
10951096
10961097 bool hasActorInstance () const {
1097- return std::holds_alternative<NominalTypeDecl *>(data);
1098+ return kind == Actor && std::holds_alternative<NominalTypeDecl *>(data);
10981099 }
10991100
11001101 bool hasTaskIsolatedValue () const {
1101- return std::holds_alternative<SILValue>(data);
1102+ return kind == Task && std::holds_alternative<SILValue>(data);
11021103 }
11031104
11041105 // / If we actually have an actor decl, return that. Otherwise, see if we have
@@ -1128,8 +1129,19 @@ class ValueIsolationRegionInfo {
11281129 if (unsigned (other.kind ) < unsigned (kind))
11291130 return *this ;
11301131
1131- assert (kind != ValueIsolationRegionInfo::Actor &&
1132- " Actor should never be merged with another actor?!" );
1132+ // TODO: Make this failing mean that we emit an unknown SIL error instead of
1133+ // asserting.
1134+ if (other.isActorIsolated () && isActorIsolated ()) {
1135+ if (other.hasActorInstance () && hasActorInstance ()) {
1136+ assert (other.getActorInstance () == getActorInstance () &&
1137+ " Actor should never be merged with another actor unless with "
1138+ " the same actor?!" );
1139+ } else if (other.hasActorIsolation () && hasActorIsolation ()) {
1140+ assert (other.getActorIsolation () == getActorIsolation () &&
1141+ " Actor should never be merged with another actor unless with "
1142+ " the same actor?!" );
1143+ }
1144+ }
11331145
11341146 // Otherwise, take the other value.
11351147 return other;
@@ -1204,15 +1216,18 @@ struct PartitionOpEvaluator {
12041216 }
12051217
12061218 // / Call handleTransferNonTransferrable on our CRTP subclass.
1207- void handleTransferNonTransferrable (const PartitionOp &op,
1208- Element elt) const {
1209- return asImpl ().handleTransferNonTransferrable (op, elt);
1219+ void handleTransferNonTransferrable (
1220+ const PartitionOp &op, Element elt,
1221+ ValueIsolationRegionInfo isolationRegionInfo) const {
1222+ return asImpl ().handleTransferNonTransferrable (op, elt,
1223+ isolationRegionInfo);
12101224 }
1211-
12121225 // / Just call our CRTP subclass.
1213- void handleTransferNonTransferrable (const PartitionOp &op, Element elt,
1214- Element otherElement) const {
1215- return asImpl ().handleTransferNonTransferrable (op, elt, otherElement);
1226+ void handleTransferNonTransferrable (
1227+ const PartitionOp &op, Element elt, Element otherElement,
1228+ ValueIsolationRegionInfo isolationRegionInfo) const {
1229+ return asImpl ().handleTransferNonTransferrable (op, elt, otherElement,
1230+ isolationRegionInfo);
12161231 }
12171232
12181233 // / Call isActorDerived on our CRTP subclass.
@@ -1282,39 +1297,35 @@ struct PartitionOpEvaluator {
12821297 assert (p.isTrackingElement (op.getOpArgs ()[0 ]) &&
12831298 " Transfer PartitionOp's argument should already be tracked" );
12841299
1300+ ValueIsolationRegionInfo isolationRegionInfo =
1301+ getIsolationRegionInfo (op.getOpArgs ()[0 ]);
1302+
12851303 // If we know our direct value is actor derived... immediately emit an
12861304 // error.
1287- if (isActorDerived (op.getOpArgs ()[0 ]))
1288- return handleTransferNonTransferrable (op, op.getOpArgs ()[0 ]);
1305+ if (isolationRegionInfo.hasActorIsolation ()) {
1306+ return handleTransferNonTransferrable (op, op.getOpArgs ()[0 ],
1307+ isolationRegionInfo);
1308+ }
12891309
1290- // Otherwise, we may have a value that is actor derived or task isolated
1291- // from another value. We need to prefer actor derived.
1292- //
1293- // While we are checking for actor derived, also check if our value or any
1294- // value in our region is closure captured and propagate that bit in our
1295- // transferred inst.
1310+ // Otherwise, we need to merge our isolation region info with the
1311+ // isolation region info of everything else in our region. This is the
1312+ // dynamic isolation region info found by the dataflow.
12961313 bool isClosureCapturedElt =
12971314 isClosureCaptured (op.getOpArgs ()[0 ], op.getSourceOp ());
12981315 Region elementRegion = p.getRegion (op.getOpArgs ()[0 ]);
1299- std::optional<Element> actorDerivedElt;
1300- std::optional<Element> taskDerivedElt;
13011316 for (const auto &pair : p.range ()) {
13021317 if (pair.second == elementRegion) {
1303- if (isActorDerived (pair.first ))
1304- actorDerivedElt = pair.first ;
1305- if (isTaskIsolatedDerived (pair.first ))
1306- taskDerivedElt = pair.first ;
1318+ isolationRegionInfo =
1319+ isolationRegionInfo.merge (getIsolationRegionInfo (pair.first ));
13071320 isClosureCapturedElt |=
13081321 isClosureCaptured (pair.first , op.getSourceOp ());
13091322 }
13101323 }
13111324
1312- // Now try to add the actor derived elt first and then the task derived
1313- // elt, preferring actor derived.
1314- if (actorDerivedElt.has_value () || taskDerivedElt.has_value ()) {
1315- return handleTransferNonTransferrable (
1316- op, op.getOpArgs ()[0 ],
1317- actorDerivedElt.has_value () ? *actorDerivedElt : *taskDerivedElt);
1325+ // If we merged anything, we need to handle a transfer non-transferrable.
1326+ if (bool (isolationRegionInfo) && !isolationRegionInfo.isDisconnected ()) {
1327+ return handleTransferNonTransferrable (op, op.getOpArgs ()[0 ],
1328+ isolationRegionInfo);
13181329 }
13191330
13201331 // Mark op.getOpArgs()[0] as transferred.
@@ -1415,14 +1426,13 @@ struct PartitionOpEvaluatorBaseImpl : PartitionOpEvaluator<Subclass> {
14151426
14161427 // / This is called if we detect a never transferred element that was passed to
14171428 // / a transfer instruction.
1418- void handleTransferNonTransferrable (const PartitionOp &op,
1419- Element elt) const {}
1429+ void
1430+ handleTransferNonTransferrable (const PartitionOp &op, Element elt,
1431+ ValueIsolationRegionInfo regionInfo) const {}
14201432
1421- // / This is called if we detect a never transferred element that was passed to
1422- // / a transfer instruction but the actual element that could not be
1423- // / transferred is a different element in its region.
1424- void handleTransferNonTransferrable (const PartitionOp &op, Element elt,
1425- Element otherEltInRegion) const {}
1433+ void handleTransferNonTransferrable (
1434+ const PartitionOp &op, Element elt, Element otherElement,
1435+ ValueIsolationRegionInfo isolationRegionInfo) const {}
14261436
14271437 // / This is used to determine if an element is actor derived. If we determine
14281438 // / that a region containing such an element is transferred, we emit an error
0 commit comments