Repository navigation
JNI: Swift Error values cross as Java Throwables - #25
Open
piercifani wants to merge 2 commits into
Open
piercifani wants to merge 2 commits into
piercifani wants to merge 2 commits into
Conversation
`Error` as a value, such as a completion handler's `Error?`, wasn't supported. Written `Error`, it was mistaken for a type of the module: the generated Java called `Error.wrapMemoryAddressUnsafe`, which `java.lang.Error` doesn't have, and neither side compiled. Written `any Error`, it was skipped, or a parameter became `<T extends Error>`. `Swift.Error` is now a known type, and `Error` or `any Error` is a `java.lang.Throwable` in parameters, results and optionals of them, in closures implemented in Java, and in closures returned to Java. - Swift to Java uses `makeJavaThrowable(for:)`, as thrown errors do: a jextracted error type becomes its exception class, another Swift error a `SwiftErrorException` holding it, and a Java exception that went through Swift is the same object again. A result is returned as a new local reference. - Java to Swift uses the new `makeSwiftError(for:)`: a `SwiftError` gives back a copy of the Swift error it holds, so `error as? LoadError` works after a round trip; any other exception is SwiftJava's `Throwable`. - `ErrorBridge` does both for closures returned to Java. 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
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 21/21 · base:
jni/20-nullability-annotations· previous: #24Problem
Erroras a value, such as a completion handler's(Error?) -> Void, wasn't supported, and in the most common spelling the output didn't compile.Error: jextract mistook it for one of the module's own types. The generated Java calledError.wrapMemoryAddressUnsafe(…)anderror.$memoryAddress(). In Java,Errormeansjava.lang.Error, which has neither, and the generated Swift failed the same way. Neither side compiled.any Error: results and closure arguments were skipped. A parameter became<T extends Error>, againjava.lang.Error.Thrown errors already worked: a Swift error enum becomes its own exception class, and any other error becomes
SwiftErrorException.Changes
Swift.Erroris now a known type, andErrororany Erroris ajava.lang.Throwablein these positions:Optional<Throwable>, orThrowablewithnullunderoptionalsAsNullable);Throwable;ErrorBridge.The conversions mirror thrown errors, so a round trip keeps the error:
makeJavaThrowable(for:), which thrown errors already use.SwiftErrorExceptionthat holds the Swift value.Throwablewrapper belongs to that wrapper.makeSwiftError(for:).SwiftError, the base ofSwiftErrorExceptionand of jextracted error types, gives back a copy of the Swift error it holds, soerror as? UploadErrorworks after a round trip.Throwable, which is already a SwiftError.A positive side effect: as a known type,
Errorin a position this PR doesn't cover is skipped, instead of producing code that doesn't compile.Kotlin in this PR
ErrorsTest.ktwithUploads.swift:Why Skip needs it
Skip bridges Swift
Errorto KotlinThrowablein every position. Completion handlers takingError?are common in Swift code: there are about 250(Error?) ->closure types in the app's packages.One difference from Skip: Skip turns a Swift error that has no Kotlin counterpart into an exception carrying only its description. Here it keeps the Swift value.
Testing
./gradlew :Samples:SwiftJavaExtractJNIKotlinSampleApp:testpasses (49 tests).JNIErrorValuesTests(2 tests): the Java signatures for every position, and the Swift conversions, the closure wrappers andErrorBridge.ErrorValuesTest(5 tests):assertSame);nilhandling;Error?;Error.swift test --disable-experimental-prebuilts --disable-sandbox(692 tests),./gradlew :Samples:SwiftJavaExtractJNISampleApp:test(307 tests) and./gradlew :SwiftKitCore:testpass.swift format formatleaves changed files unchanged;git diff --check.Not in this PR
Erroras a result of a closure implemented in Java, or as an array element.Failurebeyondany Error.🤖 Generated with Claude Code