Skip to content

"java.lang.VerifyError: Bad invoke special instruction" when running a partially applied function implemented in a superclass #8803

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
scabug opened this issue Aug 19, 2014 · 5 comments
Assignees
Milestone

Comments

@scabug
Copy link

scabug commented Aug 19, 2014

trait TraitOne {
  def m(s: String, i: Int): Int
}

class ClassOne extends TraitOne {
  override def m(s: String, i: Int): Int = i
}

class ClassTwo extends ClassOne {
  val f: (Int) => Int = super[ClassOne].m("two", _)

  def m2(i: Int): Int = f(i)
}

object Demo extends App {
  val v = (new ClassTwo).m2(2)
}

This code compiles without errors, but fails at runtime with this message:

Exception in thread "main" java.lang.VerifyError: Bad invokespecial instruction: current class isn't assignable to reference class.
Exception Details:
  Location:
    ClassTwo$$anonfun$1.apply$mcII$sp(I)I @4: invokespecial
  Reason:
    Error exists in the bytecode
  Bytecode:
    0000000: 2a12 1d1b b700 23ac   
@scabug
Copy link
Author

scabug commented Aug 19, 2014

Imported From: https://issues.scala-lang.org/browse/SI-8803?orig=1
Reporter: Egidijus Jankauskas (egis)
Affected Versions: 2.10.4, 2.11.1, 2.11.2

@scabug
Copy link
Author

scabug commented Aug 19, 2014

@gourlaysama said:
Nice, that method is very wrong indeed:

public int apply$mcII$sp(int);
    descriptor: (I)I
    flags: ACC_PUBLIC
    Code:
      stack=3, locals=2, args_size=2
         0: aload_0       
         1: ldc           #25                 // String two
         3: iload_1       
         4: invokespecial #31                 // Method ClassOne.m:(Ljava/lang/String;I)I
         7: ireturn       
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       8     0  this   LClassTwo$$anonfun$1;
            0       8     1   x$1   I

this obviously isn't a ClassOne in that anonymous function. It should use the outer reference to the ClassTwo instance. And the outer ref is used when calling super.m or just m, but not super[ClassOne].m...

@scabug
Copy link
Author

scabug commented Aug 19, 2014

@lrytz said:
will take a look

@scabug
Copy link
Author

scabug commented Aug 19, 2014

@lrytz said:
The issue is specific to closures. Workaround: manually create an accessor.

class ClassTwo extends ClassOne {
  def fBody(s: String, i: Int) = super[ClassOne].m(s, i)
  val f: (Int) => Int = fBody("two", _)
}

Or use -Ydelambdafy:method, which happens to do just that.

@scabug
Copy link
Author

scabug commented Aug 20, 2014

@lrytz said:
Actually, it's not specific to closures.

scala/scala#3935

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants