jextract/jni: Add basic support for generic types#572
jextract/jni: Add basic support for generic types#572sidepelican wants to merge 24 commits intoswiftlang:mainfrom
Conversation
# Conflicts: # Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift # Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift
| if (CallTraces.TRACE_DOWNCALLS) { | ||
| CallTraces.traceDowncall("MyID.$destroy", "self", self$); | ||
| } | ||
| MyID.$destroy(self$, selfType$); |
| if (CallTraces.TRACE_DOWNCALLS) { | ||
| CallTraces.traceDowncall("MyID.$createDestroyFunction", | ||
| "this", this, | ||
| "self", self$); |
There was a problem hiding this comment.
Let's include the selfType$ now as well
| expectedChunks: [ | ||
| """ | ||
| protocol _SwiftModule_MyID_opener { | ||
| static func _get_description(environment: UnsafeMutablePointer<JNIEnv?>!, thisClass: jclass, self: jlong) -> jstring? |
There was a problem hiding this comment.
| static func _get_description(environment: UnsafeMutablePointer<JNIEnv?>!, thisClass: jclass, self: jlong) -> jstring? | |
| static func _get_description(environment: UnsafeMutablePointer<JNIEnv?>!, thisClass: jclass, selfPointer: jlong) -> jstring? |
sorry to be annoying about the selfPointer every time 😉
I don't want it to be confusing when we see a self it should be the object and the selfPointer should be the jlong or other pointer repr
There was a problem hiding this comment.
I see. I don't have a strong preference, so I think selfPointer is fine as well.
The variable name self originates from this location:
Changing this to selfPointer would require updating a large number of existing tests.
Would you still like me to proceed with the change?
There was a problem hiding this comment.
Yeah let's bite the bullet, we can do it in a separate PR.
This is looking good, happy to land it after some nitpicks
|
|
||
| package org.swift.swiftkit.core; | ||
|
|
||
| public final class OutSwiftGenericInstance { |
There was a problem hiding this comment.
Please document what this is for
|
|
||
| public final class OutSwiftGenericInstance { | ||
| public long selfPointer; | ||
| public long selfTypePointer; |
There was a problem hiding this comment.
| public long selfTypePointer; | |
| public final long selfTypePointer; |
If making them public please make them final
There was a problem hiding this comment.
OutSwiftGenericInstance is a temporary container used for receiving multiple return values.
Both selfPointer and selfTypePointer are updated from the Swift side using JNI's SetLongField.
While JNI can technically bypass the final modifier to modify fields, I'm concerned that JIT optimizations might lead to unexpected behavior if the compiler makes incorrect assumptions about these values being constant.
Should I add the final modifier ?
| package org.swift.swiftkit.core; | ||
|
|
||
| public final class OutSwiftGenericInstance { | ||
| public long selfPointer; |
There was a problem hiding this comment.
| public long selfPointer; | |
| public final long selfPointer; |
If making them public please make them final
| | Dictionaries: `[String: Int]`, `[K:V]` | ❌ | ❌ | | ||
| | Generic type: `struct S<T>` | ❌ | ✅ | | ||
| | Functions or properties using generic type param: `struct S<T> { func f(_: T) {} }` | ❌ | ❌ | | ||
| | Static functions or properties in generic type | ❌ | ❌ | |
There was a problem hiding this comment.
This deserves some more docs about how we import it, since we drop the generic from the signature we should explain this -- but for simple things I thikn we'll be able to pull off doing a generic on the Java side tbh right?
There was a problem hiding this comment.
I wrote documentation to make it clearer what gets exported and what doesn't.
ktoso
left a comment
There was a problem hiding this comment.
I'm happy to merge this as a first step towards generics support :) Just the few nitpicks please
|
I just fixed the android CI, a new run should pass |
Purpose
This PR introduces basic support for accessing generic Swift types from Java.
As this is the initial step, the functionality is currently limited.
Specifically, the following are not supported in this PR:
Implementation
The general strategy follows the direction discussed in this issue comment.
In this implementation, the Swift metatype is stored as a field within the Java wrapper class.
When a function is called, this metatype is passed as an argument to the native function.
Regarding the usage of the metatype, I have adopted a different approach than the one originally mentioned in the issue.
When a type is generic, the generator now produces an "opener protocol".
This is a technique to handle the
Selftype correctly from a metatype. By conforming the original type to this opener protocol, we can indirectly extract and utilize the type parameters within Swift.Why not use the original pattern?
This is because the original pattern cannot handle certain cases successfully. It cannot expand when there are multiple type parameters and constraints.Others
The following functions cause branching in code generators based on whether they are generic or not:
long $typeMetadataAddress()Runnable $createDestroyFunction()Discriminator getDiscriminator()Similar to the refactoring in #567 for
toString, I plan to register these asSynthesizedAPIto remove this redundancy. However, to avoid over-complicating this PR, I have deferred that refactoring to a future update.