Skip to content

Commit e94aa36

Browse files
ktosokavon
authored andcommitted
[Concurrency] Ban multiple isolated params, as per SE-0313
1 parent deb2fbd commit e94aa36

File tree

3 files changed

+54
-2
lines changed

3 files changed

+54
-2
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4832,6 +4832,9 @@ NOTE(protocol_isolated_to_global_actor_here,none,
48324832

48334833
ERROR(isolated_parameter_not_actor,none,
48344834
"'isolated' parameter has non-actor type %0", (Type))
4835+
ERROR(isolated_parameter_second_isolated_param,none,
4836+
"function cannot have more than one 'isolated' parameter (%0 and %1)",
4837+
(DeclName, DeclName))
48354838

48364839
WARNING(non_sendable_param_type,none,
48374840
"non-sendable type %0 %select{passed in call to %4 %2 %3|"

lib/Sema/TypeCheckConcurrency.cpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3086,6 +3086,30 @@ void swift::checkTopLevelActorIsolation(TopLevelCodeDecl *decl) {
30863086
body->walk(checker);
30873087
}
30883088

3089+
static bool checkDuplicateIsolatedParameter(AbstractFunctionDecl *decl) {
3090+
// If we have already seen at least one 'isolated' parameter,
3091+
// and we see another one, this is invalid as only one 'isolated' param
3092+
// per function is allowed.
3093+
// See:
3094+
// https://github.com/apple/swift-evolution/blob/main/proposals/0313-actor-isolation-control.md#multiple-isolated-parameters
3095+
ParamDecl* previousIsolatedParam = nullptr;
3096+
for (size_t i = 0; i < decl->getParameters()->size(); ++i) {
3097+
auto param = decl->getParameters()->get(i);
3098+
if (param->isIsolated()) {
3099+
if (auto previous = previousIsolatedParam) {
3100+
decl->diagnose(diag::isolated_parameter_second_isolated_param,
3101+
previous->getParameterName(),
3102+
param->getParameterName());
3103+
return true;
3104+
}
3105+
3106+
previousIsolatedParam = const_cast<ParamDecl*>(param);
3107+
}
3108+
}
3109+
3110+
return false;
3111+
}
3112+
30893113
void swift::checkFunctionActorIsolation(AbstractFunctionDecl *decl) {
30903114
// Disable this check for @LLDBDebuggerFunction functions.
30913115
if (decl->getAttrs().hasAttribute<LLDBDebuggerFunctionAttr>())
@@ -3099,6 +3123,8 @@ void swift::checkFunctionActorIsolation(AbstractFunctionDecl *decl) {
30993123
if (auto superInit = ctor->getSuperInitCall())
31003124
superInit->walk(checker);
31013125
}
3126+
3127+
checkDuplicateIsolatedParameter(decl);
31023128
if (decl->getAttrs().hasAttribute<DistributedActorAttr>()) {
31033129
if (auto func = dyn_cast<FuncDecl>(decl)) {
31043130
checkDistributedFunction(func);

test/Concurrency/isolated_parameters.swift

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ extension Actor {
1212
}
1313

1414
@available(SwiftStdlib 5.1, *)
15-
func testA<T: Actor>(
15+
func testA<T: Actor>( // expected-error{{function cannot have more than one 'isolated' parameter ('a' and 'b')}}
1616
a: isolated A,
1717
b: isolated T,
1818
c: isolated Int // expected-error{{'isolated' parameter has non-actor type 'Int'}}
@@ -22,6 +22,29 @@ func testA<T: Actor>(
2222
b.g()
2323
}
2424

25+
actor Other {
26+
func inc() {}
27+
func pass(_ f: @Sendable (Self) async -> Void) {}
28+
}
29+
actor Counter {
30+
func inc() {}
31+
func pass(_ f: @Sendable (Self) async -> Void) {}
32+
}
33+
34+
@available(SwiftStdlib 5.1, *)
35+
func testDoubleIsolatedParams(a: isolated Counter, b: isolated Other) async { // expected-error{{function cannot have more than one 'isolated' parameter ('a' and 'b')}}
36+
a.inc()
37+
b.inc()
38+
}
39+
40+
func taaaa() async {
41+
await Counter().pass { isoC in
42+
await Other().pass { isoO in
43+
await testDoubleIsolatedParams(a: isoC, b: isoO)
44+
}
45+
}
46+
}
47+
2548
@available(SwiftStdlib 5.1, *)
2649
typealias Fn = (isolated A) -> Void
2750

@@ -107,7 +130,7 @@ func redecl(_: isolated TestActor) { } // expected-error{{invalid redeclaration
107130
func tuplify<Ts>(_ fn: (Ts) -> Void) {} // expected-note {{in call to function 'tuplify'}}
108131

109132
@available(SwiftStdlib 5.1, *)
110-
func testTuplingIsolated(_ a: isolated A, _ b: isolated A) {
133+
func testTuplingIsolated(_ a: isolated A, _ b: isolated A) { // expected-error{{function cannot have more than one 'isolated' parameter ('a' and 'b')}}
111134
tuplify(testTuplingIsolated)
112135
// expected-error@-1 {{generic parameter 'Ts' could not be inferred}}
113136
// expected-error@-2 {{cannot convert value of type '(isolated A, isolated A) -> ()' to expected argument type '(Ts) -> Void'}}

0 commit comments

Comments
 (0)