Skip to content

Commit 8ed2ad4

Browse files
Added unit tests for Sema
1 parent 6a4b1fd commit 8ed2ad4

File tree

1 file changed

+318
-0
lines changed

1 file changed

+318
-0
lines changed
Lines changed: 318 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,318 @@
1+
// RUN: %target-swift-frontend -emit-sil -swift-version 6 -target %target-swift-5.1-abi-triple -verify -verify-additional-prefix old- %s -o /dev/null
2+
// RUN: %target-swift-frontend -emit-sil -swift-version 6 -target %target-swift-5.1-abi-triple -verify -verify-additional-prefix new- -enable-experimental-feature WeakLet %s -o /dev/null
3+
4+
// This test validates the behavior of transfer non sendable around ownership
5+
// constructs like non copyable types, consuming/borrowing parameters, and inout
6+
// parameters.
7+
8+
// REQUIRES: concurrency
9+
10+
final class S: Sendable {
11+
func foo() {}
12+
}
13+
14+
// expected-old-note@+2 13{{class 'NS' does not conform to the 'Sendable' protocol}}
15+
// expected-new-note@+1 12{{class 'NS' does not conform to the 'Sendable' protocol}}
16+
final class NS {
17+
func bar() {}
18+
}
19+
20+
func getS() -> S { S() }
21+
func getNS() -> NS { NS() }
22+
23+
final class CheckOptionality1: Sendable {
24+
// expected-old-error@+4 {{'weak' variable should have optional type 'S?'}}
25+
// expected-old-error@+3 {{stored property 'x' of 'Sendable'-conforming class 'CheckOptionality1' is mutable}}
26+
// expected-new-error@+2 {{'weak' variable should have optional type 'S?'}}
27+
// expected-new-error@+1 {{stored property 'x' of 'Sendable'-conforming class 'CheckOptionality1' is mutable}}
28+
weak var x: S = getS()
29+
}
30+
31+
final class CheckOptionality2: Sendable {
32+
// expected-old-error@+3 {{'weak' must be a mutable variable, because it may change at runtime}}
33+
// expected-old-error@+2 {{'weak' variable should have optional type 'S?'}}
34+
// expected-new-error@+1 {{'weak' variable should have optional type 'S?'}}
35+
weak let x: S = getS()
36+
}
37+
38+
final class CheckSendability1: Sendable {
39+
// expected-old-error@+2 {{stored property 'x' of 'Sendable'-conforming class 'CheckSendability1' is mutable}}
40+
// expected-new-error@+1 {{stored property 'x' of 'Sendable'-conforming class 'CheckSendability1' is mutable}}
41+
weak var x: S? = nil
42+
43+
weak var y: S? {
44+
get { x }
45+
set { x = newValue }
46+
}
47+
}
48+
49+
final class CheckSendability2: Sendable {
50+
// expected-old-error@+2 {{stored property 'x' of 'Sendable'-conforming class 'CheckSendability2' is mutable}}
51+
// expected-new-error@+1 {{stored property 'x' of 'Sendable'-conforming class 'CheckSendability2' is mutable}}
52+
weak var x: NS? = nil
53+
}
54+
55+
final class CheckSendability3: Sendable {
56+
// expected-old-error@+1 {{'weak' must be a mutable variable, because it may change at runtime}}
57+
weak let x: S? = nil
58+
}
59+
60+
final class CheckSendability4: Sendable {
61+
// expected-old-error@+3 {{'weak' must be a mutable variable, because it may change at runtime}}
62+
// expected-old-error@+2 {{stored property 'x' of 'Sendable'-conforming class 'CheckSendability4' has non-sendable type 'NS?'}}
63+
// expected-new-error@+1 {{stored property 'x' of 'Sendable'-conforming class 'CheckSendability4' has non-sendable type 'NS?'}}
64+
weak let x: NS? = nil
65+
}
66+
67+
final class CheckSendability5: Sendable {
68+
// expected-old-error@+2 {{stored property 'x' of 'Sendable'-conforming class 'CheckSendability5' is mutable}}
69+
// expected-new-error@+1 {{stored property 'x' of 'Sendable'-conforming class 'CheckSendability5' is mutable}}
70+
unowned var x: S = getS()
71+
}
72+
73+
final class CheckSendability6: Sendable {
74+
// expected-old-error@+2 {{stored property 'x' of 'Sendable'-conforming class 'CheckSendability6' is mutable}}
75+
// expected-new-error@+1 {{stored property 'x' of 'Sendable'-conforming class 'CheckSendability6' is mutable}}
76+
unowned var x: NS = getNS()
77+
}
78+
79+
final class CheckSendability7: Sendable {
80+
unowned let x: S = getS()
81+
}
82+
83+
final class CheckSendability8: Sendable {
84+
// expected-old-error@+2 {{stored property 'x' of 'Sendable'-conforming class 'CheckSendability8' has non-sendable type 'NS'}}
85+
// expected-new-error@+1 {{stored property 'x' of 'Sendable'-conforming class 'CheckSendability8' has non-sendable type 'NS'}}
86+
unowned let x: NS = getNS()
87+
}
88+
89+
final class CheckSendability9: Sendable {
90+
// expected-old-error@+2 {{stored property 'x' of 'Sendable'-conforming class 'CheckSendability9' is mutable}}
91+
// expected-new-error@+1 {{stored property 'x' of 'Sendable'-conforming class 'CheckSendability9' is mutable}}
92+
unowned(unsafe) var x: S = getS()
93+
}
94+
95+
final class CheckSendability10: Sendable {
96+
// expected-old-error@+2 {{stored property 'x' of 'Sendable'-conforming class 'CheckSendability10' is mutable}}
97+
// expected-new-error@+1 {{stored property 'x' of 'Sendable'-conforming class 'CheckSendability10' is mutable}}
98+
unowned(unsafe) var x: NS = getNS()
99+
}
100+
101+
final class CheckSendability11: Sendable {
102+
unowned(unsafe) let x: S = getS()
103+
}
104+
105+
final class CheckSendability12: Sendable {
106+
// expected-old-error@+2 {{stored property 'x' of 'Sendable'-conforming class 'CheckSendability12' has non-sendable type 'NS'}}
107+
// expected-new-error@+1 {{stored property 'x' of 'Sendable'-conforming class 'CheckSendability12' has non-sendable type 'NS'}}
108+
unowned(unsafe) let x: NS = getNS()
109+
}
110+
111+
112+
func checkWeakCapture1(_ strongRef: S) -> @Sendable () -> Void {
113+
weak var weakRef: S? = strongRef
114+
return {
115+
// expected-old-error@+2 {{reference to captured var 'weakRef' in concurrently-executing code}}
116+
// expected-new-error@+1 {{reference to captured var 'weakRef' in concurrently-executing code}}
117+
weakRef?.foo()
118+
}
119+
}
120+
121+
func checkWeakCapture2(_ strongRef: S) -> @Sendable () -> Void {
122+
// expected-old-error@+1 {{'weak' must be a mutable variable, because it may change at runtime}}
123+
weak let weakRef: S? = strongRef
124+
return {
125+
weakRef?.foo()
126+
}
127+
}
128+
129+
func checkWeakCapture3(_ strongRef: S) -> @Sendable () -> Void {
130+
return { [weak weakRef = strongRef] in
131+
// TODO: Add expected old error, when https://github.com/swiftlang/swift/issues/80014 is fixed
132+
// See also https://forums.swift.org/t/lets-debug-missing-rbi-data-race-diagnostics/78910
133+
weakRef?.foo()
134+
// expected-new-error@+1 {{cannot assign to value: 'weakRef' is an immutable capture}}
135+
weakRef = nil
136+
}
137+
}
138+
139+
func checkWeakCapture4(_ strongRef: NS) -> @Sendable () -> Void {
140+
// TODO: warning consider changing to 'let' constant
141+
weak var weakRef: NS? = strongRef
142+
return {
143+
// expected-old-error@+4 {{capture of 'weakRef' with non-sendable type 'NS?' in a '@Sendable' closure}}
144+
// expected-new-error@+3 {{capture of 'weakRef' with non-sendable type 'NS?' in a '@Sendable' closure}}
145+
// expected-old-error@+2 {{reference to captured var 'weakRef' in concurrently-executing code}}
146+
// expected-new-error@+1 {{reference to captured var 'weakRef' in concurrently-executing code}}
147+
weakRef?.bar()
148+
}
149+
}
150+
151+
func checkWeakCapture5(_ strongRef: NS) -> @Sendable () -> Void {
152+
// expected-old-error@+1 {{'weak' must be a mutable variable, because it may change at runtime}}
153+
weak let weakRef: NS? = strongRef
154+
return {
155+
// expected-old-error@+2 {{capture of 'weakRef' with non-sendable type 'NS?' in a '@Sendable' closure}}
156+
// expected-new-error@+1 {{capture of 'weakRef' with non-sendable type 'NS?' in a '@Sendable' closure}}
157+
weakRef?.bar()
158+
}
159+
}
160+
161+
func checkWeakCapture6(_ strongRef: NS) -> @Sendable () -> Void {
162+
return { [weak weakRef = strongRef] in
163+
// expected-old-error@+3 {{capture of 'weakRef' with non-sendable type 'NS?' in a '@Sendable' closure}}
164+
// For some reason the next error masks this error.
165+
// This case is split into two, to verify that when unmasked error is triggered.
166+
weakRef?.bar()
167+
// expected-new-error@+1 {{cannot assign to value: 'weakRef' is an immutable capture}}
168+
weakRef = nil
169+
}
170+
}
171+
172+
func checkWeakCapture7(_ strongRef: NS) -> @Sendable () -> Void {
173+
return { [weak weakRef = strongRef] in
174+
// expected-old-error@+2 {{capture of 'weakRef' with non-sendable type 'NS?' in a '@Sendable' closure}}
175+
// expected-new-error@+1 {{capture of 'weakRef' with non-sendable type 'NS?' in a '@Sendable' closure}}
176+
weakRef?.bar()
177+
}
178+
}
179+
180+
func checkUnownedCapture1(_ strongRef: S) -> @Sendable () -> Void {
181+
// expected-old-warning@+2 {{variable 'unownedRef' was never mutated; consider changing to 'let' constant}}
182+
// expected-new-warning@+1 {{variable 'unownedRef' was never mutated; consider changing to 'let' constant}}
183+
unowned var unownedRef: S = strongRef
184+
return {
185+
// expected-old-error@+2 {{reference to captured var 'unownedRef' in concurrently-executing code}}
186+
// expected-new-error@+1 {{reference to captured var 'unownedRef' in concurrently-executing code}}
187+
unownedRef.foo()
188+
}
189+
}
190+
191+
func checkUnownedCapture2(_ strongRef: S) -> @Sendable () -> Void {
192+
unowned let unownedRef: S = strongRef
193+
return {
194+
unownedRef.foo()
195+
}
196+
}
197+
198+
func checkUnownedCapture3(_ strongRef: S) -> @Sendable () -> Void {
199+
return { [unowned unownedRef = strongRef] in
200+
// TODO: Add expected old error, when https://github.com/swiftlang/swift/issues/80014 is fixed
201+
// See also https://forums.swift.org/t/lets-debug-missing-rbi-data-race-diagnostics/78910
202+
unownedRef.foo()
203+
// expected-old-error@+2 {{cannot assign to value: 'unownedRef' is an immutable capture}}
204+
// expected-new-error@+1 {{cannot assign to value: 'unownedRef' is an immutable capture}}
205+
unownedRef = strongRef
206+
}
207+
}
208+
209+
func checkUnownedCapture4(_ strongRef: NS) -> @Sendable () -> Void {
210+
// expected-old-warning@+2 {{variable 'unownedRef' was never mutated; consider changing to 'let' constant}}
211+
// expected-new-warning@+1 {{variable 'unownedRef' was never mutated; consider changing to 'let' constant}}
212+
unowned var unownedRef: NS = strongRef
213+
return {
214+
// expected-old-error@+4 {{capture of 'unownedRef' with non-sendable type 'NS' in a '@Sendable' closure}}
215+
// expected-new-error@+3 {{capture of 'unownedRef' with non-sendable type 'NS' in a '@Sendable' closure}}
216+
// expected-old-error@+2 {{reference to captured var 'unownedRef' in concurrently-executing code}}
217+
// expected-new-error@+1 {{reference to captured var 'unownedRef' in concurrently-executing code}}
218+
unownedRef.bar()
219+
}
220+
}
221+
222+
func checkUnownedCapture5(_ strongRef: NS) -> @Sendable () -> Void {
223+
unowned let unownedRef: NS = strongRef
224+
return {
225+
// expected-old-error@+2 {{capture of 'unownedRef' with non-sendable type 'NS' in a '@Sendable' closure}}
226+
// expected-new-error@+1 {{capture of 'unownedRef' with non-sendable type 'NS' in a '@Sendable' closure}}
227+
unownedRef.bar()
228+
}
229+
}
230+
231+
func checkUnownedCapture6(_ strongRef: NS) -> @Sendable () -> Void {
232+
return { [unowned unownedRef = strongRef] in
233+
// For some reason the next error masks this error.
234+
// This case is split into two, to verify that when unmasked error is triggered.
235+
unownedRef.bar()
236+
// expected-old-error@+2 {{cannot assign to value: 'unownedRef' is an immutable capture}}
237+
// expected-new-error@+1 {{cannot assign to value: 'unownedRef' is an immutable capture}}
238+
unownedRef = strongRef
239+
}
240+
}
241+
242+
func checkUnownedCapture7(_ strongRef: NS) -> @Sendable () -> Void {
243+
return { [unowned unownedRef = strongRef] in
244+
// expected-old-error@+2 {{capture of 'unownedRef' with non-sendable type 'NS' in a '@Sendable' closure}}
245+
// expected-new-error@+1 {{capture of 'unownedRef' with non-sendable type 'NS' in a '@Sendable' closure}}
246+
unownedRef.bar()
247+
}
248+
}
249+
250+
func checkUnsafeCapture1(_ strongRef: S) -> @Sendable () -> Void {
251+
// expected-old-warning@+2 {{variable 'unownedRef' was never mutated; consider changing to 'let' constant}}
252+
// expected-new-warning@+1 {{variable 'unownedRef' was never mutated; consider changing to 'let' constant}}
253+
unowned(unsafe) var unownedRef: S = strongRef
254+
return {
255+
// expected-old-error@+2 {{reference to captured var 'unownedRef' in concurrently-executing code}}
256+
// expected-new-error@+1 {{reference to captured var 'unownedRef' in concurrently-executing code}}
257+
unownedRef.foo()
258+
}
259+
}
260+
261+
func checkUnsafeCapture2(_ strongRef: S) -> @Sendable () -> Void {
262+
unowned(unsafe) let unownedRef: S = strongRef
263+
return {
264+
unownedRef.foo()
265+
}
266+
}
267+
268+
func checkUnsafeCapture3(_ strongRef: S) -> @Sendable () -> Void {
269+
return { [unowned(unsafe) unownedRef = strongRef] in
270+
// TODO: Add expected old error, when https://github.com/swiftlang/swift/issues/80014 is fixed
271+
// See also https://forums.swift.org/t/lets-debug-missing-rbi-data-race-diagnostics/78910
272+
unownedRef.foo()
273+
// expected-old-error@+2 {{cannot assign to value: 'unownedRef' is an immutable capture}}
274+
// expected-new-error@+1 {{cannot assign to value: 'unownedRef' is an immutable capture}}
275+
unownedRef = strongRef
276+
}
277+
}
278+
279+
func checkUnsafeCapture4(_ strongRef: NS) -> @Sendable () -> Void {
280+
// expected-old-warning@+2 {{variable 'unownedRef' was never mutated; consider changing to 'let' constant}}
281+
// expected-new-warning@+1 {{variable 'unownedRef' was never mutated; consider changing to 'let' constant}}
282+
unowned(unsafe) var unownedRef: NS = strongRef
283+
return {
284+
// expected-old-error@+4 {{capture of 'unownedRef' with non-sendable type 'NS' in a '@Sendable' closure}}
285+
// expected-new-error@+3 {{capture of 'unownedRef' with non-sendable type 'NS' in a '@Sendable' closure}}
286+
// expected-old-error@+2 {{reference to captured var 'unownedRef' in concurrently-executing code}}
287+
// expected-new-error@+1 {{reference to captured var 'unownedRef' in concurrently-executing code}}
288+
unownedRef.bar()
289+
}
290+
}
291+
292+
func checkUnsafeCapture5(_ strongRef: NS) -> @Sendable () -> Void {
293+
unowned(unsafe) let unownedRef: NS = strongRef
294+
return {
295+
// expected-old-error@+2 {{capture of 'unownedRef' with non-sendable type 'NS' in a '@Sendable' closure}}
296+
// expected-new-error@+1 {{capture of 'unownedRef' with non-sendable type 'NS' in a '@Sendable' closure}}
297+
unownedRef.bar()
298+
}
299+
}
300+
301+
func checkUnsafeCapture6(_ strongRef: NS) -> @Sendable () -> Void {
302+
return { [unowned(unsafe) unownedRef = strongRef] in
303+
// For some reason the next error masks this error.
304+
// This case is split into two, to verify that when unmasked error is triggered.
305+
unownedRef.bar()
306+
// expected-old-error@+2 {{cannot assign to value: 'unownedRef' is an immutable capture}}
307+
// expected-new-error@+1 {{cannot assign to value: 'unownedRef' is an immutable capture}}
308+
unownedRef = strongRef
309+
}
310+
}
311+
312+
func checkUnsafeCapture7(_ strongRef: NS) -> @Sendable () -> Void {
313+
return { [unowned(unsafe) unownedRef = strongRef] in
314+
// expected-old-error@+2 {{capture of 'unownedRef' with non-sendable type 'NS' in a '@Sendable' closure}}
315+
// expected-new-error@+1 {{capture of 'unownedRef' with non-sendable type 'NS' in a '@Sendable' closure}}
316+
unownedRef.bar()
317+
}
318+
}

0 commit comments

Comments
 (0)