Skip to content

Stop dynamically changing Int.JNIType based on the target#16

Open
sidepelican wants to merge 1 commit intoswiftlang:mainfrom
sidepelican:fixed_witdh_integer
Open

Stop dynamically changing Int.JNIType based on the target#16
sidepelican wants to merge 1 commit intoswiftlang:mainfrom
sidepelican:fixed_witdh_integer

Conversation

@sidepelican
Copy link
Copy Markdown
Contributor

Currently, Int.JNIType changes its definition based on the build target's bit width:

#if _pointerBitWidth(_32)
extension Int: JavaValue {
  public typealias JNIType = jint
  ...
#elseif _pointerBitWidth(_64)
extension Int: JavaValue {
  public typealias JNIType = jlong
  ...

While this might seem like the correct way to match Swift's Int size, I believe this approach is actually incorrect.
JNIType is simply an interface for JNI communication; it doesn't strictly require an exact bit-width match with the native type.

In swift-java, Int is effectively handled as Int64 in all JNI interactions.
This is because the generated Java source code does not change based on the target architecture, so we must use the wider integer type to ensure consistency.

Using a dynamic JNIType has been a frequent source of bugs during type conversion. Therefore, I propose that Int.JNIType should always be jlong.

@marcprux
Copy link
Copy Markdown
Contributor

marcprux commented Apr 1, 2026

I also feel like this is incorrect, but I wonder if a better solution might be to simply not have Int conform to JavaValue and make people use Int32 or Int64 for their mappings.

Would anything break today if we removed the Int conformance? Do @madsodgaard or @colemancda use Int in any of their bridging?

@colemancda
Copy link
Copy Markdown
Contributor

My project AndroidKit uses Int for a lot of generated code.

@marcprux
Copy link
Copy Markdown
Contributor

marcprux commented Apr 1, 2026

My project AndroidKit uses Int for a lot of generated code.

Can you point to some examples? In https://github.com/PureSwift/Android I mostly see explicit Int32 and Int64 bridging.

@ktoso
Copy link
Copy Markdown
Collaborator

ktoso commented Apr 1, 2026

Not supporting Int is not an option, idiomatic Swift libraries should be handled properly by swift-java tools.

On the contrary, does widening to long ever actually break anything? We have to bounds check the value if passing to a jint but other than that I don't see issues with this?

@sidepelican
Copy link
Copy Markdown
Contributor Author

I think removing Int conformance in jni-core is certainly an option.
In that case, swift-java would need to extend Int independently, but I don't think that would be a major issue.

That said, I’m also curious about what specific scenarios would make it fatal for Int to be jlong on 32-bit systems.

@marcprux
Copy link
Copy Markdown
Contributor

marcprux commented Apr 2, 2026

That said, I’m also curious about what specific scenarios would make it fatal for Int to be jlong on 32-bit systems.

If I were to (unwisely) bridge System.nanoTime() as a Swift Int, then it would work fine on 64-bit but it would crash on 32-bit.

@sidepelican
Copy link
Copy Markdown
Contributor Author

If the return value of System.nanoTime() is incorrectly represented as Int, wouldn't it crash either way, whether we use jlong or jint?

In the case of jint, the method wouldn't be found due to the signature mismatch.
In the case of jlong, it would crash if an overflow occurs, but we can at least perform a check for that beforehand.

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.

4 participants