Skip to content

Commit 84b6308

Browse files
committed
add regression test for rdar://70751405 and rdar://70813762
1 parent 10b6a1b commit 84b6308

File tree

1 file changed

+138
-0
lines changed

1 file changed

+138
-0
lines changed

test/Concurrency/async_throwing.swift

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
// RUN: %target-typecheck-verify-swift -enable-experimental-concurrency
2+
// REQUIRES: concurrency
3+
4+
// These tests cover various interactions with async functions that are
5+
// either throws or rethrows.
6+
// See rdar://70813762 and rdar://70751405
7+
8+
enum InvocationError : Error {
9+
case ErrVal
10+
}
11+
12+
func asyncThrows() async throws {
13+
throw InvocationError.ErrVal
14+
}
15+
16+
// T = Int
17+
func asyncRethrows(fn : () async throws -> Int) async rethrows -> Int {
18+
return await try fn()
19+
}
20+
21+
// T = String
22+
func asyncRethrows(fn : () async throws -> String) async rethrows -> String {
23+
return await try fn()
24+
}
25+
26+
// Generic. NOTE the 'rethrows'
27+
func invoke<T>(fn : () async throws -> T) async rethrows -> T {
28+
return await try fn()
29+
}
30+
31+
// NOTE the 'rethrows'
32+
func invokeAuto<T>(_ val : @autoclosure () async throws -> T) async rethrows -> T {
33+
return await try val()
34+
}
35+
36+
func normalTask() async -> Int {
37+
return 42
38+
}
39+
40+
func throwingTask() async throws -> String {
41+
if 1.0 / 3.0 == 0.33 {
42+
throw InvocationError.ErrVal
43+
}
44+
return "ok!"
45+
}
46+
47+
// expected-note@+2 7 {{add '@asyncHandler' to function 'syncTest()' to create an implicit asynchronous context}}
48+
// expected-note@+1 7 {{add 'async' to function 'syncTest()' to make it asynchronous}}
49+
func syncTest() {
50+
let _ = invoke(fn: normalTask) // expected-error{{'async' in a function that does not support concurrency}}
51+
let _ = invokeAuto(42) // expected-error{{'async' in a function that does not support concurrency}}
52+
let _ = invokeAuto("intuitive") // expected-error{{'async' in a function that does not support concurrency}}
53+
54+
let _ = try! asyncRethrows(fn: throwingTask) // expected-error{{'async' in a function that does not support concurrency}}
55+
let _ = try? invoke(fn: throwingTask) // expected-error{{'async' in a function that does not support concurrency}}
56+
do {
57+
let _ = try invoke(fn: throwingTask) // expected-error{{'async' in a function that does not support concurrency}}
58+
let _ = try asyncThrows() // expected-error{{'async' in a function that does not support concurrency}}
59+
} catch {
60+
// ignore it
61+
}
62+
}
63+
64+
65+
func asyncTest() async {
66+
///////////
67+
// tests that also omit await
68+
69+
let _ = invoke(fn: normalTask) // expected-error{{call is 'async' but is not marked with 'await'}}
70+
let _ = asyncRethrows(fn: normalTask) // expected-error{{call is 'async' but is not marked with 'await'}}
71+
let _ = invokeAuto(42) // expected-error{{call is 'async' but is not marked with 'await'}}
72+
73+
// expected-error@+2 {{call can throw, but it is not marked with 'try' and the error is not handled}}
74+
// expected-error@+1 {{call is 'async' but is not marked with 'await'}}
75+
let _ = asyncThrows()
76+
77+
// expected-note@+3{{call is to 'rethrows' function, but argument function can throw}}
78+
// expected-error@+2{{call can throw, but it is not marked with 'try' and the error is not handled}}
79+
// expected-error@+1{{call is 'async' but is not marked with 'await'}}
80+
let _ = invoke(fn: throwingTask)
81+
82+
///////////
83+
// tests that use await and handles the exceptions
84+
85+
// expected-note@+2{{call is to 'rethrows' function, but argument function can throw}}
86+
// expected-error@+1{{call can throw, but it is not marked with 'try' and the error is not handled}}
87+
let _ = await invoke(fn: throwingTask)
88+
let _ = await invoke(fn: normalTask) // ok
89+
90+
let _ = await asyncRethrows(fn: normalTask)
91+
let _ = await try! asyncRethrows(fn: normalTask) // expected-warning{{no calls to throwing functions occur within 'try' expression}}
92+
let _ = await try? asyncRethrows(fn: normalTask) // expected-warning{{no calls to throwing functions occur within 'try' expression}}
93+
94+
let _ = await try! asyncRethrows(fn: throwingTask)
95+
let _ = await try? asyncRethrows(fn: throwingTask)
96+
let _ = await try! asyncThrows()
97+
let _ = await try? asyncThrows()
98+
99+
//////////
100+
// some auto-closure tests
101+
102+
let _ = await invokeAuto("intuitive")
103+
let _ = await try! invokeAuto(await throwingTask())
104+
let _ = await try? invokeAuto(await throwingTask())
105+
let _ = await invokeAuto(await try! throwingTask())
106+
let _ = await invokeAuto(await try? throwingTask())
107+
108+
// FIXME: we currently emit a less-helpful error message here.
109+
// it would be better if we said "call is 'async' in an autoclosure argument that is not marked with 'await'"
110+
let _ = await invokeAuto(try! throwingTask()) // expected-error{{call is 'async' but is not marked with 'await'}}
111+
let _ = await invokeAuto(try? throwingTask()) // expected-error{{call is 'async' but is not marked with 'await'}}
112+
113+
let _ = await invokeAuto(await try! throwingTask())
114+
let _ = await invokeAuto(await try? throwingTask())
115+
/////////
116+
117+
do {
118+
let _ = await try asyncThrows()
119+
let _ = await try asyncRethrows(fn: throwingTask)
120+
121+
//////
122+
// more auto-closure tests
123+
124+
// expected-note@+6 {{did you mean to disable error propagation?}}
125+
// expected-note@+5 {{did you mean to handle error as optional value?}}
126+
// expected-note@+4 {{did you mean to use 'try'?}}
127+
// expected-note@+3 {{call is to 'rethrows' function, but argument function can throw}}
128+
// expected-error@+2 {{call is 'async' in an autoclosure argument that is not marked with 'await'}}
129+
// expected-error@+1 2 {{call can throw but is not marked with 'try'}}
130+
let _ = await invokeAuto(throwingTask())
131+
132+
let _ = await try invokeAuto(throwingTask()) // expected-error{{call is 'async' in an autoclosure argument that is not marked with 'await'}}
133+
let _ = try invokeAuto(await throwingTask()) // expected-error{{call is 'async' but is not marked with 'await'}}
134+
let _ = await try invokeAuto(await throwingTask())
135+
} catch {
136+
// ignore
137+
}
138+
}

0 commit comments

Comments
 (0)