Open nikomatsakis opened 1 year ago
cc @fpoli -- does this cover the details, or are there further complications I'm ignoring?
One additional question: Should duchess generate runtime type checks before the JNI calls that make use of the imprecise type parameters?
Since the JVM only verifies bytecode for type safety, not the JNI calls, I suspect that the imprecision of duchess in the type parameters might lead to cases where the JVM receives the wrong type and thus dereferences some bad pointer at runtime. I'll see if I can build an example.
I've been giving this some thought. My current proposal is that we add some special types:
java::Wildcard
, where for all T
, T: Upcast<Wildcard>
and Wildcard: Upcast<Object>
java::Extends<T>
, where for all U
, U: Upcast<T> => U: Upcast<Extends<T>>
and Extends<T>: Upcast<U>
java::Super<T>
where ... (as above)and an additional trait java::SpecificClass
, which is implemented by all Java objects, but not the three types above. We would add this to any type parameter that appears more than once in a signature.
Then we can translate signatures to use those types and I think we actually get the correct typing rules.
This doesn't account for ? extends A & B
, we'd have to do something like java::Extends<(A, B)>
, but we can do that (up to some fixed arity).
It's probably also possible to do ?extends Foo super Bar
? Also possible to account for.
Our current handling for
?
and erasure is not optimal -- see #41 and #55 for an example of the problems we encounter. This issue is for brainstorming a better solution.Problem 1: returning
?
The
getClass
method returnsClass<?>
. We can't model this with 100% fidelity for Rust users. Mapping it toClass<Object>
is somewhat reasonable, since the role of the type parameter in this case is primarily covariant -- it's not necessarily suitable as a general purpose solution, consider methods likeIt also allows you to invoke Java methods like this one, which ideally wouldn't be allowed...
...but this may not be achievable. I think I'm willing to live with that,.
In both cases, the worst that happens is we generate class cast exceptions in Java, not UB.
Problem 2: returning
? extends T
or? super U
Worth pointing out that sometimes there can be bounds.
Problem 3: modeling erased Java types
Scala sometimes intentionally translates to erased Java types. These I think are largely equivalent to
?
, except that Java is more lenient and makes "angelic" type assumptions.