File: reasync.swift

package info (click to toggle)
swiftlang 6.0.3-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 2,519,992 kB
  • sloc: cpp: 9,107,863; ansic: 2,040,022; asm: 1,135,751; python: 296,500; objc: 82,456; f90: 60,502; lisp: 34,951; pascal: 19,946; sh: 18,133; perl: 7,482; ml: 4,937; javascript: 4,117; makefile: 3,840; awk: 3,535; xml: 914; fortran: 619; cs: 573; ruby: 573
file content (165 lines) | stat: -rw-r--r-- 7,130 bytes parent folder | download
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
// RUN: %target-swift-frontend -enable-experimental-concurrency -disable-availability-checking %s -emit-sil -o /dev/null -verify
// RUN: %target-swift-frontend -enable-experimental-concurrency -disable-availability-checking %s -emit-sil -o /dev/null -verify -strict-concurrency=targeted
// RUN: %target-swift-frontend -enable-experimental-concurrency -disable-availability-checking %s -emit-sil -o /dev/null -verify -strict-concurrency=complete
// RUN: %target-swift-frontend -enable-experimental-concurrency -disable-availability-checking %s -emit-sil -o /dev/null -verify -strict-concurrency=complete -enable-upcoming-feature RegionBasedIsolation

// REQUIRES: concurrency
// REQUIRES: asserts

//// Basic definitions and parsing

func reasyncFunction(_: () async -> ()) reasync {}

func reasyncRethrowsFunction(_: () async throws -> ()) reasync rethrows {}

func rethrowsReasyncFunction(_: () async throws -> ()) rethrows reasync {}
// expected-error@-1 {{'reasync' must precede 'rethrows'}}{{65-73=}}{{56-56=reasync }}

func asyncReasyncFunction(_: () async throws -> ()) async reasync {}
// expected-error@-1 {{'reasync' has already been specified}}{{59-67=}}

func reasyncParam(_: () reasync -> ()) {}
// expected-error@-1 {{only function declarations may be marked 'reasync'; did you mean 'async'?}}{{25-32=async}}

//// Invalid cases

func noReasyncParams() reasync {}
// expected-error@-1 {{'reasync' function must take an 'async' function argument}}

//// Method override attribute checking

class Base {
  func reasyncMethod(_: () async -> ()) reasync {}
  // expected-note@-1 {{overridden declaration is here}}
}

class Derived : Base {
  override func reasyncMethod(_: () async -> ()) async {}
  // expected-error@-1 {{override of 'reasync' method should also be 'reasync'}}
}

//// Reasync call site checking

func asyncFunction() async {}

func callReasyncFunction() async {
  reasyncFunction { }
  await reasyncFunction { } // expected-warning {{no 'async' operations occur within 'await' expression}}

  reasyncFunction { await asyncFunction() }
  // expected-error@-1:3 {{expression is 'async' but is not marked with 'await'}}{{3-3=await }}
  // expected-note@-2:3 {{call is 'async'}}

  await reasyncFunction { await asyncFunction() }
}

enum HorseError : Error {
  case colic
}

func callReasyncRethrowsFunction() async throws {
  reasyncRethrowsFunction { }
  await reasyncRethrowsFunction { }
  // expected-warning@-1 {{no 'async' operations occur within 'await' expression}}
  try reasyncRethrowsFunction { }
  // expected-warning@-1 {{no calls to throwing functions occur within 'try' expression}}
  try await reasyncRethrowsFunction { }
  // expected-warning@-1 {{no 'async' operations occur within 'await' expression}}
  // expected-warning@-2 {{no calls to throwing functions occur within 'try' expression}}

  reasyncRethrowsFunction { await asyncFunction() }
  // expected-error@-1:3 {{expression is 'async' but is not marked with 'await'}}{{3-3=await }}
  // expected-note@-2:3 {{call is 'async'}}

  await reasyncRethrowsFunction { await asyncFunction() }
  try reasyncRethrowsFunction { await asyncFunction() }
  // expected-warning@-1 {{no calls to throwing functions occur within 'try' expression}}
  // expected-error@-2:3 {{expression is 'async' but is not marked with 'await'}}{{7-7=await }}
  // expected-note@-3:7 {{call is 'async'}}

  try await reasyncRethrowsFunction { await asyncFunction() }
  // expected-warning@-1 {{no calls to throwing functions occur within 'try' expression}}

  reasyncRethrowsFunction { throw HorseError.colic }
  // expected-error@-1 {{call can throw but is not marked with 'try'}}
  // expected-note@-2 {{call is to 'rethrows' function, but argument function can throw}}
  await reasyncRethrowsFunction { throw HorseError.colic }
  // expected-error@-1 {{call can throw but is not marked with 'try'}}
  // expected-note@-2 {{call is to 'rethrows' function, but argument function can throw}}
  // expected-warning@-3 {{no 'async' operations occur within 'await' expression}}
  try reasyncRethrowsFunction { throw HorseError.colic }
  try await reasyncRethrowsFunction { throw HorseError.colic }
  // expected-warning@-1 {{no 'async' operations occur within 'await' expression}}

  reasyncRethrowsFunction { await asyncFunction(); throw HorseError.colic }
  // expected-error@-1 {{call can throw but is not marked with 'try'}}
  // expected-note@-2 {{call is to 'rethrows' function, but argument function can throw}}
  // expected-error@-3:3 {{expression is 'async' but is not marked with 'await'}}{{3-3=await }}
  // expected-note@-4:3 {{call is 'async'}}
  await reasyncRethrowsFunction { await asyncFunction(); throw HorseError.colic }
  // expected-error@-1 {{call can throw but is not marked with 'try'}}
  // expected-note@-2 {{call is to 'rethrows' function, but argument function can throw}}
  try reasyncRethrowsFunction { await asyncFunction(); throw HorseError.colic }
  // expected-error@-1:3 {{expression is 'async' but is not marked with 'await'}}{{7-7=await }}
  // expected-note@-2:7 {{call is 'async'}}
  try await reasyncRethrowsFunction { await asyncFunction(); throw HorseError.colic }
}

func computeValue() -> Int {}
func computeValueAsync() async -> Int {}

func reasyncWithAutoclosure(_: @autoclosure () async -> Int) reasync {}

func callReasyncWithAutoclosure1() {
// expected-note@-1 2{{add 'async' to function 'callReasyncWithAutoclosure1()' to make it asynchronous}}
  reasyncWithAutoclosure(computeValue())
  await reasyncWithAutoclosure(await computeValueAsync())
  // expected-error@-1 {{'async' call in a function that does not support concurrency}}

  await reasyncWithAutoclosure(computeValueAsync())
  // expected-error@-1:32 {{expression is 'async' but is not marked with 'await'}}{{32-32=await }}
  // expected-note@-2:32 {{call is 'async' in an autoclosure argument}}
  // expected-error@-3 {{'async' call in a function that does not support concurrency}}
}

func callReasyncWithAutoclosure2() async {
  reasyncWithAutoclosure(computeValue())
  await reasyncWithAutoclosure(await computeValueAsync())

  await reasyncWithAutoclosure(15 + computeValueAsync())
  // 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}}
}

//// Reasync body checking

// FIXME: Need tailored diagnostics to handle 'reasync' vs 'sync'.

func invalidReasyncBody(_: () async -> ()) reasync {
// expected-note@-1 {{add 'async' to function 'invalidReasyncBody' to make it asynchronous}}
  _ = await computeValueAsync()
  // expected-error@-1 {{'async' call in a function that does not support concurrency}}
}

func validReasyncBody(_ fn: () async -> ()) reasync {
  await fn()
}

//// String interpolation

func reasyncWithAutoclosure2(_: @autoclosure () async -> String) reasync {}

func callReasyncWithAutoclosure3() {
  let world = 123
  reasyncWithAutoclosure2("Hello \(world)")
}

//// async let

func callReasyncWithAutoclosure4(_: () async -> ()) reasync {
  await reasyncFunction {
    async let x = 123

    _ = await x
  }
}