[Distributed] Allow disabling SerializationRequirement by using Any

It should be possible to disable SerializationRequirement by assigning
Any to it. This effectively disables the checking, since any type
conforms to that.

Previously we would crash trying to check for this conformance; or
rather, emitting diagnostics about un-necessary casts then encountering
incomplete types in CSDiagnostics.

Avoiding the cast entirely sounds like a good solution here.

resolves rdar://159285863
This commit is contained in:
Konrad Malawski
2025-09-05 17:02:07 +09:00
parent 592642087f
commit 9c0c70be5d
2 changed files with 111 additions and 8 deletions

View File

@@ -332,17 +332,24 @@ deriveBodyDistributed_invokeHandlerOnReturn(AbstractFunctionDecl *afd,
metatypeVar->setImplicit(); metatypeVar->setImplicit();
metatypeVar->setSynthesized(); metatypeVar->setSynthesized();
// If the SerializationRequirement requires it, we need to emit a cast:
// metatype as! <<concrete SerializationRequirement.Type>> // metatype as! <<concrete SerializationRequirement.Type>>
bool serializationRequirementIsAny =
metatypeParam->getInterfaceType()->getMetatypeInstanceType()->isEqual(
C.getAnyExistentialType());
auto metatypeRef = auto metatypeRef =
new (C) DeclRefExpr(ConcreteDeclRef(metatypeParam), dloc, implicit); new (C) DeclRefExpr(ConcreteDeclRef(metatypeParam), dloc, implicit);
auto metatypeSRCastExpr = ForcedCheckedCastExpr::createImplicit(
C, metatypeRef, serializationRequirementMetaTypeTy);
auto metatypePattern = NamedPattern::createImplicit(C, metatypeVar); auto metatypePattern = NamedPattern::createImplicit(C, metatypeVar);
auto metatypePB = PatternBindingDecl::createImplicit(
C, swift::StaticSpellingKind::None, metatypePattern,
/*expr=*/metatypeSRCastExpr, func);
PatternBindingDecl *metatypePB = serializationRequirementIsAny ?
PatternBindingDecl::createImplicit(
C, swift::StaticSpellingKind::None, metatypePattern,
/*expr=*/metatypeRef, func) :
PatternBindingDecl::createImplicit(
C, swift::StaticSpellingKind::None, metatypePattern,
/*expr=*/ForcedCheckedCastExpr::createImplicit(
C, metatypeRef, serializationRequirementMetaTypeTy), func);
stmts.push_back(metatypePB); stmts.push_back(metatypePB);
stmts.push_back(metatypeVar); stmts.push_back(metatypeVar);
} }
@@ -399,7 +406,6 @@ static FuncDecl *deriveDistributedActorSystem_invokeHandlerOnReturn(
auto system = derived.Nominal; auto system = derived.Nominal;
auto &C = system->getASTContext(); auto &C = system->getASTContext();
// auto serializationRequirementType = getDistributedActorSystemType(decl);
auto resultHandlerType = getDistributedActorSystemResultHandlerType(system); auto resultHandlerType = getDistributedActorSystemResultHandlerType(system);
auto unsafeRawPointerType = C.getUnsafeRawPointerType(); auto unsafeRawPointerType = C.getUnsafeRawPointerType();
auto anyTypeType = ExistentialMetatypeType::get(C.TheAnyType); // Any.Type auto anyTypeType = ExistentialMetatypeType::get(C.TheAnyType); // Any.Type
@@ -436,7 +442,7 @@ static FuncDecl *deriveDistributedActorSystem_invokeHandlerOnReturn(
/*throws=*/true, /*throws=*/true,
/*ThrownType=*/Type(), /*ThrownType=*/Type(),
/*genericParams=*/nullptr, params, /*genericParams=*/nullptr, params,
/*returnType*/ TupleType::getEmpty(C), system); /*returnType=*/TupleType::getEmpty(C), system);
funcDecl->setSynthesized(true); funcDecl->setSynthesized(true);
funcDecl->copyFormalAccessFrom(system, /*sourceIsParentContext=*/true); funcDecl->copyFormalAccessFrom(system, /*sourceIsParentContext=*/true);
funcDecl->setBodySynthesizer(deriveBodyDistributed_invokeHandlerOnReturn); funcDecl->setBodySynthesizer(deriveBodyDistributed_invokeHandlerOnReturn);

View File

@@ -0,0 +1,97 @@
// RUN: %target-swift-frontend -typecheck -verify -target %target-swift-5.7-abi-triple -I %t 2>&1 %s
// UNSUPPORTED: back_deploy_concurrency
// REQUIRES: concurrency
// REQUIRES: distributed
import Distributed
final class CrashActorSystem: DistributedActorSystem {
typealias ActorID = CrashActorID
typealias InvocationEncoder = CrashInvocationEncoder
typealias InvocationDecoder = CrashInvocationDecoder
typealias ResultHandler = CrashResultHandler
typealias SerializationRequirement = Any
func assignID<Actor: DistributedActor>(_: Actor.Type) -> ActorID where Actor.ID == ActorID {
fatalError()
}
func resignID(_: ActorID) {
// nothing
}
func actorReady<Actor: DistributedActor>(_: Actor) where Actor.ID == ActorID { }
func resolve<Actor: DistributedActor>(id _: ActorID, as _: Actor.Type) throws -> Actor? where Actor.ID == ActorID {
return nil
}
func makeInvocationEncoder() -> InvocationEncoder {
return InvocationEncoder()
}
func remoteCallVoid<Actor: DistributedActor, Failure: Error>(
on _: Actor,
target _: RemoteCallTarget,
invocation _: inout InvocationEncoder,
throwing _: Failure.Type
) async throws where Actor.ID == ActorID {
return
}
func remoteCall<Actor: DistributedActor, Failure: Error, Success: SerializationRequirement>(
on _: Actor,
target _: RemoteCallTarget,
invocation _: inout InvocationEncoder,
throwing _: Failure.Type,
returning _: Success.Type
) async throws -> Success where Actor.ID == ActorID {
fatalError()
}
}
struct CrashActorID: Hashable {
func hash(into hasher: inout Hasher) { }
}
struct CrashInvocationEncoder: DistributedTargetInvocationEncoder {
typealias SerializationRequirement = CrashActorSystem.SerializationRequirement
func recordGenericSubstitution<GenericSubstitution>(_: GenericSubstitution.Type) throws { }
mutating func recordArgument<Argument: SerializationRequirement>(_: RemoteCallArgument<Argument>) throws { }
mutating func recordReturnType<Success: SerializationRequirement>(_: Success.Type) throws { }
func recordErrorType<Failure: Error>(_: Failure.Type) throws { }
func doneRecording() throws { }
}
struct CrashInvocationDecoder: DistributedTargetInvocationDecoder {
typealias SerializationRequirement = CrashActorSystem.SerializationRequirement
func decodeGenericSubstitutions() throws -> [Any.Type] {
return []
}
mutating func decodeNextArgument<Argument: SerializationRequirement>() throws -> Argument {
fatalError()
}
func decodeReturnType() throws -> Any.Type? {
return nil
}
func decodeErrorType() throws -> Any.Type? {
return nil
}
}
struct CrashResultHandler: DistributedTargetInvocationResultHandler {
typealias SerializationRequirement = CrashActorSystem.SerializationRequirement
func onReturn<Success: SerializationRequirement>(value _: Success) async throws { }
func onReturnVoid() async throws { }
func onThrow<Failure: Error>(error _: Failure) async throws { }
}