@@ -530,9 +530,8 @@ ActorIsolationRestriction ActorIsolationRestriction::forDeclaration(
530
530
case DeclKind::Func:
531
531
case DeclKind::Subscript: {
532
532
// Local captures are checked separately.
533
- if (cast<ValueDecl>(decl)->isLocalCapture ()) {
534
- return forLocalCapture (decl->getDeclContext ());
535
- }
533
+ if (cast<ValueDecl>(decl)->isLocalCapture ())
534
+ return forUnrestricted ();
536
535
537
536
// 'let' declarations are immutable, so they can be accessed across
538
537
// actors.
@@ -1280,7 +1279,6 @@ namespace {
1280
1279
auto isolation = ActorIsolationRestriction::forDeclaration (decl);
1281
1280
switch (isolation) {
1282
1281
case ActorIsolationRestriction::Unrestricted:
1283
- case ActorIsolationRestriction::LocalCapture:
1284
1282
case ActorIsolationRestriction::Unsafe:
1285
1283
break ;
1286
1284
case ActorIsolationRestriction::CrossGlobalActor:
@@ -1564,13 +1562,80 @@ namespace {
1564
1562
return knownContexts->second .back ();
1565
1563
}
1566
1564
1565
+ // / Check a reference to a local capture.
1566
+ bool checkLocalCapture (
1567
+ ConcreteDeclRef valueRef, SourceLoc loc, DeclRefExpr *declRefExpr) {
1568
+ auto value = valueRef.getDecl ();
1569
+
1570
+ // Check whether we are in a context that will not execute concurrently
1571
+ // with the context of 'self'. If not, it's safe.
1572
+ if (!mayExecuteConcurrentlyWith (
1573
+ getDeclContext (), findCapturedDeclContext (value)))
1574
+ return false ;
1575
+
1576
+ // Check whether this is a local variable, in which case we can
1577
+ // determine whether it was safe to access concurrently.
1578
+ if (auto var = dyn_cast<VarDecl>(value)) {
1579
+ auto parent = mutableLocalVarParent[declRefExpr];
1580
+
1581
+ // If the variable is immutable, it's fine so long as it involves
1582
+ // ConcurrentValue types.
1583
+ //
1584
+ // When flow-sensitive concurrent captures are enabled, we also
1585
+ // allow reads, depending on a SIL diagnostic pass to identify the
1586
+ // remaining race conditions.
1587
+ if (!var->supportsMutation () ||
1588
+ (ctx.LangOpts .EnableExperimentalFlowSensitiveConcurrentCaptures &&
1589
+ parent.dyn_cast <LoadExpr *>())) {
1590
+ return diagnoseNonConcurrentTypesInReference (
1591
+ valueRef, getDeclContext (), loc,
1592
+ ConcurrentReferenceKind::LocalCapture);
1593
+ }
1594
+
1595
+ // Otherwise, we have concurrent access. Complain.
1596
+ ctx.Diags .diagnose (
1597
+ loc, diag::concurrent_access_of_local_capture,
1598
+ parent.dyn_cast <LoadExpr *>(),
1599
+ var->getDescriptiveKind (), var->getName ());
1600
+ return true ;
1601
+ }
1602
+
1603
+ if (auto func = dyn_cast<FuncDecl>(value)) {
1604
+ if (func->isConcurrent ())
1605
+ return false ;
1606
+
1607
+ func->diagnose (
1608
+ diag::local_function_executed_concurrently,
1609
+ func->getDescriptiveKind (), func->getName ())
1610
+ .fixItInsert (func->getAttributeInsertionLoc (false ), " @concurrent " );
1611
+
1612
+ // Add the @concurrent attribute implicitly, so we don't diagnose
1613
+ // again.
1614
+ const_cast <FuncDecl *>(func)->getAttrs ().add (
1615
+ new (ctx) ConcurrentAttr (true ));
1616
+ return true ;
1617
+ }
1618
+
1619
+ // Concurrent access to some other local.
1620
+ ctx.Diags .diagnose (
1621
+ loc, diag::concurrent_access_local,
1622
+ value->getDescriptiveKind (), value->getName ());
1623
+ value->diagnose (
1624
+ diag::kind_declared_here, value->getDescriptiveKind ());
1625
+ return true ;
1626
+ }
1627
+
1567
1628
// / Check a reference to a local or global.
1568
1629
bool checkNonMemberReference (
1569
1630
ConcreteDeclRef valueRef, SourceLoc loc, DeclRefExpr *declRefExpr) {
1570
1631
if (!valueRef)
1571
1632
return false ;
1572
1633
1573
1634
auto value = valueRef.getDecl ();
1635
+
1636
+ if (value->isLocalCapture ())
1637
+ return checkLocalCapture (valueRef, loc, declRefExpr);
1638
+
1574
1639
switch (auto isolation =
1575
1640
ActorIsolationRestriction::forDeclaration (valueRef)) {
1576
1641
case ActorIsolationRestriction::Unrestricted:
@@ -1586,64 +1651,6 @@ namespace {
1586
1651
valueRef, loc, isolation.getGlobalActor (),
1587
1652
isolation == ActorIsolationRestriction::CrossGlobalActor);
1588
1653
1589
- case ActorIsolationRestriction::LocalCapture:
1590
- // Check whether we are in a context that will not execute concurrently
1591
- // with the context of 'self'. If not, it's safe.
1592
- if (!mayExecuteConcurrentlyWith (
1593
- getDeclContext (), findCapturedDeclContext (value)))
1594
- return false ;
1595
-
1596
- // Check whether this is a local variable, in which case we can
1597
- // determine whether it was safe to access concurrently.
1598
- if (auto var = dyn_cast<VarDecl>(value)) {
1599
- auto parent = mutableLocalVarParent[declRefExpr];
1600
-
1601
- // If the variable is immutable, it's fine so long as it involves
1602
- // ConcurrentValue types.
1603
- //
1604
- // When flow-sensitive concurrent captures are enabled, we also
1605
- // allow reads, depending on a SIL diagnostic pass to identify the
1606
- // remaining race conditions.
1607
- if (!var->supportsMutation () ||
1608
- (ctx.LangOpts .EnableExperimentalFlowSensitiveConcurrentCaptures &&
1609
- parent.dyn_cast <LoadExpr *>())) {
1610
- return diagnoseNonConcurrentTypesInReference (
1611
- valueRef, getDeclContext (), loc,
1612
- ConcurrentReferenceKind::LocalCapture);
1613
- }
1614
-
1615
- // Otherwise, we have concurrent access. Complain.
1616
- ctx.Diags .diagnose (
1617
- loc, diag::concurrent_access_of_local_capture,
1618
- parent.dyn_cast <LoadExpr *>(),
1619
- var->getDescriptiveKind (), var->getName ());
1620
- return true ;
1621
- }
1622
-
1623
- if (auto func = dyn_cast<FuncDecl>(value)) {
1624
- if (func->isConcurrent ())
1625
- return false ;
1626
-
1627
- func->diagnose (
1628
- diag::local_function_executed_concurrently,
1629
- func->getDescriptiveKind (), func->getName ())
1630
- .fixItInsert (func->getAttributeInsertionLoc (false ), " @concurrent " );
1631
-
1632
- // Add the @concurrent attribute implicitly, so we don't diagnose
1633
- // again.
1634
- const_cast <FuncDecl *>(func)->getAttrs ().add (
1635
- new (ctx) ConcurrentAttr (true ));
1636
- return true ;
1637
- }
1638
-
1639
- // Concurrent access to some other local.
1640
- ctx.Diags .diagnose (
1641
- loc, diag::concurrent_access_local,
1642
- value->getDescriptiveKind (), value->getName ());
1643
- value->diagnose (
1644
- diag::kind_declared_here, value->getDescriptiveKind ());
1645
- return true ;
1646
-
1647
1654
case ActorIsolationRestriction::Unsafe:
1648
1655
return diagnoseReferenceToUnsafeGlobal (value, loc);
1649
1656
}
@@ -1794,9 +1801,6 @@ namespace {
1794
1801
memberRef, memberLoc, isolation.getGlobalActor (),
1795
1802
isolation == ActorIsolationRestriction::CrossGlobalActor);
1796
1803
1797
- case ActorIsolationRestriction::LocalCapture:
1798
- llvm_unreachable (" Locals cannot be referenced with member syntax" );
1799
-
1800
1804
case ActorIsolationRestriction::Unsafe:
1801
1805
// This case is hit when passing actor state inout to functions in some
1802
1806
// cases. The error is emitted by diagnoseInOutArg.
0 commit comments