Skip to content

Commit a535463

Browse files
committed
[Concurrency] async autoclosures are only legal on async functions.
1 parent 5dd1bfe commit a535463

File tree

3 files changed

+42
-22
lines changed

3 files changed

+42
-22
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2174,9 +2174,6 @@ NOTE(protocol_witness_settable_conflict,none,
21742174
"candidate is not settable, but protocol requires it", ())
21752175
NOTE(protocol_witness_rethrows_conflict,none,
21762176
"candidate is not 'rethrows', but protocol requires it", ())
2177-
NOTE(protocol_witness_async_conflict,none,
2178-
"candidate is %select{not |}0'async', but protocol requirement is%select{| not}0",
2179-
(bool))
21802177
NOTE(protocol_witness_throws_conflict,none,
21812178
"candidate throws, but protocol does not allow it", ())
21822179
NOTE(protocol_witness_not_objc,none,
@@ -4036,6 +4033,16 @@ NOTE(note_error_to_optional,none,
40364033
"did you mean to handle error as optional value?", ())
40374034
NOTE(note_disable_error_propagation,none,
40384035
"did you mean to disable error propagation?", ())
4036+
4037+
WARNING(no_throw_in_try,none,
4038+
"no calls to throwing functions occur within 'try' expression", ())
4039+
4040+
WARNING(no_throw_in_do_with_catch,none,
4041+
"'catch' block is unreachable because no errors are thrown in 'do' block", ())
4042+
4043+
//------------------------------------------------------------------------------
4044+
// MARK: Concurrency
4045+
//------------------------------------------------------------------------------
40394046
ERROR(async_call_without_await,none,
40404047
"call is 'async' but is not marked with 'await'", ())
40414048
ERROR(async_call_without_await_in_autoclosure,none,
@@ -4056,12 +4063,15 @@ ERROR(async_in_nonasync_function,none,
40564063
(bool, bool))
40574064
NOTE(note_add_async_to_function,none,
40584065
"add 'async' to function %0 to make it asynchronous", (DeclName))
4059-
4060-
WARNING(no_throw_in_try,none,
4061-
"no calls to throwing functions occur within 'try' expression", ())
4062-
4063-
WARNING(no_throw_in_do_with_catch,none,
4064-
"'catch' block is unreachable because no errors are thrown in 'do' block", ())
4066+
ERROR(not_objc_function_async,none,
4067+
"'async' function cannot be represented in Objective-C", ())
4068+
NOTE(not_objc_function_type_async,none,
4069+
"'async' function types cannot be represented in Objective-C", ())
4070+
NOTE(protocol_witness_async_conflict,none,
4071+
"candidate is %select{not |}0'async', but protocol requirement is%select{| not}0",
4072+
(bool))
4073+
ERROR(async_autoclosure_nonasync_function,none,
4074+
"'async' autoclosure parameter in a non-'async' function", ())
40654075

40664076
//------------------------------------------------------------------------------
40674077
// MARK: Type Check Types
@@ -4417,10 +4427,6 @@ NOTE(not_objc_generic_type_param,none,
44174427
NOTE(not_objc_function_type_param,none,
44184428
"function types cannot be represented in Objective-C unless their "
44194429
"parameters and returns can be", ())
4420-
ERROR(not_objc_function_async,none,
4421-
"'async' function cannot be represented in Objective-C", ())
4422-
NOTE(not_objc_function_type_async,none,
4423-
"'async' function types cannot be represented in Objective-C", ())
44244430
NOTE(not_objc_function_type_throwing,none,
44254431
"throwing function types cannot be represented in Objective-C", ())
44264432
NOTE(objc_inferring_on_objc_protocol_member,none,

lib/Sema/TypeCheckDecl.cpp

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2148,9 +2148,21 @@ static Type validateParameterType(ParamDecl *decl) {
21482148
decl->setInvalid();
21492149
return ErrorType::get(ctx);
21502150
}
2151+
}
21512152

2152-
return Ty;
2153+
// async autoclosures can only occur as parameters to async functions.
2154+
if (decl->isAutoClosure()) {
2155+
if (auto fnType = Ty->getAs<FunctionType>()) {
2156+
if (fnType->isAsync() &&
2157+
!(isa<AbstractFunctionDecl>(dc) &&
2158+
cast<AbstractFunctionDecl>(dc)->hasAsync())) {
2159+
auto func = cast<AbstractFunctionDecl>(dc);
2160+
decl->diagnose(diag::async_autoclosure_nonasync_function);
2161+
func->diagnose(diag::note_add_async_to_function, func->getName());
2162+
}
2163+
}
21532164
}
2165+
21542166
return Ty;
21552167
}
21562168

test/expr/unary/async_await.swift

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -33,20 +33,22 @@ struct SomeStruct {
3333
static var y = __await getInt() // expected-error{{'async' call cannot occur in a global variable initializer}}
3434
}
3535

36-
func acceptAutoclosureNonAsync(_: @autoclosure () -> Int) { }
37-
func acceptAutoclosureAsync(_: @autoclosure () async -> Int) { }
36+
func acceptAutoclosureNonAsync(_: @autoclosure () -> Int) async { }
37+
func acceptAutoclosureAsync(_: @autoclosure () async -> Int) async { }
38+
39+
func acceptAutoclosureNonAsyncBad(_: @autoclosure () async -> Int) { }
40+
// expected-error@-1{{'async' autoclosure parameter in a non-'async' function}}
41+
// expected-note@-2{{add 'async' to function 'acceptAutoclosureNonAsyncBad' to make it asynchronous}}
3842

3943
func testAutoclosure() async {
40-
acceptAutoclosureAsync(getInt()) // expected-error{{call is 'async' in an autoclosure argument is not marked with 'await'}}
41-
acceptAutoclosureNonAsync(getInt()) // expected-error{{'async' in an autoclosure that does not support concurrency}}
44+
__await acceptAutoclosureAsync(getInt()) // expected-error{{call is 'async' in an autoclosure argument is not marked with 'await'}}
45+
__await acceptAutoclosureNonAsync(getInt()) // expected-error{{'async' in an autoclosure that does not support concurrency}}
4246

43-
acceptAutoclosureAsync(__await getInt())
44-
acceptAutoclosureNonAsync(__await getInt()) // expected-error{{'async' in an autoclosure that does not support concurrency}}
47+
__await acceptAutoclosureAsync(__await getInt())
48+
__await acceptAutoclosureNonAsync(__await getInt()) // expected-error{{'async' in an autoclosure that does not support concurrency}}
4549

4650
__await acceptAutoclosureAsync(getInt()) // expected-error{{call is 'async' in an autoclosure argument is not marked with 'await'}}
47-
// expected-warning@-1{{no calls to 'async' functions occur within 'await' expression}}
4851
__await acceptAutoclosureNonAsync(getInt()) // expected-error{{'async' in an autoclosure that does not support concurrency}}
49-
// expected-warning@-1{{no calls to 'async' functions occur within 'await' expression}}
5052
}
5153

5254
// Test inference of 'async' from the body of a closure.

0 commit comments

Comments
 (0)