Confusing error with sending value (+ opaque return type)

I've run into an odd compiler behaviour that disallows what seems to be a valid code, but doesn't compile. I'm using Xcode 16 beta 6 at the moment.

There is a protocol that looks like this:

protocol Command<In, Out> {
    associatedtype In
    associatedtype Out

    func execute(_ input: In) async throws -> Out
}

It was Sendable before, but I've revisited design and currently large amount of implementation use non-Sendable types (and those cannot & shouldn't be such), with hope to rely on region-based isolation, since commands are meant to be created, executed, and forgotten.

So now I have the following code (simplified), that I think should work, but compiler gives me an error:

protocol CommandsFactory {
    associatedtype LoggerCommandType: Command<String, Void>
    func logger() -> sending LoggerCommandType
}

@MainActor
final class UseCase<Factory> where Factory: CommandsFactory {
    private let factory: Factory

    init(factory: Factory) {
        self.factory = factory
    }

    func doSmth() async throws {
        let command = factory.logger()
        try await command.execute("did it!")  // error: sending 'command' risks causing data races
    }
}

From my understanding, command here in a clearly disconnected region, so it should be safe to use it.

Currently I blame it on protocol, because if I replace CommandsFactory to be just struct, the error is gone. Is this a compiler bug or I'm missing something?

UPD. Seems related to this issue:

Examples a bit different, but probably underlying reasons are the same.


The following seems to be reported and confirmed to be a bug: Cannot using `sending` with `some` return value · Issue #74846 · swiftlang/swift · GitHub

Also, either with CommandsFactory being a struct, or when I am going to implement protocol, having sending requirement makes it impossible to use opaque type:

struct MyCommandsFactory: CommandsFactory {
    // error: 'sending' may only be used on parameters and results
    func logger() -> sending some Command<String, Void> {  
        LoggerCommand()
    }
}

If I'd use concrete type instead of a protocol, it is fine even without sending (I guess compiler can reason about that), and I have an option to return just LoggerCommand explicitly, instead of using opaque type, but shouldn't this work? Or am I missing something?


UPD 2. I've found ever more odd workaround for now:

func doSmth() async throws {
    let factory = factory  // that piece is essential here
    try await Task { // as well as wrapping in a Task
        let command = factory.logger()
        try await command.execute("did it!") // ok!
    }.value
}

UPD 3. Finally, with command being property, I have this workaround working, while in my understanding, this should be disallowed?

@MainActor
final class Wrapper<CommandType> where CommandType: Command<String, Void> {
    private let command: CommandType

    init(_ command: CommandType) {
        self.command = command
    }

    func execute() async throws {
        let command = command
        try await Task {
            try await command.execute("I'm wrapped!") // no error!
        }.value
    }
}

I mean, there is no guarantee that command here is a value type, so let command = command might not create a disconnected copy, giving a potential data race I guess?