Repository navigation
JNI: Java overloads for trailing default arguments - #18
Open
piercifani wants to merge 4 commits into
Open
piercifani wants to merge 4 commits into
piercifani wants to merge 4 commits into
Conversation
Java and Kotlin callers had to pass every argument, including those with Swift defaults. Each function and initializer now gets an overload per trailing defaulted parameter it can be called without, like the existing variadic expansion. The overload's Swift thunk calls the function without those arguments, so Swift supplies its own defaults; no default expression is translated. An overload is skipped when a declared function already has that name and parameter types. JNI mode only; protocols are unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This was referenced Nov 3, 2026
…Kotlin Found with a view model's `Callbacks` whose closures all have defaults: - Overloads share their closure parameters' Swift `@JavaInterface` wrappers and Java helper class; each is now printed once. - With a result that may take a `SwiftArena`, `init(onOpen, SwiftArena)` was ambiguous with `init(onOpen, onClose)` for Kotlin lambdas, which convert to `SwiftArena`. Such an overload is left out when the next parameter is a closure and the longer overload exists. - A Java helper class gets a private constructor, so Kotlin's `T.init()` isn't ambiguous with constructing the helper class `T.init`. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stack 14/21 · base:
jni/13-java-enums· previous: #17 · next: #19 (jni/15-nullable-optionals)Problem
Swift default arguments didn't reach Java.
func greeting(name: String = "world", excited: Bool = false)became onlygreeting(String, boolean), so Java and Kotlin callers had to pass every argument and repeat the Swift defaults by hand.Changes
Each function and initializer now also gets one overload for each trailing defaulted parameter it can be called without. For the example:
greeting(String, boolean),greeting(String)andgreeting(). This works like the existing expansion of variadic parameters:AnalysisResult.expandDefaultArgumentOverloads()runs right afterexpandVariadicOverloadsin the JNI generator.greeting(name: …),greeting()), so Swift supplies its own defaults, whatever their expressions are.f(a: Int = 0, b: Int)gets no overload.f(a: Int64 = 0)next tof()produces only the two declared ones.Callbacks, need three more things:@JavaInterfacewrappers and Java helper class, so each is printed once.SwiftArena(initializers, and results other than primitives, strings andVoid) also gets an overload ending inSwiftArena, and a Kotlin lambda converts to it. Soinit(onOpen, SwiftArena)would be ambiguous withinit(onOpen, onClose). Such an overload is left out when the next parameter is a closure and the longer overload exists.Callbacks(onOpen:onClose:)getsinit(onOpen, onClose)andinit().Callbacks.init()isn't ambiguous with constructing the helper classCallbacks.init. Existing tests that spell out a helper class now include it.Overloads are only added, so existing callers are unaffected.
Kotlin in this PR
DefaultArgumentsTest.ktwithReceipts.swift:ReceiptPrinterhas two defaulted callbacks: Kotlin passes both lambdas,ReceiptPrinter.init({ lines += it }, { failed = true }), or neither,ReceiptPrinter.init().Kotlin named arguments still don't apply to Java methods, so only trailing arguments can be left out.
Why Skip needs it
Skip turns Swift default arguments into Kotlin default parameters, and app Kotlin code leaves them out. Without these overloads, every such call would have to spell out the Swift default.
Testing
./gradlew :Samples:SwiftJavaExtractJNIKotlinSampleApp:testpasses (39 tests).JNIDefaultArgumentsTests(7 tests): the Java overloads and their natives; the Swift calls leaving the arguments out; initializer overloads; declared overloads win, checked on the expanded analysis; no overload for a non-trailing default; closure overloads that would be ambiguous with an arena are left out (but kept for aVoidresult); closure wrappers and helper classes printed once.DefaultArgumentsTestcallsgreeting(),greeting("Ana")andgreeting("Ana", true).swift test --disable-experimental-prebuilts --disable-sandbox(668 tests) and./gradlew :Samples:SwiftJavaExtractJNISampleApp:test(293 tests) pass.swift format lint --stricton changed files;git diff --check.Not in this PR
🤖 Generated with Claude Code