1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241
|
// RUN: %target-swift-frontend -typecheck -verify %s -disable-availability-checking
// REQUIRES: concurrency
func test1(asyncfp : () async -> Int, fp : () -> Int) async {
_ = await asyncfp()
_ = await asyncfp() + asyncfp()
_ = await asyncfp() + fp()
_ = await fp() + 42 // expected-warning {{no 'async' operations occur within 'await' expression}}
_ = 32 + asyncfp() + asyncfp() // expected-error {{expression is 'async' but is not marked with 'await'}}{{7-7=await }}
// expected-note@-1:12{{call is 'async'}}
// expected-note@-2:24{{call is 'async'}}
}
func getInt() async -> Int { return 5 }
// Locations where "await" is prohibited.
func test2(
defaulted: Int = await getInt() // expected-error{{'async' call cannot occur in a default argument}}
) async {
defer {
_ = await getInt() // expected-error{{'async' call cannot occur in a defer body}}
}
print("foo")
}
func test3() { // expected-note{{add 'async' to function 'test3()' to make it asynchronous}} {{13-13= async}}
_ = await getInt() // expected-error{{'async' call in a function that does not support concurrency}}
}
func test4()throws { // expected-note{{add 'async' to function 'test4()' to make it asynchronous}} {{13-19=async throws}}
_ = await getInt() // expected-error{{'async' call in a function that does not support concurrency}}
}
func test5<T>(_ f : () async throws -> T) rethrows->T { // expected-note{{add 'async' to function 'test5' to make it asynchronous}} {{44-52=async rethrows}}
return try await f() // expected-error{{'async' call in a function that does not support concurrency}}
}
enum SomeEnum: Int {
case foo = await 5 // expected-error{{raw value for enum case must be a literal}}
}
struct SomeStruct {
var x = await getInt() // expected-error{{'async' call cannot occur in a property initializer}}
static var y = await getInt() // expected-error{{'async' call cannot occur in a global variable initializer}}
}
func acceptAutoclosureNonAsync(_: @autoclosure () -> Int) async { }
func acceptAutoclosureAsync(_: @autoclosure () async -> Int) async { }
func acceptAutoclosureAsyncThrows(_: @autoclosure () async throws -> Int) async { }
func acceptAutoclosureAsyncThrowsRethrows(_: @autoclosure () async throws -> Int) async rethrows { }
func acceptAutoclosureNonAsyncBad(_: @autoclosure () async -> Int) -> Int { 0 }
// expected-error@-1{{'async' autoclosure parameter in a non-'async' function}}
// expected-note@-2{{add 'async' to function 'acceptAutoclosureNonAsyncBad' to make it asynchronous}} {{67-67= async}}
struct HasAsyncBad {
init(_: @autoclosure () async -> Int) { }
// expected-error@-1{{'async' autoclosure parameter in a non-'async' function}}
}
func testAutoclosure() async {
await acceptAutoclosureAsync(await getInt())
await acceptAutoclosureNonAsync(await getInt()) // expected-error{{'async' call in an autoclosure that does not support concurrency}}
await acceptAutoclosureAsync(42 + getInt())
// expected-error@-1:32{{expression is 'async' but is not marked with 'await'}}{{32-32=await }}
// expected-note@-2:37{{call is 'async' in an autoclosure argument}}
await acceptAutoclosureNonAsync(getInt()) // expected-error{{'async' call in an autoclosure that does not support concurrency}}
}
// Test inference of 'async' from the body of a closure.
func testClosure() {
let closure = {
await getInt()
}
let _: () -> Int = closure // expected-error{{invalid conversion from 'async' function of type '() async -> Int' to synchronous function type '() -> Int'}}
let closure2 = { () async -> Int in
print("here")
return await getInt()
}
let _: () -> Int = closure2 // expected-error{{invalid conversion from 'async' function of type '() async -> Int' to synchronous function type '() -> Int'}}
}
// Nesting async and await together
func throwingAndAsync() async throws -> Int { return 0 }
enum HomeworkError : Error {
case dogAteIt
}
func testThrowingAndAsync() async throws {
_ = try await throwingAndAsync()
_ = await try throwingAndAsync() // expected-warning{{'try' must precede 'await'}}{{7-13=}}{{17-17=await }}
_ = await (try throwingAndAsync())
_ = try (await throwingAndAsync())
// Errors
_ = await throwingAndAsync() // expected-error{{call can throw but is not marked with 'try'}}
// expected-note@-1{{did you mean to use 'try'?}}{{7-7=try }}
// expected-note@-2{{did you mean to handle error as optional value?}}{{7-7=try? }}
// expected-note@-3{{did you mean to disable error propagation?}}{{7-7=try! }}
_ = try throwingAndAsync()
// expected-error@-1{{expression is 'async' but is not marked with 'await'}}{{11-11=await }}
// expected-note@-2{{call is 'async'}}
}
func testExhaustiveDoCatch() async {
do {
_ = try await throwingAndAsync()
} catch {
}
do {
_ = try await throwingAndAsync()
// expected-error@-1{{errors thrown from here are not handled because the enclosing catch is not exhaustive}}
} catch let e as HomeworkError {
}
// Ensure that we infer 'async' through an exhaustive do-catch.
let fn = {
do {
_ = try await throwingAndAsync()
} catch {
}
}
let _: Int = fn // expected-error{{cannot convert value of type '() async -> ()'}}
// Ensure that we infer 'async' through a non-exhaustive do-catch.
let fn2 = {
do {
_ = try await throwingAndAsync()
} catch let e as HomeworkError {
}
}
let _: Int = fn2 // expected-error{{cannot convert value of type '() async throws -> ()'}}
}
// String interpolation
func testStringInterpolation() async throws {
// expected-error@+2:30{{expression is 'async' but is not marked with 'await'}}{{30-30=await }}
// expected-note@+1:35{{call is 'async'}}
_ = "Eventually produces \(32 + getInt())"
_ = "Eventually produces \(await getInt())"
_ = await "Eventually produces \(getInt())"
}
func invalidAsyncFunction() async {
_ = try await throwingAndAsync() // expected-error {{errors thrown from here are not handled}}
}
func validAsyncFunction() async throws {
_ = try await throwingAndAsync()
}
// Async let checking
func mightThrow() throws { }
func getIntUnsafely() throws -> Int { 0 }
func getIntUnsafelyAsync() async throws -> Int { 0 }
extension Error {
var number: Int { 0 }
}
func testAsyncLet() async throws {
async let x = await getInt()
print(x) // expected-error{{expression is 'async' but is not marked with 'await'}}
// expected-note@-1:9{{reference to async let 'x' is 'async'}}
print(await x)
do {
try mightThrow()
} catch let e where e.number == x { // expected-error{{async let 'x' cannot be referenced in a catch guard expression}}
} catch {
}
defer {
async let deferX: Int = await getInt() // expected-error {{'async let' cannot be used on declarations in a defer body}}
_ = await deferX // expected-error {{async let 'deferX' cannot be referenced in a defer body}}
async let _: Int = await getInt() // expected-error {{'async let' cannot be used on declarations in a defer body}}
async let _ = await getInt() // expected-error {{'async let' cannot be used on declarations in a defer body}}
}
async let x1 = getIntUnsafely() // okay, try is implicit here
async let x2 = getInt() // okay, await is implicit here
async let x3 = try getIntUnsafely()
async let x4 = try! getIntUnsafely()
async let x5 = try? getIntUnsafely()
_ = await x1 // expected-error{{reading 'async let' can throw but is not marked with 'try'}}
_ = await x2
_ = try await x3
_ = await x4
_ = await x5
}
func search(query: String) async throws -> [String] {
let entities: [String] = []
async let r = entities.filter { $0.contains(query) }.map { String($0) }
return await r
}
// expected-note@+1 3{{add 'async' to function 'testAsyncLetOutOfAsync()' to make it asynchronous}} {{30-30= async}}
func testAsyncLetOutOfAsync() {
async let x = 1 // expected-error{{'async let' in a function that does not support concurrency}}
_ = await x // expected-error{{'async let' in a function that does not support concurrency}}
_ = x // expected-error{{'async let' in a function that does not support concurrency}}
}
class A {}
class B: A {}
func f(_ x: String) async -> String? { x }
func testAsyncExprWithoutAwait() async {
async let result: B? = nil
if let result: A = result {} // expected-error {{expression is 'async' but is not marked with 'await'}} {{22-22=await }}
// expected-warning@-1 {{immutable value 'result' was never used; consider replacing with '_' or removing it}}
// expected-note@-2 {{reference to async let 'result' is 'async'}}
if let result: A {} // expected-error {{expression is 'async' but is not marked with 'await'}} {{18-18=await }}
// expected-warning@-1 {{immutable value 'result' was never used; consider replacing with '_' or removing it}}
// expected-note@-2 {{reference to async let 'result' is 'async'}}
if let result = result {} // expected-error {{expression is 'async' but is not marked with 'await'}} {{19-19=await }}
// expected-warning@-1 {{value 'result' was defined but never used; consider replacing with boolean test}}
// expected-note@-2 {{reference to async let 'result' is 'async'}}
if let result {} // expected-error {{expression is 'async' but is not marked with 'await'}} {{10-10=await }}
// expected-warning@-1 {{value 'result' was defined but never used; consider replacing with boolean test}}
// expected-note@-2 {{reference to async let 'result' is 'async'}}
let a = f("a") // expected-error {{expression is 'async' but is not marked with 'await'}} {{11-11=await }}
// expected-warning@-1 {{initialization of immutable value 'a' was never used; consider replacing with assignment to '_' or removing it}}
// expected-note@-2 {{call is 'async'}}
}
|