Skip to content

jextract/jni: Specialization and constrained extension support#664

Merged
ktoso merged 1 commit intoswiftlang:mainfrom
ktoso:wip-specialize
Apr 1, 2026
Merged

jextract/jni: Specialization and constrained extension support#664
ktoso merged 1 commit intoswiftlang:mainfrom
ktoso:wip-specialize

Conversation

@ktoso
Copy link
Copy Markdown
Collaborator

@ktoso ktoso commented Apr 1, 2026

This allows specializing types e.g. Box with a typealias FishBox = Box<Fish> becomes its own type in Java and gets all methods from Box but also any methods where the extension Box where Element == Fish {}.

This gives Java access to previously unavailable APIs in a safe way. Though yes it makes the type different in Java - so one may have to convert to a Box<> sometimes etc. We may need more helper methods for those.

For now I want to enable getting to those otherwise unavailable methods via specialization.

Specialization is available via a typealias trigger, or via configuration which is nice if you don't control the sources you're trying to specialize.

This partially addresses typealias support as well #338

}
}

public typealias FishBox = Box<Fish>
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This triggers specialization for a new FishBox "type" on the java side 🐟

/// even if it would otherwise be excluded by `swiftFilterExclude` configuration.
@attached(peer)
public macro JavaExport() =
#externalMacro(module: "SwiftJavaMacros", type: "JavaExportMacro")
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did not end up using in this PR, but this is a way to exclude "everything" and then include a specific specialization

This allows specializing types e.g. Box<T> with a typealias `FishBox =
Box<Fish>` becomes its own type in Java and gets all methods from Box
but also any methods where the `extension Box where Element == Fish {}`.

This gives Java access to previously unavailable APIs in a safe way.
Though yes it makes the type different in Java - so one may have to
convert to a Box<> sometimes etc. We may need more helper methods for
those.

For now I want to enable getting to those otherwise unavailable methods
via specialization.

Specialization is available via a typealias trigger, or via
configuration which is nice if you don't control the sources you're
trying to specialize.
@ktoso ktoso merged commit c4a2934 into swiftlang:main Apr 1, 2026
61 checks passed
@ktoso ktoso deleted the wip-specialize branch April 1, 2026 07:35
| Dictionaries: `[String: Int]`, `[K:V]` | ❌ | ✅ |
| Generic type: `struct S<T>` | ❌ | ✅ |
| Functions or properties using generic type param: `struct S<T> { func f(_: T) {} }` | ❌ | ❌ |
| Generic type specialization and conditional extensions: `struct S<T>{} extension S where T == Value {}` | ✅ | ❌ |
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think these are swapped.

}

/// Translate a single element type for tuple results on the Java side.
private func translateTupleElementResult(
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I deleted this function in my previous #657 . It seems like it might have slipped back in during a merge?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ugh seems so, I had a few long running branches -- sorry, let me remove that

| Dictionaries: `[String: Int]`, `[K:V]` | ❌ | ✅ |
| Generic type: `struct S<T>` | ❌ | ✅ |
| Functions or properties using generic type param: `struct S<T> { func f(_: T) {} }` | ❌ | ❌ |
| Generic type specialization and conditional extensions: `struct S<T>{} extension S where T == Value {}` | ✅ | ❌ |
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Huh indeed, thank you.

I wonder if inverse order would be preferable tbh... seems most people use jni mode nowadays 🤔

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think FFM has a better design, but since I need Android support, I have to stick with the older approach🤣

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, that's the life we're stuck with on Android 😅

@ktoso
Copy link
Copy Markdown
Collaborator Author

ktoso commented Apr 1, 2026

Thanks for review @sidepelican , added cleanups to #666

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants