How to write @Sendable function composition by parameter packs and function overloading?

The compiler will complain about ambiguous function calls if I provide @Sendable function composition and the non-sendable version at the same time.

Do I really have to provide the compose function with difference names, e.g. sendableCompose, unsendableCompose?

@Sendable public func compose <each A, B, C>( _ g: @escaping @Sendable (B) -> C, _ f: @escaping @Sendable (repeat each A) -> B ) -> (repeat each A) -> C { { (args: repeat each A) in g(f(repeat each args)) } } public func compose <each A, B, C>( _ g: @escaping (B) -> C, _ f: @escaping (repeat each A) -> B ) -> (repeat each A) -> C { { (args: repeat each A) in g(f(repeat each args)) } } 
2 Likes

It should be

 public func compose <each A, B, C>( _ g: @escaping @Sendable (B) -> C, _ f: @escaping @Sendable (repeat each A) -> B ) -> @Sendable (repeat each A) -> C { { (args: repeat each A) in g(f(repeat each args)) } } public func compose <each A, B, C>( _ g: @escaping (B) -> C, _ f: @escaping (repeat each A) -> B ) -> (repeat each A) -> C { { (args: repeat each A) in g(f(repeat each args)) } } 

The leading @Sendable is unnecessary in Swift 6.0 (see SE-0418 )

The return value needs @Sendable.

1 Like

You can disambiguate with explicit Sendable. But how do you explicitly remove Sendable?

func f() { @Sendable func f(_: Never, _: Never) -> Never { } _ = compose(\.self, f) as @Sendable (_, _) -> _ // Compiles _ = compose(\.self, nonSendable(f)) // Compiles _ = compose(\.self, f) // Ambiguous use of 'compose' } 

You can get typed errors compiling with this signature, but the compiler crashes if you try to actually use that.

public func nonSendable<each Input, Value>( _ closure: @escaping @Sendable (repeat each Input) -> Value ) -> (repeat each Input) -> Value { closure }