Skip to content

[DNM] PoC of idempotent marker for remote calls (and oneway) - #93958

Draft
ktoso wants to merge 9 commits into
mainfrom
wip-idempotent
Draft

ktoso wants to merge 9 commits into
mainfrom
wip-idempotent

Conversation

@ktoso

@ktoso ktoso commented Nov 4, 2026 •

Copy link
Copy Markdown
Contributor

This is a PoC just to prepare the toolchain to play around with.

It comes with the incoming @oneway as and adds @_remoteCallIdempotent which can be used like:

@_remoteCallIdempotent distributed func ping() { }

which then allows remoteCall impls to detect for this, and for example setup an automatic retry if connections fail etc:

@_spi(DistributedIdempotent) import Distributed

extension RetryingActorSystem {
  func remoteCall<Act, Err, Res>(
    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 {
    let message = try RemoteCallMessage(
      recipient: actor.id, target: target.identifier, invocation: &invocation)

    if target.isIdempotentTarget { 
      // setup some form of retry-mechanism
    }
    // ... 
}

@ktoso

ktoso commented Nov 4, 2026

Copy link
Copy Markdown
Contributor Author

@swift-ci please build toolchain macOS

@ktoso ktoso added the distributed Feature → concurrency: distributed actor label Nov 4, 2026
@ktoso

ktoso commented Nov 5, 2026

Copy link
Copy Markdown
Contributor Author

swiftlang/swift-syntax#3498
@swift-ci Please Build Toolchain macOS Platform

@ktoso

ktoso commented Nov 5, 2026

Copy link
Copy Markdown
Contributor Author

swiftlang/swift-syntax#3498
@swift-ci Please Build Toolchain macOS Platform

@ktoso

ktoso commented Nov 6, 2026

Copy link
Copy Markdown
Contributor Author

swiftlang/swift-syntax#3498
swiftlang/sourcekit-lsp#2846
@swift-ci Please Build Toolchain macOS Platform

Add the experimental `SendCalls` feature and the `SendExpr` AST node, and parse `send <call>` in the C++ parser and in ASTGen. `send` is a contextual keyword, recognized only when it is followed on the same line by an identifier, `self` or a `$` identifier; the type checker rejects `send` calls for now.
ktoso added 8 commits November 6, 2026 19:36
Type check and lower `send` calls: the callee must be actor isolated, return `Void` and not throw, and the arguments are evaluated at the call site. A synchronous callee is enqueued through the `_enqueueOneway` helpers in `Actor+Send.swift`, an async callee runs in a discarding task which starts on the callee's actor.
…elpers

Instead of silently falling back to the task-based lowering, which changes the semantics of the call, emit `'send' requires newer _Concurrency library`.
Report `SendCalls` as used by a declaration whose printed inlinable body contains a `send`, so that the module interface guards it with `$SendCalls`.
…end` in the caller

Caller-side default arguments like `#isolation` were evaluated in the operation closure, so they saw its isolation rather than the caller's, and an explicit `#isolation` argument crashed the AST verifier with a duplicate macro discriminator once it was moved back to the call site. Evaluate them at the call site like any other argument, and assign macro discriminators before moving the expansions into the closure.
Add the `@oneway` declaration attribute for actor isolated functions which return `Void`, do not throw, and are meant to be called with `send`, and `@oneway(never)` for functions which should be awaited; awaiting a `@oneway` function or sending a `@oneway(never)` one is a warning (`AwaitedOnewayCall`, `SentOnewayNeverCall`). `@oneway` does not affect the function type or the mangling, so adding or removing it is ABI neutral, and functions which only differ in `@oneway` are redeclarations; `send` prefers a `@oneway` overload which differs in other ways.
…ed calls

A `@oneway` distributed function gets a synchronous, throwing distributed thunk next to its regular `async` one, and `try send d.f()` calls it directly: it hands a remote call to `remoteCallOneway` of the new SPI `_DistributedOnewayActorSystem` and sends a local call to the function. `RemoteCallTarget` gains `isOnewayRemoteCall` and `isOnewayTarget`, a plain function can witness a `@oneway` requirement through an adapter thunk, Embedded Swift dispatches oneway calls without a task, and the temporary "not supported yet" diagnostics are gone.
…nctions

Sent and awaited remote calls of a `@oneway` distributed function now both use the identifier of its await thunk, which is the identifier the function had before it became `@oneway`, and only `RemoteCallTarget.isOnewayRemoteCall` tells them apart. The receiving side runs both through the accessor and accessible function record of that thunk, like for any other function, so the synchronous thunk gets no record and the oneway proxy adapter dispatch is gone.
Add the `@_remoteCallIdempotent` attribute, which marks a distributed function
as safe to call more than once with the same arguments. The synthesized
distributed thunks of such a function mark the `RemoteCallTarget` of their
remote calls with the new `isIdempotentTarget` flag, next to the `@oneway`
flags, so that an actor system can make such a call more than once, e.g. to
retry it after a transport failure.

`isIdempotentTarget` is SPI in the `DistributedIdempotent` group and available
since Swift 6.5. The thunks set it through `_markIdempotentTarget()`, which is
emitted into the client and does nothing on older runtimes. The attribute only
changes the thunk bodies, so module interfaces drop it for older compilers.
@ktoso

ktoso commented Nov 6, 2026

Copy link
Copy Markdown
Contributor Author

swiftlang/swift-syntax#3498
swiftlang/sourcekit-lsp#2846
@swift-ci Please Build Toolchain macOS Platform

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

distributed Feature → concurrency: distributed actor

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant