[Help] Some issues with compiling distributed actors project with latest trunk

Hello everyone!

I'm very intriguing in new distributed actors functionality, so I started to play with it before it officially released. As first step I would like to build some very simple distributed system on top of it,

Unfortunately during development I've faced some problems with compiling my code and after some investigation / googling I'm not sure lies in my code, but not in synthesized code.

Basically I have class conforming DistributedActorSystem protocol

@available(macOS 9999, *)
final class DataSystem : DistributedActorSystem {

    typealias ActorID = InstanceId
    typealias InvocationEncoder = DataInvocationEncoder
    typealias InvocationDecoder = DataInvocationDecoder
    typealias ResultHandler = DataInvocationResultHandler
    typealias SerializationRequirement = Codable
...

DataInvocationEncoder / DataInvocationDecoder are structs conforming corresponding protocols, all functions are declared, but implementation is basically empty or returning stubs.

It compiles fine with latest (4th of May) snapshot of trunk. Then I add first distributed actor declaration

@available(macOS 9999, *)
distributed actor Server {
    
    typealias ActorSystem = DataSystem
    
    typealias SerializationRequirement = Codable
    
    distributed func send() {
        
    }
    
}

and then compilation fails with next error which is unclear for me

<unknown>:0: error: '&' used with non-inout argument of type 'DataSystem.InvocationEncoder' (aka 'DataInvocationEncoder')
<unknown>:0: error: '&' used with non-inout argument of type 'DataSystem.InvocationEncoder' (aka 'DataInvocationEncoder')

Possible it could be some bug in code synthesized by compiler which pass &encoder to functions like remoteCall(...) where non-inout argument is expected or, most probably, I'm missing something.

Do you have any idea why I can get this error?

Hi there and thanks for the interest!

Would you mind pasting your entire distributed actor system implementation -- including all the method declarations? Since some of the protocol requirements are "ad-hoc" perhaps one of the signatures is wrong and we missed to diagnose it maybe?

I'm most interested in making sure your remoteCall(Void) signatures are correct; These do include an inout Encoder:

  func remoteCall<Act, Err, Res>(
      on actor: Act,
      target: RemoteCallTarget,
      invocation: inout InvocationEncoder, // must be inout
      throwing: Err.Type,
      returning: Res.Type
  ) async throws -> Res
    where Act: DistributedActor,
          Act.ID == ActorID,
          Err: Error,
          Res: SerializationRequirement {

--

minor: you don't need to declare the SerializationRequirement on the actor; it'll be synthesized from the ActorSystem used.

Yeap, pretty sure that's it -- we missed to diagnose a missing inout on the encoder parameter on remote call ad-hoc requirements, I'll send in a PR to fix it -- thanks for reporting!

Please verify on your end and let me know :slight_smile:


Bug: [Distributed] missing diagnosis for missing inout on remoteCall params Β· Issue #58671 Β· apple/swift Β· GitHub
Solution PR: [Distributed] Diagnose missing inout on remoteCall decls by ktoso Β· Pull Request #58672 Β· apple/swift Β· GitHub

Note that this is only a diagnosis bug; the signature of your remoteCall is wrong and cannot work if you are seeing the error from the first post -- so let's confirm you indeed were missing that inout there.

4 Likes

Hello Konrad!

Thanks for prompt reply!

Yep, seems it is a reason, I didn't have inout in removeCall / remoteCallVoid. I think I copied the signatures from proposal and there is no inout there.

After I added inout it compiles! Thanks!

Will be happy to verify changes in PR as soon it will be merged to trunk and I can download new toolchain.

4 Likes

Oh, thanks β€” I’ll make sure to fix up the proposal as well, so others don’t run into the same issue.

Thanks!