Skip to content

[Sema] Either variant of @execution is incompatible with other isol… #79497

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Feb 20, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 11 additions & 16 deletions include/swift/AST/DiagnosticsSema.def
Original file line number Diff line number Diff line change
Expand Up @@ -8289,32 +8289,27 @@ 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 "
ERROR(attr_execution_incompatible_isolated_parameter,none,
"cannot use '@execution' on %kind0 because it has "
"an isolated parameter: %1",
(ValueDecl *, ValueDecl *))

ERROR(attr_execution_concurrent_incompatible_dynamically_isolated_parameter,none,
"cannot use '@execution(concurrent)' on %kind0 because it has "
ERROR(attr_execution_incompatible_dynamically_isolated_parameter,none,
"cannot use '@execution' on %kind0 because it has "
"a dynamically isolated parameter: %1",
(ValueDecl *, ValueDecl *))

ERROR(attr_execution_concurrent_incompatible_with_nonisolated,none,
"cannot use '@execution(concurrent)' and 'nonisolated' on the same %0 "
"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",
ERROR(attr_execution_type_attr_incompatible_with_global_isolation,none,
"cannot use '@execution' because function type is "
"isolated to a 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_type_attr_incompatible_with_isolated_param,none,
"cannot use '@execution' together with an isolated parameter",
())

ERROR(attr_execution_concurrent_type_attr_incompatible_with_isolated_any,none,
"cannot use '@execution(concurrent)' together with @isolated(any)",
ERROR(attr_execution_type_attr_incompatible_with_isolated_any,none,
"cannot use '@execution' together with @isolated(any)",
())


Expand Down
48 changes: 17 additions & 31 deletions lib/Sema/TypeCheckAttr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -263,45 +263,31 @@ class AttributeChecker : public AttributeVisitor<AttributeChecker> {
return;
}

switch (attr->getBehavior()) {
case ExecutionKind::Concurrent: {
auto parameters = F->getParameters();
if (!parameters)
return;
auto parameters = F->getParameters();
if (!parameters)
return;

for (auto *P : *parameters) {
auto *repr = P->getTypeRepr();
if (!repr)
continue;
for (auto *P : *parameters) {
auto *repr = P->getTypeRepr();
if (!repr)
continue;

// isolated parameters affect isolation of the function itself
if (isa<IsolatedTypeRepr>(repr)) {
// isolated parameters affect isolation of the function itself
if (isa<IsolatedTypeRepr>(repr)) {
diagnoseAndRemoveAttr(
attr, diag::attr_execution_incompatible_isolated_parameter, F, P);
return;
}

if (auto *attrType = dyn_cast<AttributedTypeRepr>(repr)) {
if (attrType->has(TypeAttrKind::Isolated)) {
diagnoseAndRemoveAttr(
attr,
diag::attr_execution_concurrent_incompatible_isolated_parameter,
diag::attr_execution_incompatible_dynamically_isolated_parameter,
F, P);
return;
}

if (auto *attrType = dyn_cast<AttributedTypeRepr>(repr)) {
if (attrType->has(TypeAttrKind::Isolated)) {
diagnoseAndRemoveAttr(
attr,
diag::
attr_execution_concurrent_incompatible_dynamically_isolated_parameter,
F, P);
return;
}
}
}

break;
}

case ExecutionKind::Caller: {
// no restrictions for now.
break;
}
}
}

Expand Down
49 changes: 22 additions & 27 deletions lib/Sema/TypeCheckType.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4179,37 +4179,32 @@ NeverNullType TypeResolver::resolveASTFunctionType(
diag::attr_execution_type_attr_only_on_async);
}

if (executionAttr->getBehavior() == ExecutionKind::Concurrent) {
switch (isolation.getKind()) {
case FunctionTypeIsolation::Kind::NonIsolated:
break;
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::GlobalActor:
diagnoseInvalid(
repr, executionAttr->getAtLoc(),
diag::attr_execution_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::Parameter:
diagnoseInvalid(
repr, executionAttr->getAtLoc(),
diag::attr_execution_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;
case FunctionTypeIsolation::Kind::Erased:
diagnoseInvalid(
repr, executionAttr->getAtLoc(),
diag::attr_execution_type_attr_incompatible_with_isolated_any);
break;

case FunctionTypeIsolation::Kind::NonIsolatedCaller:
llvm_unreachable("cannot happen because multiple @execution attributes "
"aren't allowed.");
}
case FunctionTypeIsolation::Kind::NonIsolatedCaller:
llvm_unreachable("cannot happen because multiple @execution attributes "
"aren't allowed.");
}

if (!repr->isInvalid()) {
Expand Down
21 changes: 15 additions & 6 deletions test/Parse/execution.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,23 @@ typealias E = @execution(concurrent) () -> Void
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_err1_concurrent(_: @execution(concurrent) @MainActor () async -> Void) {}
// expected-error@-1 {{cannot use '@execution' because function type is isolated to a 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_err1_caller(_: @execution(caller) @MainActor () async -> Void) {}
// expected-error@-1 {{cannot use '@execution' because function type is isolated to a global actor 'MainActor'}}

func test_err3(_: @execution(concurrent) (isolated (any Actor)?) async -> Void) {}
// expected-error@-1 {{cannot use '@execution(concurrent)' together with isolated parameter}}
func test_err2_concurrent(_: @execution(concurrent) @isolated(any) () async -> Void) {}
// expected-error@-1 {{cannot use '@execution' together with @isolated(any)}}

func test_err2_caller(_: @execution(caller) @isolated(any) () async -> Void) {}
// expected-error@-1 {{cannot use '@execution' together with @isolated(any)}}

func test_err3_concurrent(_: @execution(concurrent) (isolated (any Actor)?) async -> Void) {}
// expected-error@-1 {{cannot use '@execution' together with an isolated parameter}}

func test_err3_caller(_: @execution(caller) (isolated (any Actor)?) async -> Void) {}
// expected-error@-1 {{cannot use '@execution' together with an isolated parameter}}

func test_err4(_: @execution (Int) -> Void) {}
// expected-error@-1 {{expected 'concurrent' or 'caller' as the execution behavior}}
Expand Down
9 changes: 5 additions & 4 deletions test/attr/attr_execution.swift
Original file line number Diff line number Diff line change
Expand Up @@ -44,19 +44,20 @@ struct TestAttributeCollisions {
@execution(concurrent) nonisolated func testNonIsolated() async {}

@execution(concurrent) func test(arg: isolated MainActor) async {}
// expected-error@-1 {{cannot use '@execution(concurrent)' on instance method 'test(arg:)' because it has an isolated parameter: 'arg'}}
// expected-error@-1 {{cannot use '@execution' on instance method 'test(arg:)' because it has an isolated parameter: 'arg'}}

@execution(concurrent) func testIsolationAny(arg: @isolated(any) () -> Void) async {}
// expected-error@-1 {{cannot use '@execution(concurrent)' on instance method 'testIsolationAny(arg:)' because it has a dynamically isolated parameter: 'arg'}}
// expected-error@-1 {{cannot use '@execution' on instance method 'testIsolationAny(arg:)' because it has a dynamically isolated parameter: 'arg'}}

@MainActor @execution(concurrent) func testGlobalActor() async {}
// expected-warning @-1 {{instance method 'testGlobalActor()' has multiple actor-isolation attributes ('MainActor' and 'execution(concurrent)')}}

@execution(caller) nonisolated func testNonIsolatedCaller() async {} // Ok
@MainActor @execution(caller) func testGlobalActorCaller() async {}
// expected-warning@-1 {{instance method 'testGlobalActorCaller()' has multiple actor-isolation attributes ('MainActor' and 'execution(caller)')}}
@execution(caller) func testCaller(arg: isolated MainActor) async {} // Ok

@execution(caller) func testCaller(arg: isolated MainActor) async {}
// expected-error@-1 {{cannot use '@execution' on instance method 'testCaller(arg:)' because it has an isolated parameter: 'arg'}}

@execution(concurrent) @Sendable func test(_: @Sendable () -> Void, _: sending Int) async {} // Ok
@execution(caller) @Sendable func testWithSendableCaller(_: @Sendable () -> Void, _: sending Int) async {} // Ok
}
Expand Down