Skip to content

Assignment as the final statement in a block emits an additional debug line/breakpoint #18320

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
vasilmkd opened this issue Aug 1, 2023 · 1 comment · Fixed by #18717
Closed

Comments

@vasilmkd
Copy link
Contributor

vasilmkd commented Aug 1, 2023

This ticket is the Scala 3 equivalent of scala/bug#12835.

Compiler version

Scala 3.3.0 (and also in Scala 2.12.18 and Scala 2.13.11)

Minimized code

@main
def main(): Unit = {
  val x = 123
}

Output

Compiled from "main.scala"
public final class main$package$ implements java.io.Serializable {
  public static final main$package$ MODULE$;

  private main$package$();
    Code:
       0: aload_0
       1: invokespecial #13                 // Method java/lang/Object."<init>":()V
       4: return
    LineNumberTable:
      line 1: 0
    LocalVariableTable:
      Start  Length  Slot  Name   Signature
          0       5     0  this   Lmain$package$;

  public static {};
    Code:
       0: new           #2                  // class main$package$
       3: dup
       4: invokespecial #16                 // Method "<init>":()V
       7: putstatic     #18                 // Field MODULE$:Lmain$package$;
      10: return
    LineNumberTable:
      line 1: 0

  private java.lang.Object writeReplace();
    Code:
       0: new           #22                 // class scala/runtime/ModuleSerializationProxy
       3: dup
       4: ldc           #2                  // class main$package$
       6: invokespecial #25                 // Method scala/runtime/ModuleSerializationProxy."<init>":(Ljava/lang/Class;)V
       9: areturn
    LineNumberTable:
      line 1: 0
    LocalVariableTable:
      Start  Length  Slot  Name   Signature
          0      10     0  this   Lmain$package$;

  public void main();
    Code:
       0: bipush        123
       2: istore_1
       3: return
    LineNumberTable:
      line 2: 0                <------------ this line is also possibly not necessary (not visible in the next bytecode dump below)
      line 3: 0
      line 4: 3                 <----------- this line is not necessary, line 4 is a closing bracket
    LocalVariableTable:
      Start  Length  Slot  Name   Signature
          3       1     1     x   I
          0       4     0  this   Lmain$package$;
}

Here's how this line manifests in the debugger. The behavior is the same in Metals.

Screen.Recording.2023-08-01.at.12.12.47.mov

Expectation

The debug information line 4 is not generated. For comparison, if we omit the curly braces and use the braceless syntax:

@main
def main(): Unit =
  val x = 123

the same debug line is not generated.

Compiled from "main.scala"
public final class main$package$ implements java.io.Serializable {
  public static final main$package$ MODULE$;

  private main$package$();
    Code:
       0: aload_0
       1: invokespecial #13                 // Method java/lang/Object."<init>":()V
       4: return
    LineNumberTable:
      line 1: 0
    LocalVariableTable:
      Start  Length  Slot  Name   Signature
          0       5     0  this   Lmain$package$;

  public static {};
    Code:
       0: new           #2                  // class main$package$
       3: dup
       4: invokespecial #16                 // Method "<init>":()V
       7: putstatic     #18                 // Field MODULE$:Lmain$package$;
      10: return
    LineNumberTable:
      line 1: 0

  private java.lang.Object writeReplace();
    Code:
       0: new           #22                 // class scala/runtime/ModuleSerializationProxy
       3: dup
       4: ldc           #2                  // class main$package$
       6: invokespecial #25                 // Method scala/runtime/ModuleSerializationProxy."<init>":(Ljava/lang/Class;)V
       9: areturn
    LineNumberTable:
      line 1: 0
    LocalVariableTable:
      Start  Length  Slot  Name   Signature
          0      10     0  this   Lmain$package$;

  public void main();
    Code:
       0: bipush        123
       2: istore_1
       3: return
    LineNumberTable:
      line 3: 0                             <--------------- only 1 debug line, both the line above and below were not generated
    LocalVariableTable:
      Start  Length  Slot  Name   Signature
          3       1     1     x   I
          0       4     0  this   Lmain$package$;
}
@vasilmkd vasilmkd added itype:bug stat:needs triage Every issue needs to have an "area" and "itype" label labels Aug 1, 2023
@dwijnand dwijnand added area:backend stat:needs triage Every issue needs to have an "area" and "itype" label and removed stat:needs triage Every issue needs to have an "area" and "itype" label labels Aug 1, 2023
@som-snytt
Copy link
Contributor

Relatedly #17425

sjrd added a commit that referenced this issue Oct 18, 2023
Synthetic `()` values are added to blocks without an expression. Don't
emit a line number for them.

Implemented by checking the `SyntheticUnit` attachment. This seems
simpler than trying to control the position assigned to synthetic unit
trees, as they are created in many places.

Fixes #18320. Forward port of
scala/scala#10577
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants