twitter / rsc

Experimental Scala compiler focused on compilation speed
Apache License 2.0
1.24k stars 54 forks source link

Unnecessary $init$ call when implementing trait with abstract method with default parameter #454

Closed wiwa closed 5 years ago

wiwa commented 5 years ago

C.scala:

trait C {
    def foo(x: Int = 0): Int
}

The resulting scalasig has an extraneous $init$:

  symbols {
    tag: VALsym
    id: <empty>.#C#$init$().
    flags: METHOD
    info {
      tag: METHODtpe
      ret {
        tag: TYPEREFtpe
        pre {
          tag: THIStpe
          sym: scala.#
        }
        sym: scala.#Unit#
      }
    }
  }

This results in incorrect bytecode when using C's outline to compile:

D.scala:

class D extends C {
    def foo(x: Int = 0): Int = 0
}

Bytecode diff:

--- a/D.class.asm
+++ b/D.class.asm
@@ -7,6 +7,8 @@
   public <init>()V
     ALOAD 0
     INVOKESPECIAL java/lang/Object.<init> ()V
+    ALOAD 0
+    INVOKESTATIC C.$init$ (LC;)V
     RETURN
     MAXSTACK = 1
     MAXLOCALS = 1

This propagates to more levels in the chain: C.scala

trait C {
    def foo(x: Int = 0): Int
}
object C {
    trait E extends C {
        def foo(x: Int = 0): Int
    }
}

D.scala

class D extends C.E {
    def foo(x: Int = 0): Int = 0
}

Bytecode diff:

--- a/D.class.asm
+++ b/D.class.asm
@@ -9,6 +9,10 @@
   public <init>()V
     ALOAD 0
     INVOKESPECIAL java/lang/Object.<init> ()V
+    ALOAD 0
+    INVOKESTATIC C.$init$ (LC;)V
+    ALOAD 0
+    INVOKESTATIC C$E.$init$ (LC$E;)V
     RETURN
     MAXSTACK = 1
     MAXLOCALS = 1