skiptools / skiptools/skip-bridge

async throws closure fails to bridge: generated call to closure(forJavaObject:options:) is ambiguous

Open Beginner friendly
#116 1 comment 0 reactions 0 assignees View on GitHub

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

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.