skiptools / skiptools/skip-bridge
async throws closure fails to bridge: generated call to closure(forJavaObject:options:) is ambiguous
Nobody has claimed this yet.
- Dominant language
- Swift
- Stars
- 6
- Forks
- 7
- PR merge metrics
- No merged PRs in 30d
Description
Given an asynchronous+throwing closure like:
public init(closure: @escaping (String) async throws -> String)
the generated bridge is:
// ProbeThrowing_Bridge.swift:22
let p_0_swift = SwiftAsyncClosure1.closure(forJavaObject: p_0, options: [])! as (String) async throws -> String
which does not compile:
error: ambiguous use of 'closure(forJavaObject:options:)'
error: generic parameter 'T' could not be inferred
Closures.swift declares closure(forJavaObject:options:) twice for each arity, one returning (P0) async -> R and one returning (P0) async throws -> R. Swift chooses between overloads that differ only in return type using the surrounding context, and here the context asks for async throws and both candidates satisfy it (because Swift accepts a function that cannot throw wherever a throwing function is expected). The reverse conversion is not permitted, so a context asking for plain async leaves only one candidate, which is why non-throwing closures bridge fine.
Suggested fix
Disfavour the non-throwing overload, so the throwing one wins when both are viable:
extension SwiftAsyncClosure1 {
+ @_disfavoredOverload
public static func closure<P0, R>(forJavaObject function: JavaObjectPointer?, options: JConvertibleOptions) -> (@Sendable (P0) async -> R)? {
Environment
skip 1.9.3, skip-bridge 0.17.3, Swift Android SDK 6.3.3, bridging: true. Reproducer: <link> (./run.sh; skip android build is enough, no export needed).
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
The relevant overloads are declared in Closures.swift; start there and compare the async and async-throws closure(forJavaObject:options:) declarations. Run ./run.sh, or skip android build, with the provided reproducer, and consider the issue done when ProbeThrowing_Bridge.swift compiles without the ambiguous-overload error.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- kotlin, swift
- Domain
- mobile-dev
- Issue type
- Bug
- Difficulty
- 1/5
- Estimated time
- Under an hour
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 88/100