@@ -403,13 +403,26 @@ VarDecl *GlobalActorInstanceRequest::evaluate(
403
403
404
404
Optional<std::pair<CustomAttr *, NominalTypeDecl *>>
405
405
GlobalActorAttributeRequest::evaluate (
406
- Evaluator &evaluator, Decl *decl) const {
407
- ASTContext &ctx = decl->getASTContext ();
408
- auto dc = decl->getDeclContext ();
406
+ Evaluator &evaluator,
407
+ llvm::PointerUnion<Decl *, ClosureExpr *> subject) const {
408
+ DeclContext *dc;
409
+ DeclAttributes *declAttrs;
410
+ SourceLoc loc;
411
+ if (auto decl = subject.dyn_cast <Decl *>()) {
412
+ dc = decl->getDeclContext ();
413
+ declAttrs = &decl->getAttrs ();
414
+ loc = decl->getLoc ();
415
+ } else {
416
+ auto closure = subject.get <ClosureExpr *>();
417
+ dc = closure;
418
+ declAttrs = &closure->getAttrs ();
419
+ loc = closure->getLoc ();
420
+ }
421
+ ASTContext &ctx = dc->getASTContext ();
409
422
CustomAttr *globalActorAttr = nullptr ;
410
423
NominalTypeDecl *globalActorNominal = nullptr ;
411
424
412
- for (auto attr : decl-> getAttrs (). getAttributes <CustomAttr>()) {
425
+ for (auto attr : declAttrs-> getAttributes <CustomAttr>()) {
413
426
auto mutableAttr = const_cast <CustomAttr *>(attr);
414
427
// Figure out which nominal declaration this custom attribute refers to.
415
428
auto nominal = evaluateOrDefault (ctx.evaluator ,
@@ -424,10 +437,10 @@ GlobalActorAttributeRequest::evaluate(
424
437
if (!nominal->isGlobalActor ())
425
438
continue ;
426
439
427
- // Only a single global actor can be applied to a given declaration .
440
+ // Only a single global actor can be applied to a given entity .
428
441
if (globalActorAttr) {
429
- decl-> diagnose (
430
- diag::multiple_global_actors, globalActorNominal->getName (),
442
+ ctx. Diags . diagnose (
443
+ loc, diag::multiple_global_actors, globalActorNominal->getName (),
431
444
nominal->getName ());
432
445
continue ;
433
446
}
@@ -439,8 +452,14 @@ GlobalActorAttributeRequest::evaluate(
439
452
if (!globalActorAttr)
440
453
return None;
441
454
455
+ // Closures can always have a global actor attached.
456
+ if (auto closure = subject.dyn_cast <ClosureExpr *>()) {
457
+ return std::make_pair (globalActorAttr, globalActorNominal);
458
+ }
459
+
442
460
// Check that a global actor attribute makes sense on this kind of
443
461
// declaration.
462
+ auto decl = subject.get <Decl *>();
444
463
if (auto nominal = dyn_cast<NominalTypeDecl>(decl)) {
445
464
// Nominal types are okay...
446
465
if (auto classDecl = dyn_cast<ClassDecl>(nominal)){
@@ -1384,8 +1403,13 @@ namespace {
1384
1403
1385
1404
auto dc = const_cast <DeclContext *>(constDC);
1386
1405
while (!dc->isModuleScopeContext ()) {
1387
- // Look through non-escaping closures.
1388
1406
if (auto closure = dyn_cast<AbstractClosureExpr>(dc)) {
1407
+ // If this closure has specific isolation, use it.
1408
+ auto closureIsolation = getActorIsolationOfContext (dc);
1409
+ if (closureIsolation != ActorIsolation::Independent)
1410
+ return closureIsolation;
1411
+
1412
+ // Look through non-escaping closures.
1389
1413
if (auto type = closure->getType ()) {
1390
1414
if (auto fnType = type->getAs <AnyFunctionType>()) {
1391
1415
if (fnType->isNoEscape ()) {
@@ -1816,12 +1840,50 @@ namespace {
1816
1840
llvm_unreachable (" unhandled actor isolation kind!" );
1817
1841
}
1818
1842
1843
+ // Attempt to resolve the global actor type of a closure.
1844
+ Type resolveGlobalActorType (ClosureExpr *closure) {
1845
+ auto globalActorAttr = evaluateOrDefault (
1846
+ ctx.evaluator , GlobalActorAttributeRequest{closure}, None);
1847
+ if (!globalActorAttr)
1848
+ return Type ();
1849
+
1850
+ Type globalActor = evaluateOrDefault (
1851
+ ctx.evaluator ,
1852
+ CustomAttrTypeRequest{
1853
+ globalActorAttr->first , closure, CustomAttrTypeKind::GlobalActor},
1854
+ Type ());
1855
+ if (!globalActor || globalActor->hasError ())
1856
+ return Type ();
1857
+
1858
+ // Actor-isolated closures must be async.
1859
+ bool isAsync = false ;
1860
+ if (Type closureType = closure->getType ()) {
1861
+ if (auto closureFnType = closureType->getAs <FunctionType>())
1862
+ isAsync = closureFnType->isAsync ();
1863
+ }
1864
+
1865
+ if (!isAsync) {
1866
+ ctx.Diags .diagnose (
1867
+ closure->getLoc (), diag::global_actor_isolated_synchronous_closure,
1868
+ globalActor);
1869
+ return Type ();
1870
+ }
1871
+
1872
+ return globalActor;
1873
+ }
1874
+
1819
1875
// / Determine the isolation of a particular closure.
1820
1876
// /
1821
1877
// / This function assumes that enclosing closures have already had their
1822
1878
// / isolation checked.
1823
1879
ClosureActorIsolation determineClosureIsolation (
1824
1880
AbstractClosureExpr *closure) {
1881
+ // If the closure specifies a global actor, use it.
1882
+ if (auto explicitClosure = dyn_cast<ClosureExpr>(closure)) {
1883
+ if (Type globalActorType = resolveGlobalActorType (explicitClosure))
1884
+ return ClosureActorIsolation::forGlobalActor (globalActorType);
1885
+ }
1886
+
1825
1887
// Escaping and concurrent closures are always actor-independent.
1826
1888
if (isEscapingClosure (closure) || isConcurrentClosure (closure))
1827
1889
return ClosureActorIsolation::forIndependent ();
0 commit comments