@@ -520,6 +520,11 @@ namespace {
520520 // / a remote distributed actor in the given context.
521521 bool isDistributedThunk (ConcreteDeclRef ref, Expr *context);
522522
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+
523528 public:
524529 // / Build a reference to the given declaration.
525530 Expr *buildDeclRef (SelectedOverload overload, DeclNameLoc loc,
@@ -1615,6 +1620,64 @@ namespace {
16151620 return forceUnwrapIfExpected (ref, memberLocator);
16161621 }
16171622
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+
16181681 // For properties, build member references.
16191682 if (auto *varDecl = dyn_cast<VarDecl>(member)) {
16201683 if (isUnboundInstanceMember) {
@@ -1662,8 +1725,9 @@ namespace {
16621725 refTy = refTy->replaceCovariantResultType (containerTy, 2 );
16631726
16641727 // 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+
16671731 declRefExpr->setFunctionRefKind (choice.getFunctionRefKind ());
16681732 declRefExpr->setType (refTy);
16691733 cs.setType (declRefExpr, refTy);
@@ -7731,6 +7795,9 @@ Expr *ExprRewriter::finishApply(ApplyExpr *apply, Type openedType,
77317795 auto *FD = cast<AbstractFunctionDecl>(callee.getDecl ());
77327796 if (!FD->hasThrows ())
77337797 apply->setImplicitlyThrows (true );
7798+ if (!FD->hasAsync ())
7799+ apply->setImplicitlyAsync (ImplicitActorHopTarget::forInstanceSelf ());
7800+ apply->setShouldApplyDistributedThunk (true );
77347801 }
77357802
77367803 solution.setExprTypes (apply);
@@ -7850,16 +7917,29 @@ Expr *ExprRewriter::finishApply(ApplyExpr *apply, Type openedType,
78507917}
78517918
78527919bool ExprRewriter::isDistributedThunk (ConcreteDeclRef ref, Expr *context) {
7853- auto *FD = dyn_cast_or_null<AbstractFunctionDecl>(ref.getDecl ());
7854- if (!(FD && FD->isInstanceMember () && FD->isDistributed ()))
7855- return false ;
7856-
78577920 if (!isa<SelfApplyExpr>(context))
78587921 return false ;
78597922
7923+ return requiresDistributedThunk (cast<SelfApplyExpr>(context)->getBase (),
7924+ context->getLoc (), ref);
7925+ }
7926+
7927+ bool ExprRewriter::requiresDistributedThunk (Expr *base, SourceLoc memberLoc,
7928+ ConcreteDeclRef memberRef) {
7929+
7930+ auto *memberDecl = memberRef.getDecl ();
7931+ assert (memberDecl);
7932+
7933+ if (auto *FD = dyn_cast<AbstractFunctionDecl>(memberDecl)) {
7934+ if (!(FD->isInstanceMember () && FD->isDistributed ()))
7935+ return false ;
7936+ } else if (auto *VD = dyn_cast<VarDecl>(memberDecl)) {
7937+ if (!VD->isDistributed ())
7938+ return false ;
7939+ }
7940+
78607941 auto *actor = getReferencedParamOrCapture (
7861- cast<SelfApplyExpr>(context)->getBase (),
7862- [&](OpaqueValueExpr *opaqueValue) -> Expr * {
7942+ base, [&](OpaqueValueExpr *opaqueValue) -> Expr * {
78637943 for (const auto &existential : OpenedExistentials) {
78647944 if (existential.OpaqueValue == opaqueValue)
78657945 return existential.ExistentialValue ;
@@ -7918,7 +7998,7 @@ bool ExprRewriter::isDistributedThunk(ConcreteDeclRef ref, Expr *context) {
79187998 ReferencedActor actorRef = ReferencedActor (
79197999 actor, isPotentiallyIsolated, ReferencedActor::NonIsolatedContext);
79208000 auto refResult = ActorReferenceResult::forReference (
7921- ref, context-> getLoc () , referenceDC, None, actorRef);
8001+ memberRef, memberLoc , referenceDC, None, actorRef);
79228002 switch (refResult) {
79238003 case ActorReferenceResult::ExitsActorToNonisolated:
79248004 case ActorReferenceResult::SameConcurrencyDomain:
0 commit comments