Unboxing conversion of generic types with box as a bound

Kevin Bourrillion kevin.bourrillion at oracle.com
Mon Dec 15 23:00:59 UTC 2025


Hey Tagir, we were discussing this internally a couple months ago, and I felt there was a general consensus that this is indeed a spec bug. Javac's permissiveness seems totally reasonable here.

We either need to insert more WRCs before unbox conversions (like the one you found), or (a seemingly-simpler approach that I hope will work) just tweak the specification of unboxing conversion itself so it applies to any subtype of Integer-etc., instead of only the exact type. (Of course this also affects intersection types and capture types as well as the case in your example.)

We didn't jump on fixing it yet but it's slated to happen sooner or later as part of a series of type-conversion cleanups we're working on. Hopefully just getting this answer unblocks you for now?






Confidential- Oracle Internal

From: compiler-dev <compiler-dev-retn at openjdk.org> on behalf of Tagir Valeev <amaembo at gmail.com>
Date: Monday, December 15, 2025 at 9:21 AM
To: compiler-dev at openjdk.org <compiler-dev at openjdk.org>
Subject: Unboxing conversion of generic types with box as a bound

Hello!

I noticed that the following program is compilable without errors using OpenJDK 25 javac:

private static <X extends Integer> void add(X x) {
    System.out.println(+x);
}

void main() {
    add(10);
}

I wonder if it's correct. The JLS 15.15.3 says [1]:

The type of the operand expression of the unary + operator must be a type that is convertible (§5.1.8) to a primitive numeric type, or a compile-time error occurs.

The JLS 5.1.8, in turn, says [2]:

Unboxing conversion treats expressions of a reference type as expressions of a corresponding primitive type. Specifically, the following eight conversions are called the unboxing conversions:
...
From type Integer to type int
...
At run time, unboxing conversion proceeds as follows:
...
If r is a reference of type Integer, then unboxing conversion converts r into r.intValue()

In my case, the type of reference is X, rather than Integer. So my question, should I read 'type Integer' here as 'type Integer, or any generic type whose upper bound is type Integer'? In other words, should we assume that the X type declared as `X extends Integer` is convertible to a primitive numeric type? It looks like, here a widening reference conversion (5.1.5) happens before an unboxing conversion, but 15.15.3 does not say about widening reference conversion. I've also checked 5.6 "Numeric contexts", but it also does not mention that before unboxing conversion, a widening reference conversion might occur.

Could anybody please clarify whether the compiler is wrong or I read the specification incorrectly? Thank you in advance!

With best regards,
Tagir Valeev

[1] https://docs.oracle.com/javase/specs/jls/se25/html/jls-15.html#jls-15.15.3
[2] https://docs.oracle.com/javase/specs/jls/se25/html/jls-5.html#jls-5.1.8
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/compiler-dev/attachments/20251215/25887a7e/attachment-0001.htm>


More information about the compiler-dev mailing list