Skip to content

Commit 49edef8

Browse files
authored
Merge pull request #37304 from DougGregor/revert-nonisolated
[Concurrency] Revert 'nonisolated let' change.
2 parents 40c7341 + 052cc7d commit 49edef8

11 files changed

+95
-69
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4448,9 +4448,6 @@ NOTE(actor_isolated_sync_func,none,
44484448
NOTE(actor_mutable_state,none,
44494449
"mutation of this %0 is only permitted within the actor",
44504450
(DescriptiveDeclKind))
4451-
NOTE(actor_isolated_let,none,
4452-
"use `nonisolated` to allow synchronous access to 'let' from outside "
4453-
"the actor", ())
44544451
WARNING(shared_mutable_state_access,none,
44554452
"reference to %0 %1 is not concurrency-safe because it involves "
44564453
"shared mutable state", (DescriptiveDeclKind, DeclName))
@@ -4483,12 +4480,13 @@ WARNING(non_concurrent_property_type,none,
44834480
WARNING(non_concurrent_keypath_capture,none,
44844481
"cannot form key path that captures non-sendable type %0",
44854482
(Type))
4483+
WARNING(non_concurrent_keypath_access,none,
4484+
"cannot form key path that accesses non-sendable type %0",
4485+
(Type))
44864486
ERROR(non_concurrent_type_member,none,
44874487
"%select{stored property %1|associated value %1}0 of "
44884488
"'Sendable'-conforming %2 %3 has non-sendable type %4",
44894489
(bool, DeclName, DescriptiveDeclKind, DeclName, Type))
4490-
ERROR(non_sendable_nonisolated_let,none,
4491-
"non-isolated let property %0 has non-Sendable type %1", (DeclName, Type))
44924490
ERROR(concurrent_value_class_mutable_property,none,
44934491
"stored property %0 of 'Sendable'-conforming %1 %2 is mutable",
44944492
(DeclName, DescriptiveDeclKind, DeclName))
@@ -4504,13 +4502,21 @@ ERROR(concurrent_value_inherit,none,
45044502
"%select{| other than 'NSObject'}0",
45054503
(bool, DeclName))
45064504

4505+
ERROR(actorindependent_let,none,
4506+
"'@actorIndependent' is meaningless on 'let' declarations because "
4507+
"they are immutable",
4508+
())
45074509
ERROR(actorindependent_mutable_storage,none,
45084510
"'@actorIndependent' can not be applied to stored properties",
45094511
())
45104512
ERROR(actorindependent_local_var,none,
45114513
"'@actorIndependent' can not be applied to local variables",
45124514
())
45134515

4516+
ERROR(nonisolated_let,none,
4517+
"'nonisolated' is meaningless on 'let' declarations because "
4518+
"they are immutable",
4519+
())
45144520
ERROR(nonisolated_mutable_storage,none,
45154521
"nonisolated' can not be applied to stored properties",
45164522
())

lib/Sema/TypeCheckAttr.cpp

Lines changed: 16 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -5420,14 +5420,17 @@ void AttributeChecker::visitActorIndependentAttr(ActorIndependentAttr *attr) {
54205420
// that do not have storage.
54215421
auto dc = D->getDeclContext();
54225422
if (auto var = dyn_cast<VarDecl>(D)) {
5423-
// @actorIndependent can not be applied to mutable stored properties, unless if
5423+
// @actorIndependent is meaningless on a `let`.
5424+
if (var->isLet()) {
5425+
diagnoseAndRemoveAttr(attr, diag::actorindependent_let);
5426+
return;
5427+
}
5428+
5429+
// @actorIndependent can not be applied to stored properties, unless if
54245430
// the 'unsafe' option was specified
54255431
if (var->hasStorage()) {
54265432
switch (attr->getKind()) {
54275433
case ActorIndependentKind::Safe:
5428-
if (var->isLet())
5429-
break;
5430-
54315434
diagnoseAndRemoveAttr(attr, diag::actorindependent_mutable_storage);
54325435
return;
54335436

@@ -5459,20 +5462,16 @@ void AttributeChecker::visitNonisolatedAttr(NonisolatedAttr *attr) {
54595462
// that do not have storage.
54605463
auto dc = D->getDeclContext();
54615464
if (auto var = dyn_cast<VarDecl>(D)) {
5462-
// 'nonisolated' can only be applied to 'let' stored properties.
5463-
// Those must be Sendable.
5464-
if (var->hasStorage()) {
5465-
if (!var->isLet()) {
5466-
diagnoseAndRemoveAttr(attr, diag::nonisolated_mutable_storage);
5467-
return;
5468-
}
5465+
// 'nonisolated' is meaningless on a `let`.
5466+
if (var->isLet()) {
5467+
diagnoseAndRemoveAttr(attr, diag::nonisolated_let);
5468+
return;
5469+
}
54695470

5470-
// nonisolated lets must have Sendable type.
5471-
if (shouldDiagnoseNonSendableViolations(dc->getASTContext().LangOpts) &&
5472-
!isSendableType(dc, var->getType())) {
5473-
var->diagnose(
5474-
diag::non_sendable_nonisolated_let, var->getName(), var->getType());
5475-
}
5471+
// 'nonisolated' can not be applied to stored properties.
5472+
if (var->hasStorage()) {
5473+
diagnoseAndRemoveAttr(attr, diag::nonisolated_mutable_storage);
5474+
return;
54765475
}
54775476

54785477
// @actorIndependent can not be applied to local properties.

lib/Sema/TypeCheckConcurrency.cpp

Lines changed: 46 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -602,14 +602,21 @@ ActorIsolationRestriction ActorIsolationRestriction::forDeclaration(
602602
if (cast<ValueDecl>(decl)->isLocalCapture())
603603
return forUnrestricted();
604604

605+
// 'let' declarations are immutable, so they can be accessed across
606+
// actors.
607+
bool isAccessibleAcrossActors = false;
608+
if (auto var = dyn_cast<VarDecl>(decl)) {
609+
if (var->isLet())
610+
isAccessibleAcrossActors = true;
611+
}
612+
605613
// A function that provides an asynchronous context has no restrictions
606614
// on its access.
607615
//
608616
// FIXME: technically, synchronous functions are allowed to be cross-actor.
609617
// The call-sites are just conditionally async based on where they appear
610618
// (outside or inside the actor). This suggests that the implicitly-async
611619
// concept could be merged into the CrossActorSelf concept.
612-
bool isAccessibleAcrossActors = false;
613620
if (auto func = dyn_cast<AbstractFunctionDecl>(decl)) {
614621
if (func->isAsyncContext())
615622
isAccessibleAcrossActors = true;
@@ -922,7 +929,8 @@ static bool diagnoseNonConcurrentProperty(
922929

923930
/// Whether we should diagnose cases where Sendable conformances are
924931
/// missing.
925-
bool swift::shouldDiagnoseNonSendableViolations(const LangOptions &langOpts) {
932+
static bool shouldDiagnoseNonSendableViolations(
933+
const LangOptions &langOpts) {
926934
return langOpts.WarnConcurrency;
927935
}
928936

@@ -1426,17 +1434,11 @@ namespace {
14261434
// was it an attempt to mutate an actor instance's isolated state?
14271435
} else if (auto environment = kindOfUsage(decl, context)) {
14281436

1429-
if (isa<VarDecl>(decl) && cast<VarDecl>(decl)->isLet()) {
1430-
auto diag = decl->diagnose(diag::actor_isolated_let);
1431-
SourceLoc fixItLoc =
1432-
decl->getAttributeInsertionLoc(/*forModifier=*/true);
1433-
if (fixItLoc.isValid())
1434-
diag.fixItInsert(fixItLoc, "nonisolated ");
1435-
} else if (environment.getValue() == VarRefUseEnv::Read) {
1437+
if (environment.getValue() == VarRefUseEnv::Read)
14361438
decl->diagnose(diag::kind_declared_here, decl->getDescriptiveKind());
1437-
} else {
1439+
else
14381440
decl->diagnose(diag::actor_mutable_state, decl->getDescriptiveKind());
1439-
}
1441+
14401442
} else {
14411443
decl->diagnose(diag::kind_declared_here, decl->getDescriptiveKind());
14421444
}
@@ -1609,6 +1611,11 @@ namespace {
16091611

16101612
// is it an access to a property?
16111613
if (isPropOrSubscript(decl)) {
1614+
// we assume let-bound properties are taken care of elsewhere,
1615+
// since they are never implicitly async.
1616+
assert(!isa<VarDecl>(decl) || cast<VarDecl>(decl)->isLet() == false
1617+
&& "unexpected let-bound property; never implicitly async!");
1618+
16121619
if (auto declRef = dyn_cast_or_null<DeclRefExpr>(context)) {
16131620
if (usageEnv(declRef) == VarRefUseEnv::Read) {
16141621

@@ -1943,6 +1950,27 @@ namespace {
19431950
bool checkKeyPathExpr(KeyPathExpr *keyPath) {
19441951
bool diagnosed = false;
19451952

1953+
// returns None if it is not a 'let'-bound var decl. Otherwise,
1954+
// the bool indicates whether a diagnostic was emitted.
1955+
auto checkLetBoundVarDecl = [&](KeyPathExpr::Component const& component)
1956+
-> Optional<bool> {
1957+
auto decl = component.getDeclRef().getDecl();
1958+
if (auto varDecl = dyn_cast<VarDecl>(decl)) {
1959+
if (varDecl->isLet()) {
1960+
auto type = component.getComponentType();
1961+
if (shouldDiagnoseNonSendableViolations(ctx.LangOpts)
1962+
&& !isSendableType(getDeclContext(), type)) {
1963+
ctx.Diags.diagnose(
1964+
component.getLoc(), diag::non_concurrent_keypath_access,
1965+
type);
1966+
return true;
1967+
}
1968+
return false;
1969+
}
1970+
}
1971+
return None;
1972+
};
1973+
19461974
// check the components of the keypath.
19471975
for (const auto &component : keyPath->getComponents()) {
19481976
// The decl referred to by the path component cannot be within an actor.
@@ -1970,6 +1998,13 @@ namespace {
19701998
LLVM_FALLTHROUGH; // otherwise, it's invalid so diagnose it.
19711999

19722000
case ActorIsolationRestriction::CrossActorSelf:
2001+
// 'let'-bound decls with this isolation are OK, just check them.
2002+
if (auto wasLetBound = checkLetBoundVarDecl(component)) {
2003+
diagnosed = wasLetBound.getValue();
2004+
break;
2005+
}
2006+
LLVM_FALLTHROUGH; // otherwise, it's invalid so diagnose it.
2007+
19732008
case ActorIsolationRestriction::ActorSelf: {
19742009
auto decl = concDecl.getDecl();
19752010
ctx.Diags.diagnose(component.getLoc(),

lib/Sema/TypeCheckConcurrency.h

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@ class EnumElementDecl;
3838
class Expr;
3939
class FuncDecl;
4040
class Initializer;
41-
class LangOptions;
4241
class PatternBindingDecl;
4342
class ProtocolConformance;
4443
class TopLevelCodeDecl;
@@ -214,10 +213,6 @@ bool diagnoseNonConcurrentTypesInReference(
214213
ConcurrentReferenceKind refKind,
215214
DiagnosticBehavior behavior = DiagnosticBehavior::Unspecified);
216215

217-
/// Whether we should diagnose cases where Sendable conformances are
218-
/// missing.
219-
bool shouldDiagnoseNonSendableViolations(const LangOptions &langOpts);
220-
221216
/// How the concurrent value check should be performed.
222217
enum class SendableCheck {
223218
/// Sendable conformance was explicitly stated and should be

test/Concurrency/Runtime/actor_keypaths.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
// UNSUPPORTED: back_deployment_runtime
88

99
actor Page {
10-
nonisolated let initialNumWords : Int
10+
let initialNumWords : Int
1111

1212
@actorIndependent(unsafe)
1313
var numWords : Int
@@ -19,7 +19,7 @@ actor Page {
1919
}
2020

2121
actor Book {
22-
nonisolated let pages : [Page]
22+
let pages : [Page]
2323

2424
init(_ numPages : Int) {
2525
var stack : [Page] = []

test/Concurrency/Runtime/custom_executors.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ actor Simple {
1717

1818
actor Custom {
1919
var count = 0
20-
nonisolated let simple = Simple()
20+
let simple = Simple()
2121

2222
@available(macOS 9999, iOS 9999, watchOS 9999, tvOS 9999, *)
2323
nonisolated var unownedExecutor: UnownedSerialExecutor {

test/Concurrency/actor_isolation.swift

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ class Point {
4949

5050
@available(macOS 9999, iOS 9999, watchOS 9999, tvOS 9999, *)
5151
actor MyActor: MySuperActor { // expected-error{{actor types do not support inheritance}}
52-
nonisolated let immutable: Int = 17
52+
let immutable: Int = 17
5353
// expected-note@+2 2{{property declared here}}
5454
// expected-note@+1 6{{mutation of this property is only permitted within the actor}}
5555
var mutable: Int = 71
@@ -58,8 +58,7 @@ actor MyActor: MySuperActor { // expected-error{{actor types do not support inhe
5858
// expected-note@+1 4{{property declared here}}
5959
var text: [String] = []
6060

61-
nonisolated let point : Point = Point() // expected-error{{non-isolated let property 'point' has non-Sendable type 'Point'}}
62-
let otherPoint = Point()
61+
let point : Point = Point()
6362

6463
@MainActor
6564
var name : String = "koala" // expected-note{{property declared here}}
@@ -103,12 +102,7 @@ func checkAsyncPropertyAccess() async {
103102

104103
act.text[0] += "hello" // expected-error{{actor-isolated property 'text' can only be mutated from inside the actor}}
105104

106-
_ = act.point
107-
_ = act.otherPoint
108-
// expected-error@-1{{expression is 'async' but is not marked with 'await'}}{{7-7=await }}
109-
// expected-note@-2{{property access is 'async'}}
110-
// expected-warning@-3{{cannot use property 'otherPoint' with a non-sendable type 'Point' across actors}}
111-
_ = await act.otherPoint // expected-warning{{cannot use property 'otherPoint' with a non-sendable type 'Point' across actors}}
105+
_ = act.point // expected-warning{{cannot use property 'point' with a non-sendable type 'Point' across actors}}
112106
}
113107

114108
@available(macOS 9999, iOS 9999, watchOS 9999, tvOS 9999, *)
@@ -652,7 +646,7 @@ actor LazyActor {
652646
var v: Int = 0
653647
// expected-note@-1 6 {{property declared here}}
654648

655-
nonisolated let l: Int = 0
649+
let l: Int = 0
656650

657651
lazy var l11: Int = { v }()
658652
lazy var l12: Int = v

test/Concurrency/actor_isolation_objc.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ actor A {
2828
_ = #keyPath(A.z)
2929
}
3030

31-
nonisolated let w: Int = 0 // expected-note{{add '@objc' to expose this property to Objective-C}}
31+
let w: Int = 0 // expected-note{{add '@objc' to expose this property to Objective-C}}
3232

3333
var x: Int = 0 // expected-note{{add '@objc' to expose this property to Objective-C}}
3434

test/Concurrency/actor_keypath_isolation.swift

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,10 @@ class Box {
66
}
77

88
actor Door {
9-
nonisolated let immutable : Int = 0
9+
let immutable : Int = 0
1010
let letBox : Box? = nil
1111
let letDict : [Int : Box] = [:]
12-
nonisolated let immutableNeighbor : Door? = nil
12+
let immutableNeighbor : Door? = nil
1313

1414

1515
var mutableNeighbor : Door? = nil
@@ -47,7 +47,7 @@ func tryKeyPathsMisc(d : Door) {
4747

4848
// in combination with other key paths
4949

50-
_ = (\Door.letBox).appending(path: // expected-error {{cannot form key path to actor-isolated property 'letBox'}}
50+
_ = (\Door.letBox).appending(path: // expected-warning {{cannot form key path that accesses non-sendable type 'Box?'}}
5151
\Box?.?.size)
5252

5353
_ = (\Door.varBox).appending(path: // expected-error {{cannot form key path to actor-isolated property 'varBox'}}
@@ -61,9 +61,9 @@ func tryKeyPathsFromAsync() async {
6161
}
6262

6363
func tryNonSendable() {
64-
_ = \Door.letDict[0] // expected-error {{cannot form key path to actor-isolated property 'letDict'}}
64+
_ = \Door.letDict[0] // expected-warning {{cannot form key path that accesses non-sendable type '[Int : Box]'}}
6565
_ = \Door.varDict[0] // expected-error {{cannot form key path to actor-isolated property 'varDict'}}
66-
_ = \Door.letBox!.size // expected-error {{cannot form key path to actor-isolated property 'letBox'}}
66+
_ = \Door.letBox!.size // expected-warning {{cannot form key path that accesses non-sendable type 'Box?'}}
6767
}
6868

6969
func tryKeypaths() {

test/Concurrency/concurrent_value_checking.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ extension A1 {
3737
_ = await self.asynchronous(nil)
3838

3939
// Across to a different actor, so Sendable restriction is enforced.
40-
_ = await other.localLet // expected-warning{{cannot use property 'localLet' with a non-sendable type 'NotConcurrent' across actors}}
40+
_ = other.localLet // expected-warning{{cannot use property 'localLet' with a non-sendable type 'NotConcurrent' across actors}}
4141
_ = await other.synchronous() // expected-warning{{cannot call function returning non-sendable type 'NotConcurrent?' across actors}}
4242
_ = await other.asynchronous(nil) // expected-warning{{cannot pass argument of non-sendable type 'NotConcurrent?' across actors}}
4343
}
@@ -67,7 +67,7 @@ func globalAsync(_: NotConcurrent?) async {
6767
}
6868

6969
func globalTest() async {
70-
let a = await globalValue // expected-warning{{cannot use let 'globalValue' with a non-sendable type 'NotConcurrent?' across actors}}
70+
let a = globalValue // expected-warning{{cannot use let 'globalValue' with a non-sendable type 'NotConcurrent?' across actors}}
7171
await globalAsync(a) // expected-warning{{cannot pass argument of non-sendable type 'NotConcurrent?' across actors}}
7272
await globalSync(a) // expected-warning{{cannot pass argument of non-sendable type 'NotConcurrent?' across actors}}
7373
}
@@ -88,7 +88,7 @@ class ClassWithGlobalActorInits {
8888

8989
@MainActor
9090
func globalTestMain(nc: NotConcurrent) async {
91-
let a = await globalValue // expected-warning{{cannot use let 'globalValue' with a non-sendable type 'NotConcurrent?' across actors}}
91+
let a = globalValue // expected-warning{{cannot use let 'globalValue' with a non-sendable type 'NotConcurrent?' across actors}}
9292
await globalAsync(a) // expected-warning{{cannot pass argument of non-sendable type 'NotConcurrent?' across actors}}
9393
await globalSync(a) // expected-warning{{cannot pass argument of non-sendable type 'NotConcurrent?' across actors}}
9494
_ = await ClassWithGlobalActorInits(nc) // expected-warning{{cannot pass argument of non-sendable type 'NotConcurrent' across actors}}

test/Concurrency/global_actor_from_ordinary_context.swift

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,7 @@ actor Alex {
3131
func referenceGlobalActor() async {
3232
let a = Alex()
3333
_ = a.method
34-
// expected-error@+1{{expression is 'async' but is not marked with 'await'}}{{7-7=await }}
35-
_ = a.const_memb // expected-note{{property access is 'async'}}
34+
_ = a.const_memb
3635
// expected-error@+1{{expression is 'async' but is not marked with 'await'}}{{7-7=await }}
3736
_ = a.mut_memb // expected-note{{property access is 'async'}}
3837

@@ -117,14 +116,12 @@ func fromAsync() async {
117116
y() // expected-note{{call is 'async'}}
118117

119118
let a = Alex()
120-
121119
let fn = a.method
122-
// expected-error@+1{{expression is 'async' but is not marked with 'await'}}{{3-3=await }}
123-
fn() //expected-note{{calls to let 'fn' from outside of its actor context are implicitly asynchronous}}
124-
// expected-error@+1{{expression is 'async' but is not marked with 'await'}}{{7-7=await }}
125-
_ = a.const_memb // expected-note{{property access is 'async'}}
126-
// expected-error@+1{{expression is 'async' but is not marked with 'await'}}{{7-7=await }}
127-
_ = a.mut_memb // expected-note{{property access is 'async'}}
120+
fn() // expected-error{{expression is 'async' but is not marked with 'await'}}
121+
// expected-note@-1{{calls to let 'fn' from outside of its actor context are implicitly asynchronous}}
122+
_ = a.const_memb
123+
_ = a.mut_memb // expected-error{{expression is 'async' but is not marked with 'await'}}
124+
// expected-note@-1{{property access is 'async'}}
128125

129126
// expected-error@+1{{expression is 'async' but is not marked with 'await'}}{{7-7=await }}
130127
_ = a[1] // expected-note{{subscript access is 'async'}}

0 commit comments

Comments
 (0)