@@ -996,6 +996,16 @@ struct PartitionOpEvaluator {
996996 isolationRegionInfo);
997997 }
998998
999+ // / Just call our CRTP subclass.
1000+ void handleAssignTransferNonTransferrableIntoSendingResult (
1001+ const PartitionOp &op, Element destElement,
1002+ SILFunctionArgument *destValue, Element srcElement, SILValue srcValue,
1003+ SILDynamicMergedIsolationInfo srcIsolationRegionInfo) const {
1004+ return asImpl ().handleAssignTransferNonTransferrableIntoSendingResult (
1005+ op, destElement, destValue, srcElement, srcValue,
1006+ srcIsolationRegionInfo);
1007+ }
1008+
9991009 // / Call our CRTP subclass.
10001010 void handleInOutSendingNotInitializedAtExitError (
10011011 const PartitionOp &op, Element elt, Operand *transferringOp) const {
@@ -1112,13 +1122,41 @@ struct PartitionOpEvaluator {
11121122 p.pushHistorySequenceBoundary (loc);
11131123
11141124 switch (op.getKind ()) {
1115- case PartitionOpKind::Assign:
1125+ case PartitionOpKind::Assign: {
11161126 assert (op.getOpArgs ().size () == 2 &&
11171127 " Assign PartitionOp should be passed 2 arguments" );
11181128 assert (p.isTrackingElement (op.getOpArgs ()[1 ]) &&
11191129 " Assign PartitionOp's source argument should be already tracked" );
1130+
1131+ // See if we are assigning an a non-disconnected value into a 'out
1132+ // sending' parameter. In such a case, we emit a diagnostic.
1133+ if (op.getSourceInst ()
1134+ ->getFunction ()
1135+ ->getLoweredFunctionType ()
1136+ ->hasSendingResult ()) {
1137+ if (auto instance = getRepresentativeValue (op.getOpArgs ()[0 ])) {
1138+ if (auto value = instance.maybeGetValue ()) {
1139+ if (auto *fArg = dyn_cast<SILFunctionArgument>(value)) {
1140+ if (fArg ->getArgumentConvention ().isIndirectOutParameter ()) {
1141+ Region srcRegion = p.getRegion (op.getOpArgs ()[1 ]);
1142+ auto dynamicRegionIsolation = getIsolationRegionInfo (srcRegion);
1143+ // We can unconditionally getValue here since we can never
1144+ // assign an actor introducing inst.
1145+ auto rep = getRepresentativeValue (op.getOpArgs ()[1 ]).getValue ();
1146+ if (!dynamicRegionIsolation.isDisconnected ()) {
1147+ handleAssignTransferNonTransferrableIntoSendingResult (
1148+ op, op.getOpArgs ()[0 ], fArg , op.getOpArgs ()[1 ], rep,
1149+ dynamicRegionIsolation);
1150+ }
1151+ }
1152+ }
1153+ }
1154+ }
1155+ }
1156+
11201157 p.assignElement (op.getOpArgs ()[0 ], op.getOpArgs ()[1 ]);
11211158 return ;
1159+ }
11221160 case PartitionOpKind::AssignFresh:
11231161 assert (op.getOpArgs ().size () == 1 &&
11241162 " AssignFresh PartitionOp should be passed 1 argument" );
@@ -1199,15 +1237,42 @@ struct PartitionOpEvaluator {
11991237 p.undoTransfer (op.getOpArgs ()[0 ]);
12001238 return ;
12011239 }
1202- case PartitionOpKind::Merge:
1240+ case PartitionOpKind::Merge: {
12031241 assert (op.getOpArgs ().size () == 2 &&
12041242 " Merge PartitionOp should be passed 2 arguments" );
12051243 assert (p.isTrackingElement (op.getOpArgs ()[0 ]) &&
12061244 p.isTrackingElement (op.getOpArgs ()[1 ]) &&
12071245 " Merge PartitionOp's arguments should already be tracked" );
12081246
1247+ // See if we are assigning an a non-disconnected value into a 'out
1248+ // sending' parameter. In such a case, we emit a diagnostic.
1249+ if (op.getSourceInst ()
1250+ ->getFunction ()
1251+ ->getLoweredFunctionType ()
1252+ ->hasSendingResult ()) {
1253+ if (auto instance = getRepresentativeValue (op.getOpArgs ()[0 ])) {
1254+ if (auto value = instance.maybeGetValue ()) {
1255+ if (auto *fArg = dyn_cast<SILFunctionArgument>(value)) {
1256+ if (fArg ->getArgumentConvention ().isIndirectOutParameter ()) {
1257+ Region srcRegion = p.getRegion (op.getOpArgs ()[1 ]);
1258+ auto dynamicRegionIsolation = getIsolationRegionInfo (srcRegion);
1259+ // We can unconditionally getValue here since we can never
1260+ // assign an actor introducing inst.
1261+ auto rep = getRepresentativeValue (op.getOpArgs ()[1 ]).getValue ();
1262+ if (!dynamicRegionIsolation.isDisconnected ()) {
1263+ handleAssignTransferNonTransferrableIntoSendingResult (
1264+ op, op.getOpArgs ()[0 ], fArg , op.getOpArgs ()[1 ], rep,
1265+ dynamicRegionIsolation);
1266+ }
1267+ }
1268+ }
1269+ }
1270+ }
1271+ }
1272+
12091273 p.merge (op.getOpArgs ()[0 ], op.getOpArgs ()[1 ]);
12101274 return ;
1275+ }
12111276 case PartitionOpKind::Require:
12121277 assert (op.getOpArgs ().size () == 1 &&
12131278 " Require PartitionOp should be passed 1 argument" );
@@ -1424,10 +1489,19 @@ struct PartitionOpEvaluatorBaseImpl : PartitionOpEvaluator<Subclass> {
14241489 const PartitionOp &op, Element elt,
14251490 SILDynamicMergedIsolationInfo regionInfo) const {}
14261491
1492+ // / Please see documentation on the CRTP version of this call for information
1493+ // / about this entrypoint.
14271494 void handleTransferNonTransferrable (
14281495 const PartitionOp &op, Element elt, Element otherElement,
14291496 SILDynamicMergedIsolationInfo isolationRegionInfo) const {}
14301497
1498+ // / Please see documentation on the CRTP version of this call for information
1499+ // / about this entrypoint.
1500+ void handleAssignTransferNonTransferrableIntoSendingResult (
1501+ const PartitionOp &partitionOp, Element destElement,
1502+ SILFunctionArgument *destValue, Element srcElement, SILValue srcValue,
1503+ SILDynamicMergedIsolationInfo srcIsolationRegionInfo) const {}
1504+
14311505 // / Used to signify an "unknown code pattern" has occured while performing
14321506 // / dataflow.
14331507 // /
0 commit comments