scala/bug

Scala 2.10.7 and 2.11.12 regression: VerifyError when overriding a Java-defined default method

sjrd opened this issue · 4 comments

sjrd commented

Reproduction:

import java.{util => ju}

class DefaultMethodsTest {
  def canOverrideDefaultMethod(): Unit = {
    var counter = 0

    class SpecialIntComparator extends ju.Comparator[Int] {
      def compare(o1: Int, o2: Int): Int =
        o1.compareTo(o2)

      override def reversed(): ju.Comparator[Int] = {
        counter += 1
        super.reversed()
      }
    }

    val c = new SpecialIntComparator
    assert(c.compare(5, 7) < 0)
    assert(0 == counter)

    val reversed = c.reversed()
    assert(1 == counter)
    assert(reversed.compare(5, 7) > 0)
  }
}

object Test {
  def main(args: Array[String]) {
    new DefaultMethodsTest().canOverrideDefaultMethod()
  }
}

In all cases, I build on Java 8 via sbt 0.13.16 (empty build except for scalaVersion := "...").

Using any version of Scala since 2.10.2 and until 2.12.4, except 2.10.7 and 2.11.12, the above .scala source compiles and runs without error.

When using 2.10.7 or 2.11.12, running causes the following VerifyError:

[info] Running Test
[error] (run-main-4) java.lang.VerifyError: Illegal type at constant pool entry 51 in class DefaultMethodsTest$SpecialIntComparator$1
[error] Exception Details:
[error]   Location:
[error]     DefaultMethodsTest$SpecialIntComparator$1.reversed()Ljava/util/Comparator; @17: invokespecial
[error]   Reason:
[error]     Constant pool index 51 is invalid
[error]   Bytecode:
[error]     0x0000000: 2ab4 002c 2ab4 002c b400 3104 60b5 0031
[error]     0x0000010: 2ab7 0033 b0
java.lang.VerifyError: Illegal type at constant pool entry 51 in class DefaultMethodsTest$SpecialIntComparator$1
Exception Details:
  Location:
    DefaultMethodsTest$SpecialIntComparator$1.reversed()Ljava/util/Comparator; @17: invokespecial
  Reason:
    Constant pool index 51 is invalid
  Bytecode:
    0x0000000: 2ab4 002c 2ab4 002c b400 3104 60b5 0031
    0x0000010: 2ab7 0033 b0

        at DefaultMethodsTest.canOverrideDefaultMethod(Test.scala:17)
        at Test$.main(Test.scala:29)
        at Test.main(Test.scala)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:497)

This is a test case part of the Scala.js test suite. It is part of the cross-compiled tests that we run both on JS and on the JVM. The community build does not include the JVM version (testSuiteJVM/test) but only the JS version (testSuite/test) which explains why it was not discovered there.

Can you report whether this problem persists if you use -target:jvm-1.8?

sjrd commented

You're right. -target:jvm-1.8 solves the issue both in 2.10.7 and 2.11.12.

Feel free to close this issue if that's expected.

I added a compiler error in the pre-2.12 compiler version when attempting to call an interface method without -jvm:1.8. Maybe that missed out on detecting super calls? I'll leave this ticket open until I figure that out.

Closing since it seems increasingly unlikely there will ever be a 2.11.13.