Skip to content

Wrong debug line number in the body of a CaseDef #15535

Closed
@adpi2

Description

@adpi2

Compiler version

3.1.3 and also 2.13.8

Minimized code

package example

object Main {
  def m(x: Int): Unit = {
    x match {
      case y =>
        println(y) // breakpoint here, line 7
        println(y)
    }
  }
  
  def main(args: Array[String]): Unit = {
    m(1)
  }
}

Output

The program pauses on line 7 but the local variable y is not defined.

image

Expectation

The local variable y should be defined

Details

An incorrect line number table

The result of decompiling m from its class file is:

  public void m(int);
    Code:
       0: iload_1
       1: istore_2
       2: iload_2
       3: istore_3
       4: getstatic     #33                 // Field scala/Predef$.MODULE$:Lscala/Predef$;
       7: iload_3
       8: invokestatic  #39                 // Method scala/runtime/BoxesRunTime.boxToInteger:(I)Ljava/lang/Integer;
      11: invokevirtual #43                 // Method scala/Predef$.println:(Ljava/lang/Object;)V
      14: getstatic     #33                 // Field scala/Predef$.MODULE$:Lscala/Predef$;
      17: iload_3
      18: invokestatic  #39                 // Method scala/runtime/BoxesRunTime.boxToInteger:(I)Ljava/lang/Integer;
      21: invokevirtual #43                 // Method scala/Predef$.println:(Ljava/lang/Object;)V
      24: goto          27
      27: return
    LineNumberTable:
      line 4: 0
      line 5: 0
      line 7: 2
      line 8: 14
    LocalVariableTable:
      Start  Length  Slot  Name   Signature
          4      23     3     y   I
          0      28     0  this   Lexample/Main$;
          0      28     1     x   I

Here the line number 7 is associated with byte code 2 which is too early, the local variable y on slot 3 has not yet been initialized.

I believe the line number 7 should be associated with the byte code 4.

A correct line number table

If the body of the case contains only one instruction, then the debug line number table is correct:

def m(x: Int): Unit = {
  x match {
    case y =>
      println(y)
  }
}
  public void m(int);
    Code:
       0: iload_1
       1: istore_2
       2: iload_2
       3: istore_3
       4: getstatic     #33                 // Field scala/Predef$.MODULE$:Lscala/Predef$;
       7: iload_3
       8: invokestatic  #39                 // Method scala/runtime/BoxesRunTime.boxToInteger:(I)Ljava/lang/Integer;
      11: invokevirtual #43                 // Method scala/Predef$.println:(Ljava/lang/Object;)V
      14: goto          17
      17: return
    LineNumberTable:
      line 4: 0
      line 5: 0
      line 6: 2
      line 7: 4
    LocalVariableTable:
      Start  Length  Slot  Name   Signature
          4      13     3     y   I
          0      18     0  this   Lexample/Main$;
          0      18     1     x   I

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions