diff --git a/lib/AST/DistributedDecl.cpp b/lib/AST/DistributedDecl.cpp index b4179eba0c479..056c0c8dff6ce 100644 --- a/lib/AST/DistributedDecl.cpp +++ b/lib/AST/DistributedDecl.cpp @@ -440,6 +440,11 @@ bool AbstractFunctionDecl::isDistributedActorSystemRemoteCall(bool isVoidReturn) return false; } + auto *func = dyn_cast(this); + if (!func) { + return false; + } + // === Structural Checks // -- Must be throwing if (!hasThrows()) { @@ -451,6 +456,11 @@ bool AbstractFunctionDecl::isDistributedActorSystemRemoteCall(bool isVoidReturn) return false; } + // -- Must not be mutating, use classes to implement a system instead + if (func->isMutating()) { + return false; + } + // === Check generics if (!isGeneric()) { return false; @@ -1202,6 +1212,11 @@ AbstractFunctionDecl::isDistributedTargetInvocationResultHandlerOnReturn() const return false; } + // --- must not be mutating + if (func->isMutating()) { + return false; + } + // === Check generics if (!isGeneric()) { return false; diff --git a/lib/Sema/TypeCheckDistributed.cpp b/lib/Sema/TypeCheckDistributed.cpp index 95f4f26ceea4d..bde6d9023fcc4 100644 --- a/lib/Sema/TypeCheckDistributed.cpp +++ b/lib/Sema/TypeCheckDistributed.cpp @@ -247,7 +247,7 @@ bool swift::checkDistributedActorSystemAdHocProtocolRequirements( decl->getDescriptiveKind(), decl->getName(), identifier); decl->diagnose( diag::note_distributed_actor_system_conformance_missing_adhoc_requirement, - decl->getName(), identifier, + Proto->getName(), identifier, "func remoteCall(\n" " on actor: Act,\n" " target: RemoteCallTarget,\n" @@ -274,7 +274,7 @@ bool swift::checkDistributedActorSystemAdHocProtocolRequirements( decl->getDescriptiveKind(), decl->getName(), identifier); decl->diagnose( diag::note_distributed_actor_system_conformance_missing_adhoc_requirement, - decl->getName(), identifier, + Proto->getName(), identifier, "func remoteCallVoid(\n" " on actor: Act,\n" " target: RemoteCallTarget,\n" @@ -303,7 +303,7 @@ bool swift::checkDistributedActorSystemAdHocProtocolRequirements( diag::distributed_actor_system_conformance_missing_adhoc_requirement, decl->getDescriptiveKind(), decl->getName(), identifier); decl->diagnose(diag::note_distributed_actor_system_conformance_missing_adhoc_requirement, - decl->getName(), identifier, + Proto->getName(), identifier, "mutating func recordArgument(_ argument: RemoteCallArgument) throws\n"); anyMissingAdHocRequirements = true; } @@ -318,7 +318,7 @@ bool swift::checkDistributedActorSystemAdHocProtocolRequirements( diag::distributed_actor_system_conformance_missing_adhoc_requirement, decl->getDescriptiveKind(), decl->getName(), identifier); decl->diagnose(diag::note_distributed_actor_system_conformance_missing_adhoc_requirement, - decl->getName(), identifier, + Proto->getName(), identifier, "mutating func recordReturnType(_ resultType: Res.Type) throws\n"); anyMissingAdHocRequirements = true; } @@ -339,7 +339,7 @@ bool swift::checkDistributedActorSystemAdHocProtocolRequirements( diag::distributed_actor_system_conformance_missing_adhoc_requirement, decl->getDescriptiveKind(), decl->getName(), identifier); decl->diagnose(diag::note_distributed_actor_system_conformance_missing_adhoc_requirement, - decl->getName(), identifier, + Proto->getName(), identifier, "mutating func decodeNextArgument() throws -> Argument\n"); anyMissingAdHocRequirements = true; } @@ -360,10 +360,9 @@ bool swift::checkDistributedActorSystemAdHocProtocolRequirements( diag::distributed_actor_system_conformance_missing_adhoc_requirement, decl->getDescriptiveKind(), decl->getName(), identifier); decl->diagnose( - diag:: - note_distributed_actor_system_conformance_missing_adhoc_requirement, - decl->getName(), identifier, - "mutating func onReturn(value: " + diag::note_distributed_actor_system_conformance_missing_adhoc_requirement, + Proto->getName(), identifier, + "func onReturn(value: " "Success) async throws\n"); anyMissingAdHocRequirements = true; } @@ -448,8 +447,6 @@ bool swift::checkDistributedActorSystem(const NominalTypeDecl *system) { // work to enable associatedtypes to be constrained to class or protocol, // which then will unlock using them as generic constraints in protocols. Type requirementTy = getDistributedSerializationRequirementType(nominal, DAS); - requirementTy->dump(); - if (auto existentialTy = requirementTy->getAs()) { requirementTy = existentialTy->getConstraintType(); } diff --git a/test/Distributed/distributed_actor_system_missing_adhoc_requirement_impls.swift b/test/Distributed/distributed_actor_system_missing_adhoc_requirement_impls.swift index 9306161205f9e..ec698117a5b8d 100644 --- a/test/Distributed/distributed_actor_system_missing_adhoc_requirement_impls.swift +++ b/test/Distributed/distributed_actor_system_missing_adhoc_requirement_impls.swift @@ -8,10 +8,10 @@ import Distributed struct MissingRemoteCall: DistributedActorSystem { // expected-error@-1{{struct 'MissingRemoteCall' is missing witness for protocol requirement 'remoteCall'}} - // expected-note@-2{{protocol 'MissingRemoteCall' requires function 'remoteCall' with signature:}} + // expected-note@-2{{protocol 'DistributedActorSystem' requires function 'remoteCall' with signature:}} // expected-error@-4{{struct 'MissingRemoteCall' is missing witness for protocol requirement 'remoteCallVoid'}} - // expected-note@-5{{protocol 'MissingRemoteCall' requires function 'remoteCallVoid' with signature:}} + // expected-note@-5{{protocol 'DistributedActorSystem' requires function 'remoteCallVoid' with signature:}} typealias ActorID = ActorAddress typealias InvocationDecoder = FakeInvocationDecoder @@ -41,12 +41,73 @@ struct MissingRemoteCall: DistributedActorSystem { } } +struct RemoteCallMutating: DistributedActorSystem { + // expected-error@-1{{struct 'RemoteCallMutating' is missing witness for protocol requirement 'remoteCall'}} + // expected-note@-2{{protocol 'DistributedActorSystem' requires function 'remoteCall' with signature:}} + + // expected-error@-4{{struct 'RemoteCallMutating' is missing witness for protocol requirement 'remoteCallVoid'}} + // expected-note@-5{{protocol 'DistributedActorSystem' requires function 'remoteCallVoid' with signature:}} + + typealias ActorID = ActorAddress + typealias InvocationDecoder = FakeInvocationDecoder + typealias InvocationEncoder = FakeInvocationEncoder + typealias SerializationRequirement = Codable + typealias ResultHandler = FakeResultHandler + + func resolve(id: ActorID, as actorType: Act.Type) + throws -> Act? where Act: DistributedActor { + return nil + } + + func assignID(_ actorType: Act.Type) -> ActorID + where Act: DistributedActor { + ActorAddress(parse: "fake://123") + } + + func actorReady(_ actor: Act) + where Act: DistributedActor, + Act.ID == ActorID { + } + + func resignID(_ id: ActorID) { + } + + mutating func remoteCall( + on actor: Act, + target: RemoteCallTarget, + invocation: inout InvocationEncoder, + throwing: Err.Type, + returning: Res.Type + ) async throws -> Res + where Act: DistributedActor, + Act.ID == ActorID, + Err: Error, + Res: SerializationRequirement { + fatalError("NOT IMPLEMENTED \(#function)") + } + + mutating func remoteCallVoid( + on actor: Act, + target: RemoteCallTarget, + invocation: inout InvocationEncoder, + throwing: Err.Type + ) async throws + where Act: DistributedActor, + Act.ID == ActorID, + Err: Error { + fatalError("NOT IMPLEMENTED \(#function)") + } + + func makeInvocationEncoder() -> InvocationEncoder { + } +} + struct MissingRemoteCall_missingInout_on_encoder: DistributedActorSystem { // expected-error@-1{{struct 'MissingRemoteCall_missingInout_on_encoder' is missing witness for protocol requirement 'remoteCall'}} - // expected-note@-2{{protocol 'MissingRemoteCall_missingInout_on_encoder' requires function 'remoteCall' with signature:}} + // expected-note@-2{{protocol 'DistributedActorSystem' requires function 'remoteCall' with signature:}} // expected-error@-4{{struct 'MissingRemoteCall_missingInout_on_encoder' is missing witness for protocol requirement 'remoteCallVoid'}} - // expected-note@-5{{protocol 'MissingRemoteCall_missingInout_on_encoder' requires function 'remoteCallVoid' with signature:}} + // expected-note@-5{{protocol 'DistributedActorSystem' requires function 'remoteCallVoid' with signature:}} typealias ActorID = ActorAddress typealias InvocationDecoder = FakeInvocationDecoder @@ -160,10 +221,10 @@ struct MissingRemoteCall_missing_makeInvocationEncoder: DistributedActorSystem { struct Error_wrongReturn: DistributedActorSystem { // expected-error@-1{{struct 'Error_wrongReturn' is missing witness for protocol requirement 'remoteCall'}} - // expected-note@-2{{protocol 'Error_wrongReturn' requires function 'remoteCall' with signature:}} + // expected-note@-2{{protocol 'DistributedActorSystem' requires function 'remoteCall' with signature:}} // expected-error@-4{{struct 'Error_wrongReturn' is missing witness for protocol requirement 'remoteCallVoid'}} - // expected-note@-5{{protocol 'Error_wrongReturn' requires function 'remoteCallVoid' with signature:}} + // expected-note@-5{{protocol 'DistributedActorSystem' requires function 'remoteCallVoid' with signature:}} typealias ActorID = ActorAddress typealias InvocationDecoder = FakeInvocationDecoder @@ -235,10 +296,10 @@ struct Error_wrongReturn: DistributedActorSystem { struct BadRemoteCall_param: DistributedActorSystem { // expected-error@-1{{struct 'BadRemoteCall_param' is missing witness for protocol requirement 'remoteCall'}} - // expected-note@-2{{protocol 'BadRemoteCall_param' requires function 'remoteCall' with signature:}} + // expected-note@-2{{protocol 'DistributedActorSystem' requires function 'remoteCall' with signature:}} // expected-error@-4{{struct 'BadRemoteCall_param' is missing witness for protocol requirement 'remoteCallVoid'}} - // expected-note@-5{{protocol 'BadRemoteCall_param' requires function 'remoteCallVoid' with signature:}} + // expected-note@-5{{protocol 'DistributedActorSystem' requires function 'remoteCallVoid' with signature:}} typealias ActorID = ActorAddress typealias InvocationDecoder = FakeInvocationDecoder @@ -345,7 +406,7 @@ public struct BadRemoteCall_notPublic: DistributedActorSystem { public struct BadRemoteCall_badResultConformance: DistributedActorSystem { // expected-error@-1{{struct 'BadRemoteCall_badResultConformance' is missing witness for protocol requirement 'remoteCall'}} - // expected-note@-2{{protocol 'BadRemoteCall_badResultConformance' requires function 'remoteCall' with signature:}} + // expected-note@-2{{protocol 'DistributedActorSystem' requires function 'remoteCall' with signature:}} public typealias ActorID = ActorAddress public typealias InvocationDecoder = PublicFakeInvocationDecoder @@ -452,7 +513,7 @@ struct BadRemoteCall_largeSerializationRequirement: DistributedActorSystem { struct BadRemoteCall_largeSerializationRequirementSlightlyOffInDefinition: DistributedActorSystem { // expected-error@-1{{struct 'BadRemoteCall_largeSerializationRequirementSlightlyOffInDefinition' is missing witness for protocol requirement 'remoteCall'}} - // expected-note@-2{{protocol 'BadRemoteCall_largeSerializationRequirementSlightlyOffInDefinition' requires function 'remoteCall' with signature:}} + // expected-note@-2{{protocol 'DistributedActorSystem' requires function 'remoteCall' with signature:}} typealias ActorID = ActorAddress typealias InvocationDecoder = LargeSerializationReqFakeInvocationDecoder @@ -608,7 +669,7 @@ public struct PublicFakeInvocationEncoder: DistributedTargetInvocationEncoder { struct FakeInvocationEncoder_missing_recordArgument: DistributedTargetInvocationEncoder { //expected-error@-1{{struct 'FakeInvocationEncoder_missing_recordArgument' is missing witness for protocol requirement 'recordArgument'}} - //expected-note@-2{{protocol 'FakeInvocationEncoder_missing_recordArgument' requires function 'recordArgument' with signature:}} + //expected-note@-2{{protocol 'DistributedTargetInvocationEncoder' requires function 'recordArgument' with signature:}} typealias SerializationRequirement = Codable mutating func recordGenericSubstitution(_ type: T.Type) throws {} @@ -620,7 +681,7 @@ struct FakeInvocationEncoder_missing_recordArgument: DistributedTargetInvocation struct FakeInvocationEncoder_missing_recordArgument2: DistributedTargetInvocationEncoder { //expected-error@-1{{struct 'FakeInvocationEncoder_missing_recordArgument2' is missing witness for protocol requirement 'recordArgument'}} - //expected-note@-2{{protocol 'FakeInvocationEncoder_missing_recordArgument2' requires function 'recordArgument' with signature:}} + //expected-note@-2{{protocol 'DistributedTargetInvocationEncoder' requires function 'recordArgument' with signature:}} typealias SerializationRequirement = Codable mutating func recordGenericSubstitution(_ type: T.Type) throws {} @@ -632,7 +693,7 @@ struct FakeInvocationEncoder_missing_recordArgument2: DistributedTargetInvocatio struct FakeInvocationEncoder_missing_recordReturnType: DistributedTargetInvocationEncoder { //expected-error@-1{{struct 'FakeInvocationEncoder_missing_recordReturnType' is missing witness for protocol requirement 'recordReturnType'}} - //expected-note@-2{{protocol 'FakeInvocationEncoder_missing_recordReturnType' requires function 'recordReturnType' with signature:}} + //expected-note@-2{{protocol 'DistributedTargetInvocationEncoder' requires function 'recordReturnType' with signature:}} typealias SerializationRequirement = Codable mutating func recordGenericSubstitution(_ type: T.Type) throws {} @@ -655,7 +716,7 @@ struct FakeInvocationEncoder_missing_recordErrorType: DistributedTargetInvocatio struct FakeInvocationEncoder_recordArgument_wrongType: DistributedTargetInvocationEncoder { //expected-error@-1{{struct 'FakeInvocationEncoder_recordArgument_wrongType' is missing witness for protocol requirement 'recordArgument'}} - //expected-note@-2{{protocol 'FakeInvocationEncoder_recordArgument_wrongType' requires function 'recordArgument' with signature:}} + //expected-note@-2{{protocol 'DistributedTargetInvocationEncoder' requires function 'recordArgument' with signature:}} typealias SerializationRequirement = Codable mutating func recordGenericSubstitution(_ type: T.Type) throws {} @@ -668,7 +729,7 @@ struct FakeInvocationEncoder_recordArgument_wrongType: DistributedTargetInvocati } struct FakeInvocationEncoder_recordArgument_missingMutating: DistributedTargetInvocationEncoder { //expected-error@-1{{struct 'FakeInvocationEncoder_recordArgument_missingMutating' is missing witness for protocol requirement 'recordArgument'}} - //expected-note@-2{{protocol 'FakeInvocationEncoder_recordArgument_missingMutating' requires function 'recordArgument' with signature:}} + //expected-note@-2{{protocol 'DistributedTargetInvocationEncoder' requires function 'recordArgument' with signature:}} typealias SerializationRequirement = Codable mutating func recordGenericSubstitution(_ type: T.Type) throws {} @@ -680,7 +741,7 @@ struct FakeInvocationEncoder_recordArgument_missingMutating: DistributedTargetIn struct FakeInvocationEncoder_recordResultType_wrongType: DistributedTargetInvocationEncoder { //expected-error@-1{{struct 'FakeInvocationEncoder_recordResultType_wrongType' is missing witness for protocol requirement 'recordReturnType'}} - //expected-note@-2{{protocol 'FakeInvocationEncoder_recordResultType_wrongType' requires function 'recordReturnType' with signature:}} + //expected-note@-2{{protocol 'DistributedTargetInvocationEncoder' requires function 'recordReturnType' with signature:}} typealias SerializationRequirement = Codable mutating func recordGenericSubstitution(_ type: T.Type) throws {} @@ -757,7 +818,7 @@ public final class PublicFakeInvocationDecoder_badNotPublic: DistributedTargetIn final class PublicFakeInvocationDecoder_badBadProtoRequirement: DistributedTargetInvocationDecoder { // expected-error@-1{{class 'PublicFakeInvocationDecoder_badBadProtoRequirement' is missing witness for protocol requirement 'decodeNextArgument'}} - // expected-note@-2{{protocol 'PublicFakeInvocationDecoder_badBadProtoRequirement' requires function 'decodeNextArgument' with signature:}} + // expected-note@-2{{protocol 'DistributedTargetInvocationDecoder' requires function 'decodeNextArgument' with signature:}} typealias SerializationRequirement = Codable func decodeGenericSubstitutions() throws -> [Any.Type] { [] } @@ -809,16 +870,17 @@ struct LargeSerializationReqFakeInvocationResultHandler: DistributedTargetInvoca struct BadResultHandler_missingOnReturn: DistributedTargetInvocationResultHandler { // expected-error@-1{{struct 'BadResultHandler_missingOnReturn' is missing witness for protocol requirement 'onReturn'}} - // expected-note@-2{{protocol 'BadResultHandler_missingOnReturn' requires function 'onReturn' with signature:}} + // expected-note@-2{{protocol 'DistributedTargetInvocationResultHandler' requires function 'onReturn' with signature:}} typealias SerializationRequirement = Codable // func onReturn(value: Res) async throws {} // MISSING func onReturnVoid() async throws {} func onThrow(error: Err) async throws {} } + struct BadResultHandler_missingRequirement: DistributedTargetInvocationResultHandler { // expected-error@-1{{struct 'BadResultHandler_missingRequirement' is missing witness for protocol requirement 'onReturn'}} - // expected-note@-2{{protocol 'BadResultHandler_missingRequirement' requires function 'onReturn' with signature:}} + // expected-note@-2{{protocol 'DistributedTargetInvocationResultHandler' requires function 'onReturn' with signature:}} typealias SerializationRequirement = Codable func onReturn(value: Success) async throws {} // MISSING : Codable @@ -826,6 +888,16 @@ struct BadResultHandler_missingRequirement: DistributedTargetInvocationResultHan func onThrow(error: Err) async throws {} } +struct BadResultHandler_mutatingButShouldNotBe: DistributedTargetInvocationResultHandler { + // expected-error@-1{{struct 'BadResultHandler_mutatingButShouldNotBe' is missing witness for protocol requirement 'onReturn'}} + // expected-note@-2{{protocol 'DistributedTargetInvocationResultHandler' requires function 'onReturn' with signature:}} + typealias SerializationRequirement = Codable + + mutating func onReturn(value: Success) async throws {} // WRONG: can't be mutating + func onReturnVoid() async throws {} + func onThrow(error: Err) async throws {} +} + public struct PublicFakeResultHandler: DistributedTargetInvocationResultHandler { public typealias SerializationRequirement = Codable diff --git a/test/Distributed/distributed_serializationRequirement_must_be_protocol.swift b/test/Distributed/distributed_serializationRequirement_must_be_protocol.swift index cb496f78cbd05..35764b7ff0e99 100644 --- a/test/Distributed/distributed_serializationRequirement_must_be_protocol.swift +++ b/test/Distributed/distributed_serializationRequirement_must_be_protocol.swift @@ -16,9 +16,9 @@ final class SomeEnum: Sendable {} final class System: DistributedActorSystem { // ignore those since they all fail with the SerializationRequirement being invalid: // expected-error@-2{{type 'System' does not conform to protocol 'DistributedActorSystem'}} - // expected-note@-3{{protocol 'System' requires function 'remoteCallVoid'}} + // expected-note@-3{{protocol 'DistributedActorSystem' requires function 'remoteCallVoid'}} // expected-error@-4{{class 'System' is missing witness for protocol requirement 'remoteCall'}} - // expected-note@-5{{protocol 'System' requires function 'remoteCall' with signature:}} + // expected-note@-5{{protocol 'DistributedActorSystem' requires function 'remoteCall' with signature:}} // expected-error@-6{{class 'System' is missing witness for protocol requirement 'remoteCallVoid'}} typealias ActorID = String typealias InvocationEncoder = ClassInvocationEncoder @@ -81,9 +81,9 @@ final class System: DistributedActorSystem { } struct ClassInvocationEncoder: DistributedTargetInvocationEncoder { - // expected-note@-1{{protocol 'ClassInvocationEncoder' requires function 'recordArgument' with signature:}} + // expected-note@-1{{protocol 'DistributedTargetInvocationEncoder' requires function 'recordArgument' with signature:}} // expected-error@-2{{struct 'ClassInvocationEncoder' is missing witness for protocol requirement 'recordArgument'}} - // expected-note@-3{{protocol 'ClassInvocationEncoder' requires function 'recordReturnType' with signature:}} + // expected-note@-3{{protocol 'DistributedTargetInvocationEncoder' requires function 'recordReturnType' with signature:}} // expected-error@-4{{struct 'ClassInvocationEncoder' is missing witness for protocol requirement 'recordReturnType'}} typealias SerializationRequirement = SomeClazz @@ -97,7 +97,7 @@ struct ClassInvocationEncoder: DistributedTargetInvocationEncoder { final class ClassInvocationDecoder: DistributedTargetInvocationDecoder { // expected-error@-1{{class 'ClassInvocationDecoder' is missing witness for protocol requirement 'decodeNextArgument'}} - // expected-note@-2{{protocol 'ClassInvocationDecoder' requires function 'decodeNextArgument'}} + // expected-note@-2{{protocol 'DistributedTargetInvocationDecoder' requires function 'decodeNextArgument'}} typealias SerializationRequirement = SomeClazz public func decodeGenericSubstitutions() throws -> [Any.Type] {