@@ -1574,15 +1574,66 @@ class PartitionOpTranslator {
15741574 }
15751575 }
15761576
1577+ // / Handles the semantics for SIL applies that cross isolation.
1578+ // /
1579+ // / Semantically this causes all arguments of the applysite to be transferred.
1580+ void translateIsolatedPartialApply (PartialApplyInst *pai) {
1581+ ApplySite applySite (pai);
1582+
1583+ // For each argument operand.
1584+ for (auto &op : applySite.getArgumentOperands ()) {
1585+ // See if we tracked it.
1586+ if (auto value = tryToTrackValue (op.get ())) {
1587+ // If we are tracking it, transfer it and if it is actor derived, mark
1588+ // our partial apply as actor derived.
1589+ builder.addTransfer (value->getRepresentative ().getValue (), &op);
1590+ }
1591+ }
1592+
1593+ // Now that we have transferred everything into the partial_apply, perform
1594+ // an assign fresh for the partial_apply. If we use any of the transferred
1595+ // values later, we will error, so it is safe to just create a new value.
1596+ auto paiValue = tryToTrackValue (pai).value ();
1597+ SILValue rep = paiValue.getRepresentative ().getValue ();
1598+ markValueAsActorDerived (rep);
1599+ translateSILAssignFresh (rep);
1600+ }
1601+
15771602 void translateSILPartialApply (PartialApplyInst *pai) {
15781603 assert (!isIsolationBoundaryCrossingApply (pai));
15791604
15801605 // First check if our partial_apply is fed into an async let begin. If so,
15811606 // handle it especially.
1607+ //
1608+ // NOTE: If it is an async_let, then the closure itself will be Sendable. We
1609+ // treat passing in a value into the async Sendable closure as transferring
1610+ // it into the closure.
15821611 if (isAsyncLetBeginPartialApply (pai)) {
15831612 return translateSILPartialApplyAsyncLetBegin (pai);
15841613 }
15851614
1615+ // Then check if our partial apply is Sendable. In such a case, we will have
1616+ // emitted an earlier warning in Sema.
1617+ //
1618+ // DISCUSSION: The reason why we can treat values passed into an async let
1619+ // as transferring safely but it is unsafe to do this for arbitrary Sendable
1620+ // closures is that we do not know how many times the Sendable closure will
1621+ // be executed. It is possible to have different invocations of the Sendable
1622+ // closure to cause races with the captured non-Sendable value. In contrast
1623+ // since we know an async let runs exactly once, we do not need to worry
1624+ // about such a possibility. If we had the ability in the language to
1625+ // specify that a closure is run at most once or that it is always run
1626+ // serially, we could lift this restriction... so for now we leave in the
1627+ // Sema warning and just bail here.
1628+ if (pai->getFunctionType ()->isSendableType ())
1629+ return ;
1630+
1631+ if (auto *ace = pai->getLoc ().getAsASTNode <AbstractClosureExpr>()) {
1632+ if (ace->getActorIsolation ().isActorIsolated ()) {
1633+ return translateIsolatedPartialApply (pai);
1634+ }
1635+ }
1636+
15861637 SILMultiAssignOptions options;
15871638 for (auto arg : pai->getOperandValues ()) {
15881639 if (auto value = tryToTrackValue (arg)) {
0 commit comments