Super accessors
Scalac has an obscure feature that synthesizes methods, called super accessors, to bridge certain super calls, e.g.
trait T1 {
def x: Int = ???
}
trait T2 extends T1 {
def y: Int = super.x
}
13:31 ~/Projects/2126/sandbox (HEAD)$ s -Xprint:refchecks
[[syntax trees at end of refchecks]] // Test.scala
package <empty> {
abstract trait T1 extends scala.AnyRef {
def /*T1*/$init$(): Unit = {
()
};
def x: Int = scala.Predef.???
};
abstract trait T2 extends AnyRef with T1 {
<superaccessor> <artifact> private def super$x: Int;
def /*T2*/$init$(): Unit = {
()
};
def y: Int = T2.this.super$x
}
}
At the moment, mjar can't generate super accessors because they aren't present in SemanticDB and can't be inferred from SemanticDB contents alone. In the future, we may be able to solve this problem via https://github.com/scalameta/scalameta/issues/1648.
As mentioned in https://github.com/scalameta/scalameta/issues/1648, super accessors not only involve super$ methods, but sometimes they also give rise to protected$ methods. I don't fully understand why these methods are created, but figured I'd make a note here anyway.
trait T1 {
def x: Int = ???
}
trait T2 extends T1 {
def y: Int = super.x
}
class C extends T2
--- expected
+++ actual
diff --git a/C.class.asm b/C.class.asm
index e42d81e..5ab4b5f 100644
--- a/C.class.asm
+++ b/C.class.asm
@@ -15,14 +15,6 @@
MAXSTACK = 1
MAXLOCALS = 1
- // access flags 0x1001
- public synthetic T2$$super$x()I
- ALOAD 0
- INVOKESTATIC T1$class.x (LT1;)I
- IRETURN
- MAXSTACK = 1
- MAXLOCALS = 1
-
// access flags 0x1
public x()I
ALOAD 0
I've scratched the immediate itch in https://github.com/twitter/rsc/pull/326 by implementing a workaround to nudge Rsc into generating super accessors. This workaround requires users to modify their code, so it doesn't count as a proper fix, but at least now we don't have to fix this ticket right away (which is pretty tricky due to the reasons outlined in the PR).
For reference, the pretty-printed scalasigs which would be required:
symbols {
tag: VALsym
id: <empty>.#T2#super$x().
flags: PRIVATE | METHOD | SUPERACCESSOR | ARTIFACT
info {
tag: POLYtpe
tpe {
tag: TYPEREFtpe
pre {
tag: THIStpe
sym: scala.#
}
sym: scala.#Int#
}
}
alias: <empty>.#T1#x.
}