mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
[Sema] Implement validation of @execution(...) in type context
This commit is contained in:
@@ -8257,10 +8257,14 @@ ERROR(attr_abi_incompatible_with_silgen_name,none,
|
||||
// MARK: @execution Attribute
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
ERROR(attr_execution_concurrent_only_on_async,none,
|
||||
"cannot use '@execution(concurrent)' on non-async %kind0",
|
||||
ERROR(attr_execution_only_on_async,none,
|
||||
"cannot use '@execution' on non-async %kind0",
|
||||
(ValueDecl *))
|
||||
|
||||
ERROR(attr_execution_type_attr_only_on_async,none,
|
||||
"cannot use '@execution' on non-async function type",
|
||||
())
|
||||
|
||||
ERROR(attr_execution_concurrent_incompatible_isolated_parameter,none,
|
||||
"cannot use '@execution(concurrent)' on %kind0 because it has "
|
||||
"an isolated parameter: %1",
|
||||
@@ -8276,6 +8280,19 @@ ERROR(attr_execution_concurrent_incompatible_with_nonisolated,none,
|
||||
"because they serve the same purpose",
|
||||
(ValueDecl *))
|
||||
|
||||
ERROR(attr_execution_concurrent_type_attr_incompatible_with_global_isolation,none,
|
||||
"cannot use '@execution(concurrent)' because function type is "
|
||||
"isolated to global actor %0",
|
||||
(Type))
|
||||
|
||||
ERROR(attr_execution_concurrent_type_attr_incompatible_with_isolated_param,none,
|
||||
"cannot use '@execution(concurrent)' together with isolated parameter",
|
||||
())
|
||||
|
||||
ERROR(attr_execution_concurrent_type_attr_incompatible_with_isolated_any,none,
|
||||
"cannot use '@execution(concurrent)' together with @isolated(any)",
|
||||
())
|
||||
|
||||
|
||||
#define UNDEFINE_DIAGNOSTIC_MACROS
|
||||
#include "DefineDiagnosticMacros.h"
|
||||
|
||||
@@ -259,8 +259,7 @@ public:
|
||||
return;
|
||||
|
||||
if (!F->hasAsync()) {
|
||||
diagnoseAndRemoveAttr(attr, diag::attr_execution_concurrent_only_on_async,
|
||||
F);
|
||||
diagnoseAndRemoveAttr(attr, diag::attr_execution_only_on_async, F);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -4197,6 +4197,51 @@ NeverNullType TypeResolver::resolveASTFunctionType(
|
||||
}
|
||||
}
|
||||
|
||||
if (auto executionAttr = claim<ExecutionTypeAttr>(attrs)) {
|
||||
if (!repr->isAsync()) {
|
||||
diagnoseInvalid(repr, executionAttr->getAtLoc(),
|
||||
diag::attr_execution_type_attr_only_on_async);
|
||||
}
|
||||
|
||||
switch (isolation.getKind()) {
|
||||
case FunctionTypeIsolation::Kind::NonIsolated:
|
||||
break;
|
||||
|
||||
case FunctionTypeIsolation::Kind::GlobalActor:
|
||||
diagnoseInvalid(
|
||||
repr, executionAttr->getAtLoc(),
|
||||
diag::
|
||||
attr_execution_concurrent_type_attr_incompatible_with_global_isolation,
|
||||
isolation.getGlobalActorType());
|
||||
break;
|
||||
|
||||
case FunctionTypeIsolation::Kind::Parameter:
|
||||
diagnoseInvalid(
|
||||
repr, executionAttr->getAtLoc(),
|
||||
diag::
|
||||
attr_execution_concurrent_type_attr_incompatible_with_isolated_param);
|
||||
break;
|
||||
|
||||
case FunctionTypeIsolation::Kind::Erased:
|
||||
diagnoseInvalid(
|
||||
repr, executionAttr->getAtLoc(),
|
||||
diag::
|
||||
attr_execution_concurrent_type_attr_incompatible_with_isolated_any);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!repr->isInvalid()) {
|
||||
switch (executionAttr->getBehavior()) {
|
||||
case ExecutionKind::Concurrent:
|
||||
// TODO: We need to introduce a new isolation kind to support this.
|
||||
break;
|
||||
case ExecutionKind::Caller:
|
||||
isolation = FunctionTypeIsolation::forNonIsolated();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (auto *lifetimeRepr = dyn_cast_or_null<LifetimeDependentTypeRepr>(
|
||||
repr->getResultTypeRepr())) {
|
||||
diagnoseInvalid(lifetimeRepr, lifetimeRepr->getLoc(),
|
||||
|
||||
44
test/Parse/execution.swift
Normal file
44
test/Parse/execution.swift
Normal file
@@ -0,0 +1,44 @@
|
||||
// RUN: %target-typecheck-verify-swift -disable-availability-checking
|
||||
|
||||
typealias F = @execution(concurrent) () async -> Void
|
||||
|
||||
typealias E = @execution(concurrent) () -> Void
|
||||
// expected-error@-1 {{cannot use '@execution' on non-async function type}}
|
||||
|
||||
func test1(_: @execution(caller) (Int...) async -> Void) {}
|
||||
func test2(_: @execution(concurrent) (Int...) async -> Void) {}
|
||||
|
||||
func test_err1(_: @execution(concurrent) @MainActor () async -> Void) {}
|
||||
// expected-error@-1 {{cannot use '@execution(concurrent)' because function type is isolated to global actor 'MainActor'}}
|
||||
|
||||
func test_err2(_: @execution(concurrent) @isolated(any) () async -> Void) {}
|
||||
// expected-error@-1 {{cannot use '@execution(concurrent)' together with @isolated(any)}}
|
||||
|
||||
func test_err3(_: @execution(concurrent) (isolated (any Actor)?) async -> Void) {}
|
||||
// expected-error@-1 {{cannot use '@execution(concurrent)' together with isolated parameter}}
|
||||
|
||||
func test_err4(_: @execution (Int) -> Void) {}
|
||||
// expected-error@-1 {{expected 'concurrent' or 'caller' as the execution behavior}}
|
||||
// expected-error@-2 {{expected parameter type following ':'}}
|
||||
|
||||
func test_err5(_: @execution( () async -> Void) {}
|
||||
// expected-error@-1 {{expected 'concurrent' or 'caller' as the execution behavior}}
|
||||
// expected-note@-2 {{to match this opening '('}}
|
||||
// expected-error@-3 {{expected ')' after execution behavior}}
|
||||
|
||||
func test_err6(_: @execution(hello) () async -> Void) {}
|
||||
// expected-error@-1 {{expected 'concurrent' or 'caller' as the execution behavior}}
|
||||
|
||||
func test_err7(_: @execution(hello () async -> Void) {}
|
||||
// expected-error@-1 {{expected 'concurrent' or 'caller' as the execution behavior}}
|
||||
// expected-note@-2 {{to match this opening '('}}
|
||||
// expected-error@-3 {{expected ')' after execution behavior}}
|
||||
|
||||
func test_err8(_: @execution(concurrent) Int) {} // expected-error {{attribute does not apply to type}}
|
||||
|
||||
do {
|
||||
let _ = [@execution(caller) () async -> Void]()
|
||||
let _ = [@execution(caller) () -> Void]()
|
||||
// expected-error@-1 {{cannot use '@execution' on non-async function type}}
|
||||
}
|
||||
|
||||
@@ -9,10 +9,10 @@
|
||||
// expected-error@-1 {{duplicate attribute}} expected-note@-1 {{attribute already specified here}}
|
||||
|
||||
@execution(concurrent) func nonAsync1() {}
|
||||
// expected-error@-1 {{cannot use '@execution(concurrent)' on non-async global function 'nonAsync1()'}}
|
||||
// expected-error@-1 {{cannot use '@execution' on non-async global function 'nonAsync1()'}}
|
||||
|
||||
@execution(caller) func nonAsync2() {}
|
||||
// expected-error@-1 {{cannot use '@execution(concurrent)' on non-async global function 'nonAsync2()'}}
|
||||
// expected-error@-1 {{cannot use '@execution' on non-async global function 'nonAsync2()'}}
|
||||
|
||||
@execution(concurrent) func testGlobal() async {} // Ok
|
||||
|
||||
@@ -21,7 +21,7 @@ struct Test {
|
||||
// expected-error@-1 {{@execution(concurrent) may only be used on 'func' declarations}}
|
||||
|
||||
@execution(concurrent) func member() {}
|
||||
// expected-error@-1 {{cannot use '@execution(concurrent)' on non-async instance method 'member()'}}
|
||||
// expected-error@-1 {{cannot use '@execution' on non-async instance method 'member()'}}
|
||||
|
||||
@execution(concurrent) func member() async {} // Ok
|
||||
|
||||
|
||||
Reference in New Issue
Block a user