@@ -125,17 +125,74 @@ struct IsolatedType {
125125 @concurrent func test( ) async { }
126126}
127127
128- _ = { @concurrent in // Ok
128+ // `@concurrent` on closures does not contribute to `async` inference.
129+ do {
130+ _ = { @concurrent in }
131+ // expected-error@-1:9 {{cannot use @concurrent on non-async closure}}{{none}}
132+ _ = { @concurrent ( ) -> Int in }
133+ // expected-error@-1:9 {{cannot use @concurrent on non-async closure}}{{none}}
134+ // Explicit effect precludes effects inference from the body.
135+ _ = { @concurrent ( ) throws in await awaitMe ( ) }
136+ // expected-error@-1:9 {{cannot use @concurrent on non-async closure}}{{none}}
137+ // expected-error@-2:40 {{'async' call in a function that does not support concurrency}}{{none}}
138+ _ = { @concurrent ( ) async in }
139+ _ = { @concurrent in await awaitMe ( ) }
140+
141+ func awaitMe( ) async { }
142+
143+ do {
144+ func foo( _: ( ) -> Void ) { }
145+ func foo( _: ( ) async -> Void ) async { }
146+
147+ func sync( ) {
148+ foo { @concurrent in }
149+ // expected-error@-1:13 {{cannot use @concurrent on non-async closure}}{{none}}
150+ }
151+ // expected-note@+1:10 {{add 'async' to function 'sync2()' to make it asynchronous}}{{17-17= async}}
152+ func sync2( ) {
153+ foo { @concurrent in await awaitMe ( ) }
154+ // expected-error@-1:7 {{'async' call in a function that does not support concurrency}}{{none}}
155+ }
156+ func async ( ) async {
157+ // Even though the context is async, the sync overload is favored because
158+ // the closure is sync, so the error is expected.
159+ foo { @concurrent in }
160+ // expected-error@-1:13 {{cannot use @concurrent on non-async closure}}{{none}}
161+
162+ foo { @concurrent in await awaitMe ( ) }
163+ // expected-error@-1:7 {{expression is 'async' but is not marked with 'await'}}{{7-7=await }}
164+ // expected-note@-2:7 {{call is 'async'}}{{none}}
165+ }
166+ }
167+
168+ do {
169+ func foo( _: ( Int ) async -> Void ) { }
170+ func foo( _: ( Int ) -> Void ) async { }
171+
172+ func sync( ) {
173+ // OK, sync overload picked.
174+ foo { @concurrent _ in }
175+ }
176+ func async ( ) async {
177+ foo { @concurrent _ in }
178+ // expected-error@-1:13 {{cannot use @concurrent on non-async closure}}{{none}}
179+ // expected-error@-2:7 {{expression is 'async' but is not marked with 'await'}}{{7-7=await }}
180+ // expected-note@-3:7 {{call is 'async'}}{{none}}
181+ }
182+ }
183+
184+ do {
185+ func foo< T> ( _: T ) { }
186+
187+ foo ( { @concurrent in } )
188+ // expected-error@-1:10 {{cannot use @concurrent on non-async closure}}{{none}}
189+ }
129190}
130191
131192_ = { @MainActor @concurrent in
132193 // expected-error@-1 {{cannot use @concurrent because function type is isolated to a global actor 'MainActor'}}
133194}
134195
135- _ = { @concurrent ( ) -> Int in
136- // expected-error@-1 {{@concurrent on non-async closure}}
137- }
138-
139196// Make sure that explicit use of `@concurrent` doesn't interfere with inference of `throws` from the body.
140197do {
141198 func acceptsThrowing( _ body: ( ) async throws -> Void ) async {
0 commit comments