Skip to content

Commit f3be40e

Browse files
committed
[test] eff. prop + actor isolation
1 parent efbb0f1 commit f3be40e

File tree

1 file changed

+302
-0
lines changed

1 file changed

+302
-0
lines changed

test/Concurrency/actor_call_implicitly_async.swift

Lines changed: 302 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,22 @@
11
// RUN: %target-typecheck-verify-swift -enable-experimental-concurrency -warn-concurrency
22
// REQUIRES: concurrency
33

4+
5+
// some utilities
6+
func thrower() throws {}
7+
func asyncer() async {}
8+
9+
func rethrower(_ f : @autoclosure () throws -> Any) rethrows -> Any {
10+
return try f()
11+
}
12+
13+
func asAutoclosure(_ f : @autoclosure () -> Any) -> Any { return f() }
14+
15+
// not a concurrency-safe type
16+
class Box {
17+
var counter : Int = 0
18+
}
19+
420
actor BankAccount {
521

622
private var curBalance : Int
@@ -61,6 +77,73 @@ actor BankAccount {
6177
_ = deposit(withdraw(deposit(withdraw(balance()))))
6278
}
6379

80+
func testThrowing() throws {}
81+
82+
var effPropA : Box {
83+
get async {
84+
await asyncer()
85+
return Box()
86+
}
87+
}
88+
89+
var effPropT : Box {
90+
get throws {
91+
try thrower()
92+
return Box()
93+
}
94+
}
95+
96+
var effPropAT : Int {
97+
get async throws {
98+
await asyncer()
99+
try thrower()
100+
return 0
101+
}
102+
}
103+
104+
// expected-note@+1 2 {{add 'async' to function 'effPropertiesFromInsideActorInstance()' to make it asynchronous}}
105+
func effPropertiesFromInsideActorInstance() throws {
106+
// expected-error@+1{{'async' property access in a function that does not support concurrency}}
107+
_ = effPropA
108+
109+
// expected-note@+4{{did you mean to handle error as optional value?}}
110+
// expected-note@+3{{did you mean to use 'try'?}}
111+
// expected-note@+2{{did you mean to disable error propagation?}}
112+
// expected-error@+1{{property access can throw but is not marked with 'try'}}
113+
_ = effPropT
114+
115+
_ = try effPropT
116+
117+
// expected-note@+6 {{did you mean to handle error as optional value?}}
118+
// expected-note@+5 {{did you mean to use 'try'?}}
119+
// expected-note@+4 {{did you mean to disable error propagation?}}
120+
// expected-error@+3 {{property access can throw but is not marked with 'try'}}
121+
// expected-note@+2 {{call is to 'rethrows' function, but argument function can throw}}
122+
// expected-error@+1 {{call can throw but is not marked with 'try'}}
123+
_ = rethrower(effPropT)
124+
125+
// expected-note@+2 {{call is to 'rethrows' function, but argument function can throw}}
126+
// expected-error@+1 {{call can throw but is not marked with 'try'}}
127+
_ = rethrower(try effPropT)
128+
129+
_ = try rethrower(effPropT)
130+
_ = try rethrower(thrower())
131+
132+
_ = try rethrower(try effPropT)
133+
_ = try rethrower(try thrower())
134+
135+
_ = rethrower(effPropA) // expected-error{{'async' property access in an autoclosure that does not support concurrency}}
136+
137+
_ = asAutoclosure(effPropT) // expected-error{{property access can throw, but it is not marked with 'try' and it is executed in a non-throwing autoclosure}}
138+
139+
// expected-note@+5{{did you mean to handle error as optional value?}}
140+
// expected-note@+4{{did you mean to use 'try'?}}
141+
// expected-note@+3{{did you mean to disable error propagation?}}
142+
// expected-error@+2{{property access can throw but is not marked with 'try'}}
143+
// expected-error@+1{{'async' property access in a function that does not support concurrency}}
144+
_ = effPropAT
145+
}
146+
64147
} // end actor
65148

66149
func someAsyncFunc() async {
@@ -88,6 +171,29 @@ func someAsyncFunc() async {
88171

89172
a.testSelfBalance() // expected-error {{call is 'async' but is not marked with 'await'}}
90173

174+
await a.testThrowing() // expected-error {{call can throw, but it is not marked with 'try' and the error is not handled}}
175+
176+
////////////
177+
// effectful properties from outside the actor instance
178+
179+
// expected-warning@+2 {{cannot use property 'effPropA' with a non-sendable type 'Box' across actors}}
180+
// expected-error@+1{{property access is 'async' but is not marked with 'await'}} {{7-7=await }}
181+
_ = a.effPropA
182+
183+
// expected-warning@+3 {{cannot use property 'effPropT' with a non-sendable type 'Box' across actors}}
184+
// expected-error@+2{{property access can throw, but it is not marked with 'try' and the error is not handled}}
185+
// expected-error@+1{{property access is 'async' but is not marked with 'await'}} {{7-7=await }}
186+
_ = a.effPropT
187+
188+
// expected-error@+2{{property access can throw, but it is not marked with 'try' and the error is not handled}}
189+
// expected-error@+1{{property access is 'async' but is not marked with 'await'}} {{7-7=await }}
190+
_ = a.effPropAT
191+
192+
// (mostly) corrected ones
193+
_ = await a.effPropA // expected-warning {{cannot use property 'effPropA' with a non-sendable type 'Box' across actors}}
194+
_ = try! await a.effPropT // expected-warning {{cannot use property 'effPropT' with a non-sendable type 'Box' across actors}}
195+
_ = try? await a.effPropAT
196+
91197
print("ok!")
92198
}
93199

@@ -255,3 +361,199 @@ actor Calculator {
255361
// expected-warning@-1{{cannot call function returning non-sendable type}}
256362
let _ = plusOne(2)
257363
}
364+
365+
///////
366+
// Effectful properties isolated to a global actor
367+
368+
@BananaActor
369+
var effPropA : Int {
370+
get async {
371+
await asyncer()
372+
try thrower() // expected-error{{errors thrown from here are not handled}}
373+
return 0
374+
}
375+
}
376+
377+
@BananaActor
378+
var effPropT : Int { // expected-note{{var declared here}}
379+
get throws {
380+
await asyncer() // expected-error{{'async' call in a function that does not support concurrency}}
381+
try thrower()
382+
return 0
383+
}
384+
}
385+
386+
@BananaActor
387+
var effPropAT : Int {
388+
get async throws {
389+
await asyncer()
390+
try thrower()
391+
return 0
392+
}
393+
}
394+
395+
// expected-note@+1 2 {{add 'async' to function 'tryEffPropsFromBanana()' to make it asynchronous}}
396+
@BananaActor func tryEffPropsFromBanana() throws {
397+
// expected-error@+1{{'async' property access in a function that does not support concurrency}}
398+
_ = effPropA
399+
400+
// expected-note@+4{{did you mean to handle error as optional value?}}
401+
// expected-note@+3{{did you mean to use 'try'?}}
402+
// expected-note@+2{{did you mean to disable error propagation?}}
403+
// expected-error@+1{{property access can throw but is not marked with 'try'}}
404+
_ = effPropT
405+
406+
_ = try effPropT
407+
408+
// expected-note@+6 {{did you mean to handle error as optional value?}}
409+
// expected-note@+5 {{did you mean to use 'try'?}}
410+
// expected-note@+4 {{did you mean to disable error propagation?}}
411+
// expected-error@+3 {{property access can throw but is not marked with 'try'}}
412+
// expected-note@+2 {{call is to 'rethrows' function, but argument function can throw}}
413+
// expected-error@+1 {{call can throw but is not marked with 'try'}}
414+
_ = rethrower(effPropT)
415+
416+
// expected-note@+2 {{call is to 'rethrows' function, but argument function can throw}}
417+
// expected-error@+1 {{call can throw but is not marked with 'try'}}
418+
_ = rethrower(try effPropT)
419+
420+
_ = try rethrower(effPropT)
421+
_ = try rethrower(thrower())
422+
423+
_ = try rethrower(try effPropT)
424+
_ = try rethrower(try thrower())
425+
426+
_ = rethrower(effPropA) // expected-error{{'async' property access in an autoclosure that does not support concurrency}}
427+
428+
_ = asAutoclosure(effPropT) // expected-error{{property access can throw, but it is not marked with 'try' and it is executed in a non-throwing autoclosure}}
429+
430+
// expected-note@+5{{did you mean to handle error as optional value?}}
431+
// expected-note@+4{{did you mean to use 'try'?}}
432+
// expected-note@+3{{did you mean to disable error propagation?}}
433+
// expected-error@+2{{property access can throw but is not marked with 'try'}}
434+
// expected-error@+1{{'async' property access in a function that does not support concurrency}}
435+
_ = effPropAT
436+
}
437+
438+
439+
// expected-note@+2 {{add '@BananaActor' to make global function 'tryEffPropsFromSync()' part of global actor 'BananaActor'}}
440+
// expected-note@+1 2 {{add 'async' to function 'tryEffPropsFromSync()' to make it asynchronous}}
441+
func tryEffPropsFromSync() {
442+
_ = effPropA // expected-error{{'async' property access in a function that does not support concurrency}}
443+
444+
// expected-error@+1 {{property access can throw, but it is not marked with 'try' and the error is not handled}}
445+
_ = effPropT // expected-error{{var 'effPropT' isolated to global actor 'BananaActor' can not be referenced from this synchronous context}}
446+
// NOTE: that we don't complain about async access on `effPropT` because it's not declared async, and we're not in an async context!
447+
448+
// expected-error@+1 {{property access can throw, but it is not marked with 'try' and the error is not handled}}
449+
_ = effPropAT // expected-error{{'async' property access in a function that does not support concurrency}}
450+
}
451+
452+
@OrangeActor func tryEffPropertiesFromGlobalActor() async throws {
453+
// expected-error@+1{{property access is 'async' but is not marked with 'await'}} {{7-7=await }}
454+
_ = effPropA
455+
456+
// expected-note@+5{{did you mean to handle error as optional value?}}
457+
// expected-note@+4{{did you mean to use 'try'?}}
458+
// expected-note@+3{{did you mean to disable error propagation?}}
459+
// expected-error@+2{{property access can throw but is not marked with 'try'}}
460+
// expected-error@+1{{property access is 'async' but is not marked with 'await'}} {{7-7=await }}
461+
_ = effPropT
462+
463+
// expected-note@+5{{did you mean to handle error as optional value?}}
464+
// expected-note@+4{{did you mean to use 'try'?}}
465+
// expected-note@+3{{did you mean to disable error propagation?}}
466+
// expected-error@+2{{property access can throw but is not marked with 'try'}}
467+
// expected-error@+1{{property access is 'async' but is not marked with 'await'}} {{7-7=await }}
468+
_ = effPropAT
469+
470+
_ = await effPropA
471+
_ = try? await effPropT
472+
_ = try! await effPropAT
473+
}
474+
475+
/////////////
476+
// check subscripts in actors
477+
478+
actor SubscriptA {
479+
subscript(_ i : Int) -> Int {
480+
get async {
481+
try thrower() // expected-error{{errors thrown from here are not handled}}
482+
await asyncer()
483+
return 0
484+
}
485+
}
486+
487+
func f() async {
488+
_ = self[0] // expected-error{{subscript access is 'async' but is not marked with 'await'}}
489+
}
490+
}
491+
492+
actor SubscriptT {
493+
subscript(_ i : Int) -> Int {
494+
get throws {
495+
try thrower()
496+
await asyncer() // expected-error{{'async' call in a function that does not support concurrency}}
497+
return 0
498+
}
499+
}
500+
501+
func f() throws {
502+
_ = try self[0]
503+
504+
// expected-note@+6 {{did you mean to handle error as optional value?}}
505+
// expected-note@+5 {{did you mean to use 'try'?}}
506+
// expected-note@+4 {{did you mean to disable error propagation?}}
507+
// expected-error@+3 {{subscript access can throw but is not marked with 'try'}}
508+
// expected-note@+2 {{call is to 'rethrows' function, but argument function can throw}}
509+
// expected-error@+1 {{call can throw but is not marked with 'try'}}
510+
_ = rethrower(self[1])
511+
512+
// expected-note@+2 {{call is to 'rethrows' function, but argument function can throw}}
513+
// expected-error@+1 {{call can throw but is not marked with 'try'}}
514+
_ = rethrower(try self[1])
515+
516+
_ = try rethrower(self[1])
517+
_ = try rethrower(try self[1])
518+
}
519+
}
520+
521+
actor SubscriptAT {
522+
subscript(_ i : Int) -> Int {
523+
get async throws {
524+
try thrower()
525+
await asyncer()
526+
return 0
527+
}
528+
}
529+
530+
func f() async throws {
531+
_ = try await self[0]
532+
}
533+
}
534+
535+
func tryTheActorSubscripts(a : SubscriptA, t : SubscriptT, at : SubscriptAT) async throws {
536+
_ = a[0] // expected-error{{subscript access is 'async' but is not marked with 'await'}}
537+
538+
_ = await a[0]
539+
540+
// expected-note@+5{{did you mean to handle error as optional value?}}
541+
// expected-note@+4{{did you mean to use 'try'?}}
542+
// expected-note@+3{{did you mean to disable error propagation?}}
543+
// expected-error@+2{{subscript access can throw but is not marked with 'try'}}
544+
// expected-error@+1 {{subscript access is 'async' but is not marked with 'await'}}
545+
_ = t[0]
546+
547+
_ = try await t[0]
548+
_ = try! await t[0]
549+
_ = try? await t[0]
550+
551+
// expected-note@+5{{did you mean to handle error as optional value?}}
552+
// expected-note@+4{{did you mean to use 'try'?}}
553+
// expected-note@+3{{did you mean to disable error propagation?}}
554+
// expected-error@+2{{subscript access can throw but is not marked with 'try'}}
555+
// expected-error@+1 {{subscript access is 'async' but is not marked with 'await'}}
556+
_ = at[0]
557+
558+
_ = try await at[0]
559+
}

0 commit comments

Comments
 (0)