RFR: 8295020: javac emits incorrect code for for-each on an intersection type.

Srikanth Adayapalam sadayapalam at openjdk.org
Fri Oct 14 04:24:54 UTC 2022


On Fri, 14 Oct 2022 04:16:33 GMT, Srikanth Adayapalam <sadayapalam at openjdk.org> wrote:

> Eliminate needless casts and ensure invoked method is looked up against the appropriate receiver type

Notes for the reviewer:

The loop from the test case viz:


for (Object s : (MyIterable & Serializable) null) {}


gets transformed by Lower into:


for (Iterator i$ = ((Iterable)(Main$MyIterable & Serializable)null).iterator(); i$.hasNext(); ) {
    Object s = (Object)i$.next();
    {
    }
}


This transformation is problematic in a couple of ways:

    The cast of the expression (Main$MyIterable & Serializable)null into (Iterable) is not
    required at all. After erasure the type of the intersection cast node is actually
    Main$MyIterable which is already an Iterable. As a matter of Gen#visitTypeCast correctly
    deduces this to be a redundant cast and does not emit a checkcast in the class file.

    The iterator() method to be invoked is looked up against the JCEnhancedForLoop#expr.type
    i.e from Main$MyIterable while the type of the receiver expression for the iterator()
    method invocation is the casted type of (Iterable)(Main$MyIterable & Serializable)null).
    As a result, the method
    com.sun.tools.javac.jvm.Gen#binaryQualifier((Symbol sym, Type site)
    attempts to coalesce the method iterator() (sym) as owned by Iterator (site) by calling
    com.sun.tools.javac.code.Symbol.MethodSymbol#clone which simply changes ownership of
    the method symbol iterator() without accommodating for descriptor difference that arises
    due to covariant return type.


The fix comes in two parts: (a) Ensuring that a cast is inserted only when absolutely necessary
and not just because JCEnhancedForLoop#expr.type happens to be an intersection type (b) Ensuring
that where a type cast is inserted, the iterator() method is looked up against the modified
receiver type.

(An open question is whether MethodSymbol#clone should be fixed to not just rewire ownership, but also
account for differences in descriptor - if deemed needed this can be followed up in a separate
ticket.)

-------------

PR: https://git.openjdk.org/jdk/pull/10710


More information about the compiler-dev mailing list