@@ -587,7 +587,7 @@ Type swift::getExplicitGlobalActor(ClosureExpr *closure) {
587
587
588
588
// / Determine the isolation rules for a given declaration.
589
589
ActorIsolationRestriction ActorIsolationRestriction::forDeclaration (
590
- ConcreteDeclRef declRef) {
590
+ ConcreteDeclRef declRef, bool fromExpression ) {
591
591
auto decl = declRef.getDecl ();
592
592
593
593
switch (decl->getKind ()) {
@@ -673,6 +673,13 @@ ActorIsolationRestriction ActorIsolationRestriction::forDeclaration(
673
673
674
674
case ActorIsolation::GlobalActorUnsafe:
675
675
case ActorIsolation::GlobalActor: {
676
+ // A global-actor-isolated function referenced within an expression
677
+ // carries the global actor into its function type. The actual
678
+ // reference to the function is therefore not restricted, because the
679
+ // call to the function is.
680
+ if (fromExpression && isa<AbstractFunctionDecl>(decl))
681
+ return forUnrestricted ();
682
+
676
683
Type actorType = isolation.getGlobalActor ();
677
684
if (auto subs = declRef.getSubstitutions ())
678
685
actorType = actorType.subst (subs);
@@ -1276,6 +1283,9 @@ namespace {
1276
1283
if (auto apply = dyn_cast<ApplyExpr>(expr)) {
1277
1284
applyStack.push_back (apply); // record this encounter
1278
1285
1286
+ // Check the call itself.
1287
+ (void )checkApply (apply);
1288
+
1279
1289
// If this is a call to a partial apply thunk, decompose it to check it
1280
1290
// like based on the original written syntax, e.g., "self.method".
1281
1291
if (auto partialApply = decomposePartialApplyThunk (
@@ -1411,6 +1421,33 @@ namespace {
1411
1421
return nullptr ;
1412
1422
}
1413
1423
1424
+ // / Note when the enclosing context could be put on a global actor.
1425
+ void noteGlobalActorOnContext (DeclContext *dc, Type globalActor) {
1426
+ // If we are in a synchronous function on the global actor,
1427
+ // suggest annotating with the global actor itself.
1428
+ if (auto fn = dyn_cast<FuncDecl>(dc)) {
1429
+ if (!isa<AccessorDecl>(fn) && !fn->isAsyncContext ()) {
1430
+ switch (getActorIsolation (fn)) {
1431
+ case ActorIsolation::ActorInstance:
1432
+ case ActorIsolation::GlobalActor:
1433
+ case ActorIsolation::GlobalActorUnsafe:
1434
+ case ActorIsolation::Independent:
1435
+ return ;
1436
+
1437
+ case ActorIsolation::Unspecified:
1438
+ fn->diagnose (diag::note_add_globalactor_to_function,
1439
+ globalActor->getWithoutParens ().getString (),
1440
+ fn->getDescriptiveKind (),
1441
+ fn->getName (),
1442
+ globalActor)
1443
+ .fixItInsert (fn->getAttributeInsertionLoc (false ),
1444
+ diag::insert_globalactor_attr, globalActor);
1445
+ return ;
1446
+ }
1447
+ }
1448
+ }
1449
+ }
1450
+
1414
1451
// / Note that the given actor member is isolated.
1415
1452
// / @param context is allowed to be null if no context is appropriate.
1416
1453
void noteIsolatedActorMember (ValueDecl *decl, Expr *context) {
@@ -1672,6 +1709,86 @@ namespace {
1672
1709
return result;
1673
1710
}
1674
1711
1712
+ // / Check actor isolation for a particular application.
1713
+ bool checkApply (ApplyExpr *apply) {
1714
+ auto fnExprType = apply->getFn ()->getType ();
1715
+ if (!fnExprType)
1716
+ return false ;
1717
+
1718
+ auto fnType = fnExprType->getAs <FunctionType>();
1719
+ if (!fnType)
1720
+ return false ;
1721
+
1722
+ // Handle calls to global-actor-qualified functions.
1723
+ Type globalActor = fnType->getGlobalActor ();
1724
+ if (!globalActor)
1725
+ return false ;
1726
+
1727
+ auto declContext = const_cast <DeclContext *>(getDeclContext ());
1728
+
1729
+ // Check whether we are within the same isolation context, in which
1730
+ // case there is nothing further to check,
1731
+ auto contextIsolation = getInnermostIsolatedContext (declContext);
1732
+ if (contextIsolation.isGlobalActor () &&
1733
+ contextIsolation.getGlobalActor ()->isEqual (globalActor)) {
1734
+ return false ;
1735
+ }
1736
+
1737
+ // From this point on, the only possibility is that we have an implicitly
1738
+ // aynchronous call.
1739
+
1740
+ // If we are not in an asynchronous context, complain.
1741
+ if (!isInAsynchronousContext ()) {
1742
+ auto isolation = ActorIsolation::forGlobalActor (
1743
+ globalActor, /* unsafe=*/ false );
1744
+ if (auto calleeDecl = apply->getCalledValue ()) {
1745
+ ctx.Diags .diagnose (
1746
+ apply->getLoc (), diag::actor_isolated_call_decl, isolation,
1747
+ calleeDecl->getDescriptiveKind (), calleeDecl->getName (),
1748
+ contextIsolation);
1749
+ calleeDecl->diagnose (
1750
+ diag::actor_isolated_sync_func, calleeDecl->getDescriptiveKind (),
1751
+ calleeDecl->getName ());
1752
+ } else {
1753
+ ctx.Diags .diagnose (
1754
+ apply->getLoc (), diag::actor_isolated_call, isolation,
1755
+ contextIsolation);
1756
+ }
1757
+ noteGlobalActorOnContext (
1758
+ const_cast <DeclContext *>(getDeclContext ()), globalActor);
1759
+
1760
+ return true ;
1761
+ }
1762
+
1763
+ // Mark as implicitly async.
1764
+ apply->setImplicitlyAsync (true );
1765
+
1766
+ // If we don't need to check for sendability, we're done.
1767
+ if (!shouldDiagnoseNonSendableViolations (ctx.LangOpts ))
1768
+ return false ;
1769
+
1770
+ // Check for sendability of the parameter types.
1771
+ for (const auto ¶m : fnType->getParams ()) {
1772
+ // FIXME: Dig out the locations of the corresponding arguments.
1773
+ if (!isSendableType (getDeclContext (), param.getParameterType ())) {
1774
+ ctx.Diags .diagnose (
1775
+ apply->getLoc (), diag::non_concurrent_param_type,
1776
+ param.getParameterType ());
1777
+ return true ;
1778
+ }
1779
+ }
1780
+
1781
+ // Check for sendability of the result type.
1782
+ if (!isSendableType (getDeclContext (), fnType->getResult ())) {
1783
+ ctx.Diags .diagnose (
1784
+ apply->getLoc (), diag::non_concurrent_result_type,
1785
+ fnType->getResult ());
1786
+ return true ;
1787
+ }
1788
+
1789
+ return false ;
1790
+ }
1791
+
1675
1792
// / Check a reference to an entity within a global actor.
1676
1793
bool checkGlobalActorReference (
1677
1794
ConcreteDeclRef valueRef, SourceLoc loc, Type globalActor,
@@ -1763,21 +1880,7 @@ namespace {
1763
1880
value->getDescriptiveKind (), value->getName (), globalActor,
1764
1881
/* actorIndependent=*/ false , useKind,
1765
1882
result == AsyncMarkingResult::SyncContext);
1766
-
1767
- // If we are in a synchronous function on the global actor,
1768
- // suggest annotating with the global actor itself.
1769
- if (auto fn = dyn_cast<FuncDecl>(declContext)) {
1770
- if (!isa<AccessorDecl>(fn) && !fn->isAsyncContext ()) {
1771
- fn->diagnose (diag::note_add_globalactor_to_function,
1772
- globalActor->getWithoutParens ().getString (),
1773
- fn->getDescriptiveKind (),
1774
- fn->getName (),
1775
- globalActor)
1776
- .fixItInsert (fn->getAttributeInsertionLoc (false ),
1777
- diag::insert_globalactor_attr, globalActor);
1778
- }
1779
- }
1780
-
1883
+ noteGlobalActorOnContext (declContext, globalActor);
1781
1884
noteIsolatedActorMember (value, context);
1782
1885
1783
1886
return true ;
@@ -2733,10 +2836,10 @@ ActorIsolation ActorIsolationRequest::evaluate(
2733
2836
if (!isAsyncHandler (value)) {
2734
2837
auto isolation = getActorIsolation (overriddenValue);
2735
2838
SubstitutionMap subs;
2736
- if ( auto env = value-> getInnermostDeclContext ()
2737
- -> getGenericEnvironmentOfContext ()) {
2738
- subs = SubstitutionMap::getOverrideSubstitutions (
2739
- overriddenValue, value, subs );
2839
+
2840
+ if (Type selfType = value-> getDeclContext ()-> getSelfInterfaceType ()) {
2841
+ subs = selfType-> getMemberSubstitutionMap (
2842
+ value-> getModuleContext (), overriddenValue );
2740
2843
}
2741
2844
2742
2845
return inferredIsolation (isolation.subst (subs));
@@ -2881,11 +2984,12 @@ void swift::checkOverrideActorIsolation(ValueDecl *value) {
2881
2984
2882
2985
if (overriddenIsolation.requiresSubstitution ()) {
2883
2986
SubstitutionMap subs;
2884
- if (auto env = value->getInnermostDeclContext ()
2885
- ->getGenericEnvironmentOfContext ()) {
2886
- subs = SubstitutionMap::getOverrideSubstitutions (overridden, value, subs);
2887
- overriddenIsolation = overriddenIsolation.subst (subs);
2987
+ if (Type selfType = value->getDeclContext ()->getSelfInterfaceType ()) {
2988
+ subs = selfType->getMemberSubstitutionMap (
2989
+ value->getModuleContext (), overridden);
2888
2990
}
2991
+
2992
+ overriddenIsolation = overriddenIsolation.subst (subs);
2889
2993
}
2890
2994
2891
2995
// If the isolation matches, we're done.
0 commit comments