@@ -520,6 +520,11 @@ namespace {
520
520
// / a remote distributed actor in the given context.
521
521
bool isDistributedThunk (ConcreteDeclRef ref, Expr *context);
522
522
523
+ // / Determine whether the given reference on the given
524
+ // / base has to be replaced with a distributed thunk instead.
525
+ bool requiresDistributedThunk (Expr *base, SourceLoc memberLoc,
526
+ ConcreteDeclRef memberRef);
527
+
523
528
public:
524
529
// / Build a reference to the given declaration.
525
530
Expr *buildDeclRef (SelectedOverload overload, DeclNameLoc loc,
@@ -1615,6 +1620,64 @@ namespace {
1615
1620
return forceUnwrapIfExpected (ref, memberLocator);
1616
1621
}
1617
1622
1623
+ if (requiresDistributedThunk (base, memberLoc.getStartLoc (), memberRef)) {
1624
+ auto *decl = memberRef.getDecl ();
1625
+ FuncDecl *thunkDecl = nullptr ;
1626
+ if (auto *FD = dyn_cast<FuncDecl>(decl)) {
1627
+ thunkDecl = FD->getDistributedThunk ();
1628
+ } else {
1629
+ thunkDecl = cast<VarDecl>(decl)->getDistributedThunk ();
1630
+ }
1631
+
1632
+ if (!thunkDecl)
1633
+ return nullptr ;
1634
+
1635
+ auto thunkType = refTy;
1636
+ auto thunkOpenedType = openedType;
1637
+
1638
+ // If this is a reference to a computed property then we need to
1639
+ // form a function type from it with unapplied Self so
1640
+ // (Self) -> T becomes (Self) -> () -> T
1641
+ if (isa<VarDecl>(decl)) {
1642
+ auto extInfo = ASTExtInfoBuilder ().withAsync ().withThrows ().build ();
1643
+
1644
+ thunkOpenedType =
1645
+ FunctionType::get (/* params=*/ {}, thunkOpenedType, extInfo);
1646
+ thunkType =
1647
+ FunctionType::get ({FunctionType::Param (selfTy)}, thunkOpenedType);
1648
+ }
1649
+
1650
+ ConcreteDeclRef thunkRef{thunkDecl, memberRef.getSubstitutions ()};
1651
+
1652
+ auto declRefExpr = new (context) DeclRefExpr (
1653
+ thunkRef, memberLoc, Implicit, AccessSemantics::DirectToStorage);
1654
+
1655
+ declRefExpr->setFunctionRefKind (choice.getFunctionRefKind ());
1656
+ declRefExpr->setType (thunkType);
1657
+
1658
+ cs.cacheType (declRefExpr);
1659
+
1660
+ Expr *thunkApply =
1661
+ DotSyntaxCallExpr::create (context, declRefExpr, dotLoc, base);
1662
+ if (Implicit)
1663
+ thunkApply->setImplicit ();
1664
+
1665
+ thunkApply = finishApply (cast<ApplyExpr>(thunkApply), thunkOpenedType,
1666
+ locator, memberLocator);
1667
+
1668
+ // If this is access to a computed property, that requires
1669
+ // implicit call.
1670
+ if (isa<VarDecl>(decl)) {
1671
+ auto *thunkCall = CallExpr::createImplicitEmpty (context, thunkApply);
1672
+ thunkCall->setType (solution.simplifyType (openedType));
1673
+ thunkCall->setShouldApplyDistributedThunk (true );
1674
+ cs.cacheType (thunkCall);
1675
+ return thunkCall;
1676
+ }
1677
+
1678
+ return thunkApply;
1679
+ }
1680
+
1618
1681
// For properties, build member references.
1619
1682
if (auto *varDecl = dyn_cast<VarDecl>(member)) {
1620
1683
if (isUnboundInstanceMember) {
@@ -1662,8 +1725,9 @@ namespace {
1662
1725
refTy = refTy->replaceCovariantResultType (containerTy, 2 );
1663
1726
1664
1727
// Handle all other references.
1665
- auto declRefExpr = new (context) DeclRefExpr (memberRef, memberLoc,
1666
- Implicit, semantics);
1728
+ auto declRefExpr =
1729
+ new (context) DeclRefExpr (memberRef, memberLoc, Implicit, semantics);
1730
+
1667
1731
declRefExpr->setFunctionRefKind (choice.getFunctionRefKind ());
1668
1732
declRefExpr->setType (refTy);
1669
1733
cs.setType (declRefExpr, refTy);
@@ -7734,6 +7798,9 @@ Expr *ExprRewriter::finishApply(ApplyExpr *apply, Type openedType,
7734
7798
auto *FD = cast<AbstractFunctionDecl>(callee.getDecl ());
7735
7799
if (!FD->hasThrows ())
7736
7800
apply->setImplicitlyThrows (true );
7801
+ if (!FD->hasAsync ())
7802
+ apply->setImplicitlyAsync (ImplicitActorHopTarget::forInstanceSelf ());
7803
+ apply->setShouldApplyDistributedThunk (true );
7737
7804
}
7738
7805
7739
7806
solution.setExprTypes (apply);
@@ -7853,16 +7920,29 @@ Expr *ExprRewriter::finishApply(ApplyExpr *apply, Type openedType,
7853
7920
}
7854
7921
7855
7922
bool ExprRewriter::isDistributedThunk (ConcreteDeclRef ref, Expr *context) {
7856
- auto *FD = dyn_cast_or_null<AbstractFunctionDecl>(ref.getDecl ());
7857
- if (!(FD && FD->isInstanceMember () && FD->isDistributed ()))
7858
- return false ;
7859
-
7860
7923
if (!isa<SelfApplyExpr>(context))
7861
7924
return false ;
7862
7925
7926
+ return requiresDistributedThunk (cast<SelfApplyExpr>(context)->getBase (),
7927
+ context->getLoc (), ref);
7928
+ }
7929
+
7930
+ bool ExprRewriter::requiresDistributedThunk (Expr *base, SourceLoc memberLoc,
7931
+ ConcreteDeclRef memberRef) {
7932
+
7933
+ auto *memberDecl = memberRef.getDecl ();
7934
+ assert (memberDecl);
7935
+
7936
+ if (auto *FD = dyn_cast<AbstractFunctionDecl>(memberDecl)) {
7937
+ if (!(FD->isInstanceMember () && FD->isDistributed ()))
7938
+ return false ;
7939
+ } else if (auto *VD = dyn_cast<VarDecl>(memberDecl)) {
7940
+ if (!VD->isDistributed ())
7941
+ return false ;
7942
+ }
7943
+
7863
7944
auto *actor = getReferencedParamOrCapture (
7864
- cast<SelfApplyExpr>(context)->getBase (),
7865
- [&](OpaqueValueExpr *opaqueValue) -> Expr * {
7945
+ base, [&](OpaqueValueExpr *opaqueValue) -> Expr * {
7866
7946
for (const auto &existential : OpenedExistentials) {
7867
7947
if (existential.OpaqueValue == opaqueValue)
7868
7948
return existential.ExistentialValue ;
@@ -7921,7 +8001,7 @@ bool ExprRewriter::isDistributedThunk(ConcreteDeclRef ref, Expr *context) {
7921
8001
ReferencedActor actorRef = ReferencedActor (
7922
8002
actor, isPotentiallyIsolated, ReferencedActor::NonIsolatedContext);
7923
8003
auto refResult = ActorReferenceResult::forReference (
7924
- ref, context-> getLoc () , referenceDC, None, actorRef);
8004
+ memberRef, memberLoc , referenceDC, None, actorRef);
7925
8005
switch (refResult) {
7926
8006
case ActorReferenceResult::ExitsActorToNonisolated:
7927
8007
case ActorReferenceResult::SameConcurrencyDomain:
0 commit comments