Skip to content

Commit 1d64558

Browse files
authored
Merge pull request #68612 from kavon/generic-params-isolated
[Concurrency] tighten-up rules about isolated generic parameters
2 parents dffda32 + 16af507 commit 1d64558

File tree

4 files changed

+31
-3
lines changed

4 files changed

+31
-3
lines changed

include/swift/AST/DiagnosticsSema.def

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

53325332
ERROR(isolated_parameter_not_actor,none,
53335333
"'isolated' parameter has non-actor type %0", (Type))
5334+
ERROR(isolated_parameter_no_actor_conformance,none,
5335+
"'isolated' parameter %0 must conform to 'Actor' "
5336+
"or 'DistributedActor' protocol", (Type))
53345337
ERROR(isolated_parameter_duplicate,none,
53355338
"cannot have more than one 'isolated' parameter", ())
53365339
ERROR(isolated_parameter_duplicate_type,none,

lib/Sema/TypeCheckConcurrency.cpp

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4092,12 +4092,26 @@ ActorIsolation ActorIsolationRequest::evaluate(
40924092
if (auto paramIdx = getIsolatedParamIndex(value)) {
40934093
checkDeclWithIsolatedParameter(value);
40944094

4095-
// FIXME: This doesn't allow us to find an Actor or DistributedActor
4096-
// bound on the parameter type effectively.
4097-
auto param = getParameterList(value)->get(*paramIdx);
4095+
ParamDecl *param = getParameterList(value)->get(*paramIdx);
40984096
Type paramType = param->getInterfaceType();
40994097
if (paramType->isTypeParameter()) {
41004098
paramType = param->getDeclContext()->mapTypeIntoContext(paramType);
4099+
4100+
auto &ctx = value->getASTContext();
4101+
auto conformsTo = [&](KnownProtocolKind kind) {
4102+
if (auto *proto = ctx.getProtocol(kind))
4103+
return value->getModuleContext()->conformsToProtocol(paramType, proto);
4104+
return ProtocolConformanceRef::forInvalid();
4105+
};
4106+
4107+
// The type parameter must be bound by Actor or DistributedActor, as they
4108+
// have an unownedExecutor. AnyActor does NOT have an unownedExecutor!
4109+
if (!conformsTo(KnownProtocolKind::Actor)
4110+
&& !conformsTo(KnownProtocolKind::DistributedActor)) {
4111+
ctx.Diags.diagnose(param->getLoc(),
4112+
diag::isolated_parameter_no_actor_conformance,
4113+
paramType);
4114+
}
41014115
}
41024116

41034117
if (auto actor = paramType->getAnyActor())

test/Concurrency/isolated_parameters.swift

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -348,3 +348,12 @@ func getValues(
348348
actor.dictionary[key]
349349
}
350350
}
351+
352+
func isolated_generic_bad_1<T>(_ t: isolated T) {}
353+
// expected-error@-1 {{'isolated' parameter 'T' must conform to 'Actor' or 'DistributedActor' protocol}}
354+
func isolated_generic_bad_2<T: Equatable>(_ t: isolated T) {}
355+
// expected-error@-1 {{'isolated' parameter 'T' must conform to 'Actor' or 'DistributedActor' protocol}}
356+
func isolated_generic_bad_3<T: AnyActor>(_ t: isolated T) {}
357+
// expected-error@-1 {{'isolated' parameter 'T' must conform to 'Actor' or 'DistributedActor' protocol}}
358+
359+
func isolated_generic_ok_1<T: Actor>(_ t: isolated T) {}

test/Distributed/distributed_actor_isolation.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,3 +258,5 @@ extension Greeting where SerializationRequirement == Codable {
258258
try await greetLocal(name: "Alice") // expected-error{{only 'distributed' instance methods can be called on a potentially remote distributed actor}}
259259
}
260260
}
261+
262+
func isolated_generic_ok<T: DistributedActor>(_ t: isolated T) {}

0 commit comments

Comments
 (0)