Skip to content

VerifyError: erased context function parameter before non-erased produces invalid bytecode #25725

@haskiindahouse

Description

@haskiindahouse

Compiler version

3.8.3 (also verified on 3.7.3 and 3.6.4)

Minimized code

import scala.language.experimental.erasedDefinitions

class Proof
erased given Proof = Proof()

def mixed: (erased Proof) ?=> Int ?=> String =
  s"value: ${summon[Int]}"

@main def test(): Unit =
  given Int = 99
  println(mixed)

Output (click arrow to expand)

Details
Exception in thread "main" java.lang.VerifyError: Bad local variable type
Exception Details:
  Location:
    bug003$package$.mixed(I)Ljava/lang/String; @0: iload_2
  Reason:
    Type top (current frame, locals[2]) is not assignable to integer
  Current Frame:
    bci: @0
    flags: { }
    locals: { 'bug003$package$', integer }
    stack: { }
  Bytecode:
    0000000: 1cba 002e 0000 b0

	at test.main(bug003.scala:10)

Expectation

Should print value: 99.

The method signature is mixed(I)String — one int parameter. But the bytecode uses iload_2 (slot 2) when only slots 0 (this) and 1 (Int) exist. The erased Proof parameter was removed from the signature but slot numbering in the body was not adjusted.

Key observation: order matters

// CRASHES: erased first, then non-erased
def mixed: (erased Proof) ?=> Int ?=> String = s"${summon[Int]}"

// WORKS: non-erased first, then erased (erased in last position)
def reversed: Int ?=> (erased Proof) ?=> String = s"${summon[Int]}"

All these also crash:

def varA: (erased P1) ?=> (erased P2) ?=> Int ?=> String = ...  // 2 erased before non-erased
def varB: (erased P1) ?=> Int ?=> (erased P2) ?=> String = ...  // erased, non-erased, erased
def varC: Int ?=> (erased P1) ?=> String ?=> String = ...       // non-erased, erased, non-erased

The bug triggers whenever an erased context function param appears BEFORE any subsequent non-erased param. Only erased in the very last position is safe.

Notes

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions