Skip to content

Commit 40185cc

Browse files
committed
[Concurrency] Allow nonisolated to be used on protocols, extensions, classes, structs, and enums.
1 parent 4d01253 commit 40185cc

File tree

3 files changed

+170
-69
lines changed

3 files changed

+170
-69
lines changed

include/swift/AST/DeclAttr.def

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -441,7 +441,7 @@ SIMPLE_DECL_ATTR(reasync, Reasync,
441441
OnFunc | OnConstructor | RejectByParser | ABIBreakingToAdd | ABIBreakingToRemove | APIBreakingToAdd | APIBreakingToRemove,
442442
109)
443443
CONTEXTUAL_DECL_ATTR(nonisolated, Nonisolated,
444-
DeclModifier | OnFunc | OnConstructor | OnVar | OnSubscript | ABIStableToAdd | ABIStableToRemove | APIBreakingToAdd | APIStableToRemove,
444+
DeclModifier | OnFunc | OnConstructor | OnVar | OnSubscript | OnProtocol | OnExtension | OnClass | OnStruct | OnEnum | ABIStableToAdd | ABIStableToRemove | APIBreakingToAdd | APIStableToRemove,
445445
112)
446446
CONTEXTUAL_SIMPLE_DECL_ATTR(distributed, DistributedActor,
447447
DeclModifier | OnClass | OnFunc | OnAccessor | OnVar | ABIBreakingToAdd | ABIBreakingToRemove | APIBreakingToAdd | APIBreakingToRemove,

test/Concurrency/mutable_storage_nonisolated.swift

Lines changed: 0 additions & 68 deletions
This file was deleted.
Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
// RUN: %target-swift-frontend -disable-availability-checking -swift-version 6 -parse-as-library %s -emit-sil -o /dev/null -verify
2+
// RUN: %target-swift-frontend -disable-availability-checking -swift-version 6 -parse-as-library %s -emit-sil -o /dev/null -verify -strict-concurrency=complete
3+
4+
// REQUIRES: concurrency
5+
// REQUIRES: asserts
6+
7+
@MainActor
8+
protocol GloballyIsolated {}
9+
10+
// expected-note@+1 {{class 'NonSendable' does not conform to the 'Sendable' protocol}}
11+
class NonSendable {}
12+
13+
@propertyWrapper struct P {
14+
var wrappedValue = 0
15+
}
16+
17+
// MARK: - Structs
18+
19+
struct ImplicitlySendable {
20+
var a: Int
21+
22+
// always okay
23+
nonisolated let b = 0
24+
nonisolated var c: Int { 0 }
25+
26+
// okay
27+
nonisolated var d = 0
28+
29+
// never okay
30+
nonisolated lazy var e = 0 // expected-error {{'nonisolated' is not supported on lazy properties}}
31+
@P nonisolated var f = 0 // expected-error {{'nonisolated' is not supported on properties with property wrappers}}
32+
}
33+
34+
struct ImplicitlyNonSendable {
35+
let a: NonSendable
36+
37+
// always okay
38+
nonisolated let b = 0
39+
nonisolated var c: Int { 0 }
40+
41+
// not okay
42+
nonisolated var d = 0 // expected-error {{'nonisolated' cannot be applied to mutable stored properties}}
43+
// expected-note@-1 {{convert 'd' to a 'let' constant or consider declaring it 'nonisolated(unsafe)' if manually managing concurrency safety}}
44+
45+
// never okay
46+
nonisolated lazy var e = 0 // expected-error {{'nonisolated' is not supported on lazy properties}}
47+
@P nonisolated var f = 0 // expected-error {{'nonisolated' is not supported on properties with property wrappers}}
48+
}
49+
50+
public struct PublicSendable: Sendable {
51+
// always okay
52+
nonisolated let b = 0
53+
nonisolated var c: Int { 0 }
54+
55+
// okay
56+
nonisolated var d = 0
57+
58+
// never okay
59+
nonisolated lazy var e = 0 // expected-error {{'nonisolated' is not supported on lazy properties}}
60+
@P nonisolated var f = 0 // expected-error {{'nonisolated' is not supported on properties with property wrappers}}
61+
}
62+
63+
public struct PublicNonSendable {
64+
// always okay
65+
nonisolated let b = 0
66+
nonisolated var c: Int { 0 }
67+
68+
// not okay
69+
nonisolated var d = 0 // expected-error {{'nonisolated' cannot be applied to mutable stored properties}}
70+
// expected-note@-1 {{convert 'd' to a 'let' constant or consider declaring it 'nonisolated(unsafe)' if manually managing concurrency safety}}
71+
72+
// never okay
73+
nonisolated lazy var e = 0 // expected-error {{'nonisolated' is not supported on lazy properties}}
74+
@P nonisolated var f = 0 // expected-error {{'nonisolated' is not supported on properties with property wrappers}}
75+
}
76+
77+
78+
nonisolated struct NonisolatedStruct: GloballyIsolated {
79+
var x: NonSendable
80+
var y: Int = 1
81+
82+
init(x: NonSendable) {
83+
self.x = x // okay
84+
}
85+
86+
struct Nested: GloballyIsolated {
87+
// expected-note@+1 {{mutation of this property is only permitted within the actor}}
88+
var z: NonSendable
89+
nonisolated init(z: NonSendable) {
90+
// expected-error@+1 {{main actor-isolated property 'z' can not be mutated from a nonisolated context}}
91+
self.z = z
92+
}
93+
}
94+
}
95+
96+
@MainActor struct S {
97+
var value: NonSendable // globally-isolated
98+
struct Nested {} // 'Nested' is not @MainActor-isolated
99+
}
100+
101+
// expected-note@+1 {{calls to global function 'requireMain()' from outside of its actor context are implicitly asynchronous}}
102+
@MainActor func requireMain() {}
103+
104+
nonisolated struct S1: GloballyIsolated {
105+
var x: NonSendable
106+
func f() {
107+
// expected-error@+1 {{call to main actor-isolated global function 'requireMain()' in a synchronous nonisolated context}}
108+
requireMain()
109+
}
110+
}
111+
112+
// MARK: - Protocols
113+
114+
nonisolated protocol Refined: GloballyIsolated {}
115+
116+
struct A: Refined {
117+
var x: NonSendable
118+
init(x: NonSendable) {
119+
self.x = x // okay
120+
}
121+
}
122+
123+
// MARK: - Extensions
124+
125+
nonisolated extension GloballyIsolated {
126+
var x: NonSendable { .init () }
127+
func implicitlyNonisolated() {}
128+
}
129+
130+
struct C: GloballyIsolated {
131+
nonisolated func explicitlyNonisolated() {
132+
let _ = x // okay
133+
implicitlyNonisolated() // okay
134+
}
135+
}
136+
137+
// MARK: - Enums
138+
139+
nonisolated enum E: GloballyIsolated {
140+
func implicitlyNonisolated() {}
141+
init() {}
142+
}
143+
144+
struct TestEnum {
145+
nonisolated func call() {
146+
E().implicitlyNonisolated() // okay
147+
}
148+
}
149+
150+
// MARK: - Classes
151+
152+
nonisolated class K: GloballyIsolated {
153+
var x: NonSendable
154+
init(x: NonSendable) {
155+
self.x = x // okay
156+
}
157+
}
158+
159+
// MARK: - Storage of non-Sendable
160+
161+
class KlassA {
162+
nonisolated var test: NonSendable = NonSendable()
163+
}
164+
165+
// MARK: - Restrictions
166+
167+
@MainActor
168+
nonisolated struct Conflict {}
169+
// expected-error@-1 {{struct 'Conflict' has multiple actor-isolation attributes ('nonisolated' and 'MainActor')}}

0 commit comments

Comments
 (0)