Skip to content

Commit aad858d

Browse files
committed
[Sema] Implement validation of @execution(...) in type context
1 parent 84fb496 commit aad858d

File tree

5 files changed

+112
-7
lines changed

5 files changed

+112
-7
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8257,10 +8257,14 @@ ERROR(attr_abi_incompatible_with_silgen_name,none,
82578257
// MARK: @execution Attribute
82588258
//===----------------------------------------------------------------------===//
82598259

8260-
ERROR(attr_execution_concurrent_only_on_async,none,
8261-
"cannot use '@execution(concurrent)' on non-async %kind0",
8260+
ERROR(attr_execution_only_on_async,none,
8261+
"cannot use '@execution' on non-async %kind0",
82628262
(ValueDecl *))
82638263

8264+
ERROR(attr_execution_type_attr_only_on_async,none,
8265+
"cannot use '@execution' on non-async function type",
8266+
())
8267+
82648268
ERROR(attr_execution_concurrent_incompatible_isolated_parameter,none,
82658269
"cannot use '@execution(concurrent)' on %kind0 because it has "
82668270
"an isolated parameter: %1",
@@ -8276,6 +8280,19 @@ ERROR(attr_execution_concurrent_incompatible_with_nonisolated,none,
82768280
"because they serve the same purpose",
82778281
(ValueDecl *))
82788282

8283+
ERROR(attr_execution_concurrent_type_attr_incompatible_with_global_isolation,none,
8284+
"cannot use '@execution(concurrent)' because function type is "
8285+
"isolated to global actor %0",
8286+
(Type))
8287+
8288+
ERROR(attr_execution_concurrent_type_attr_incompatible_with_isolated_param,none,
8289+
"cannot use '@execution(concurrent)' together with isolated parameter",
8290+
())
8291+
8292+
ERROR(attr_execution_concurrent_type_attr_incompatible_with_isolated_any,none,
8293+
"cannot use '@execution(concurrent)' together with @isolated(any)",
8294+
())
8295+
82798296

82808297
#define UNDEFINE_DIAGNOSTIC_MACROS
82818298
#include "DefineDiagnosticMacros.h"

lib/Sema/TypeCheckAttr.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -259,8 +259,7 @@ class AttributeChecker : public AttributeVisitor<AttributeChecker> {
259259
return;
260260

261261
if (!F->hasAsync()) {
262-
diagnoseAndRemoveAttr(attr, diag::attr_execution_concurrent_only_on_async,
263-
F);
262+
diagnoseAndRemoveAttr(attr, diag::attr_execution_only_on_async, F);
264263
return;
265264
}
266265

lib/Sema/TypeCheckType.cpp

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4197,6 +4197,51 @@ NeverNullType TypeResolver::resolveASTFunctionType(
41974197
}
41984198
}
41994199

4200+
if (auto executionAttr = claim<ExecutionTypeAttr>(attrs)) {
4201+
if (!repr->isAsync()) {
4202+
diagnoseInvalid(repr, executionAttr->getAtLoc(),
4203+
diag::attr_execution_type_attr_only_on_async);
4204+
}
4205+
4206+
switch (isolation.getKind()) {
4207+
case FunctionTypeIsolation::Kind::NonIsolated:
4208+
break;
4209+
4210+
case FunctionTypeIsolation::Kind::GlobalActor:
4211+
diagnoseInvalid(
4212+
repr, executionAttr->getAtLoc(),
4213+
diag::
4214+
attr_execution_concurrent_type_attr_incompatible_with_global_isolation,
4215+
isolation.getGlobalActorType());
4216+
break;
4217+
4218+
case FunctionTypeIsolation::Kind::Parameter:
4219+
diagnoseInvalid(
4220+
repr, executionAttr->getAtLoc(),
4221+
diag::
4222+
attr_execution_concurrent_type_attr_incompatible_with_isolated_param);
4223+
break;
4224+
4225+
case FunctionTypeIsolation::Kind::Erased:
4226+
diagnoseInvalid(
4227+
repr, executionAttr->getAtLoc(),
4228+
diag::
4229+
attr_execution_concurrent_type_attr_incompatible_with_isolated_any);
4230+
break;
4231+
}
4232+
4233+
if (!repr->isInvalid()) {
4234+
switch (executionAttr->getBehavior()) {
4235+
case ExecutionKind::Concurrent:
4236+
// TODO: We need to introduce a new isolation kind to support this.
4237+
break;
4238+
case ExecutionKind::Caller:
4239+
isolation = FunctionTypeIsolation::forNonIsolated();
4240+
break;
4241+
}
4242+
}
4243+
}
4244+
42004245
if (auto *lifetimeRepr = dyn_cast_or_null<LifetimeDependentTypeRepr>(
42014246
repr->getResultTypeRepr())) {
42024247
diagnoseInvalid(lifetimeRepr, lifetimeRepr->getLoc(),

test/Parse/execution.swift

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
// RUN: %target-typecheck-verify-swift -disable-availability-checking
2+
3+
typealias F = @execution(concurrent) () async -> Void
4+
5+
typealias E = @execution(concurrent) () -> Void
6+
// expected-error@-1 {{cannot use '@execution' on non-async function type}}
7+
8+
func test1(_: @execution(caller) (Int...) async -> Void) {}
9+
func test2(_: @execution(concurrent) (Int...) async -> Void) {}
10+
11+
func test_err1(_: @execution(concurrent) @MainActor () async -> Void) {}
12+
// expected-error@-1 {{cannot use '@execution(concurrent)' because function type is isolated to global actor 'MainActor'}}
13+
14+
func test_err2(_: @execution(concurrent) @isolated(any) () async -> Void) {}
15+
// expected-error@-1 {{cannot use '@execution(concurrent)' together with @isolated(any)}}
16+
17+
func test_err3(_: @execution(concurrent) (isolated (any Actor)?) async -> Void) {}
18+
// expected-error@-1 {{cannot use '@execution(concurrent)' together with isolated parameter}}
19+
20+
func test_err4(_: @execution (Int) -> Void) {}
21+
// expected-error@-1 {{expected 'concurrent' or 'caller' as the execution behavior}}
22+
// expected-error@-2 {{expected parameter type following ':'}}
23+
24+
func test_err5(_: @execution( () async -> Void) {}
25+
// expected-error@-1 {{expected 'concurrent' or 'caller' as the execution behavior}}
26+
// expected-note@-2 {{to match this opening '('}}
27+
// expected-error@-3 {{expected ')' after execution behavior}}
28+
29+
func test_err6(_: @execution(hello) () async -> Void) {}
30+
// expected-error@-1 {{expected 'concurrent' or 'caller' as the execution behavior}}
31+
32+
func test_err7(_: @execution(hello () async -> Void) {}
33+
// expected-error@-1 {{expected 'concurrent' or 'caller' as the execution behavior}}
34+
// expected-note@-2 {{to match this opening '('}}
35+
// expected-error@-3 {{expected ')' after execution behavior}}
36+
37+
func test_err8(_: @execution(concurrent) Int) {} // expected-error {{attribute does not apply to type}}
38+
39+
do {
40+
let _ = [@execution(caller) () async -> Void]()
41+
let _ = [@execution(caller) () -> Void]()
42+
// expected-error@-1 {{cannot use '@execution' on non-async function type}}
43+
}
44+

test/attr/attr_execution.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,10 @@
99
// expected-error@-1 {{duplicate attribute}} expected-note@-1 {{attribute already specified here}}
1010

1111
@execution(concurrent) func nonAsync1() {}
12-
// expected-error@-1 {{cannot use '@execution(concurrent)' on non-async global function 'nonAsync1()'}}
12+
// expected-error@-1 {{cannot use '@execution' on non-async global function 'nonAsync1()'}}
1313

1414
@execution(caller) func nonAsync2() {}
15-
// expected-error@-1 {{cannot use '@execution(concurrent)' on non-async global function 'nonAsync2()'}}
15+
// expected-error@-1 {{cannot use '@execution' on non-async global function 'nonAsync2()'}}
1616

1717
@execution(concurrent) func testGlobal() async {} // Ok
1818

@@ -21,7 +21,7 @@ struct Test {
2121
// expected-error@-1 {{@execution(concurrent) may only be used on 'func' declarations}}
2222

2323
@execution(concurrent) func member() {}
24-
// expected-error@-1 {{cannot use '@execution(concurrent)' on non-async instance method 'member()'}}
24+
// expected-error@-1 {{cannot use '@execution' on non-async instance method 'member()'}}
2525

2626
@execution(concurrent) func member() async {} // Ok
2727

0 commit comments

Comments
 (0)