Skip to content

Commit d495ee0

Browse files
committed
Move the trait super call encoding logic to the back-end.
1 parent 90070e2 commit d495ee0

File tree

4 files changed

+58
-7
lines changed

4 files changed

+58
-7
lines changed

compiler/src/dotty/tools/backend/jvm/BCodeBodyBuilder.scala

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -780,6 +780,7 @@ trait BCodeBodyBuilder extends BCodeSkelBuilder {
780780
val invokeStyle =
781781
if (sym.isStaticMember) InvokeStyle.Static
782782
else if (sym.is(Private) || sym.isClassConstructor) InvokeStyle.Special
783+
else if (app.hasAttachment(BCodeHelpers.UseInvokeSpecial)) InvokeStyle.Special
783784
else InvokeStyle.Virtual
784785

785786
if (invokeStyle.hasInstance) genLoadQualifier(fun)
@@ -1165,9 +1166,16 @@ trait BCodeBodyBuilder extends BCodeSkelBuilder {
11651166
val isInterface = isEmittedInterface(receiverClass)
11661167
import InvokeStyle._
11671168
if (style == Super) {
1168-
// DOTTY: this differ from how super-calls in traits are handled in the scalac backend,
1169-
// this is intentional but could change in the future, see https://github.com/lampepfl/dotty/issues/5928
1170-
bc.invokespecial(receiverName, jname, mdescr, isInterface)
1169+
if (isInterface && !method.is(JavaDefined)) {
1170+
val args = new Array[BType](bmType.argumentTypes.length + 1)
1171+
val ownerBType = toTypeKind(method.owner.info)
1172+
bmType.argumentTypes.copyToArray(args, 1)
1173+
val staticDesc = MethodBType(ownerBType :: bmType.argumentTypes, bmType.returnType).descriptor
1174+
val staticName = traitSuperAccessorName(method)
1175+
bc.invokestatic(receiverName, staticName, staticDesc, isInterface)
1176+
} else {
1177+
bc.invokespecial(receiverName, jname, mdescr, isInterface)
1178+
}
11711179
} else {
11721180
val opc = style match {
11731181
case Static => Opcodes.INVOKESTATIC

compiler/src/dotty/tools/backend/jvm/BCodeHelpers.scala

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,12 @@ trait BCodeHelpers extends BCodeIdiomatic with BytecodeWriters {
8282
}
8383
}
8484

85+
final def traitSuperAccessorName(sym: Symbol): String = {
86+
val nameString = sym.javaSimpleName.toString
87+
if (sym.name == nme.TRAIT_CONSTRUCTOR) nameString
88+
else nameString + "$"
89+
}
90+
8591
// -----------------------------------------------------------------------------------------
8692
// finding the least upper bound in agreement with the bytecode verifier (given two internal names handed by ASM)
8793
// Background:
@@ -950,4 +956,10 @@ object BCodeHelpers {
950956
val Super = new InvokeStyle(3) // InvokeSpecial (super calls)
951957
}
952958

959+
/** An attachment on Apply nodes indicating that it should be compiled with
960+
* `invokespecial` instead of `invokevirtual`. This is used for static
961+
* forwarders.
962+
*/
963+
val UseInvokeSpecial = new dotc.util.Property.Key[Unit]
964+
953965
}

compiler/src/dotty/tools/backend/jvm/BCodeSkelBuilder.scala

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,9 @@ import dotty.tools.dotc.CompilationUnit
1414
import dotty.tools.dotc.core.Annotations.Annotation
1515
import dotty.tools.dotc.core.Decorators._
1616
import dotty.tools.dotc.core.Flags._
17-
import dotty.tools.dotc.core.StdNames.str
17+
import dotty.tools.dotc.core.StdNames.{nme, str}
1818
import dotty.tools.dotc.core.Symbols._
19-
import dotty.tools.dotc.core.Types.Type
19+
import dotty.tools.dotc.core.Types.{MethodType, Type}
2020
import dotty.tools.dotc.util.Spans._
2121
import dotty.tools.dotc.report
2222

@@ -496,7 +496,19 @@ trait BCodeSkelBuilder extends BCodeHelpers {
496496

497497
case ValDef(name, tpt, rhs) => () // fields are added in `genPlainClass()`, via `addClassFields()`
498498

499-
case dd: DefDef => genDefDef(dd)
499+
case dd: DefDef =>
500+
val sym = dd.symbol
501+
502+
def needsStaticImplMethod: Boolean =
503+
claszSymbol.isInterface
504+
&& !dd.rhs.isEmpty
505+
&& !sym.isPrivate
506+
&& !sym.isStaticMember
507+
508+
if needsStaticImplMethod then
509+
genStaticForwarderForDefDef(dd)
510+
511+
genDefDef(dd)
500512

501513
case tree: Template =>
502514
val body =
@@ -537,6 +549,25 @@ trait BCodeSkelBuilder extends BCodeHelpers {
537549

538550
} // end of method initJMethod
539551

552+
private def genStaticForwarderForDefDef(dd: DefDef): Unit =
553+
val forwarderDef = makeStaticForwarder(dd, traitSuperAccessorName(dd.symbol))
554+
genDefDef(forwarderDef)
555+
556+
private def makeStaticForwarder(dd: DefDef, name: String): DefDef =
557+
val origSym = dd.symbol.asTerm
558+
val info = origSym.info match
559+
case mt: MethodType =>
560+
MethodType(nme.SELF :: mt.paramNames, origSym.owner.typeRef :: mt.paramInfos, mt.resType)
561+
val sym = origSym.copy(
562+
name = name.toTermName,
563+
flags = Method | JavaStatic,
564+
info = info
565+
)
566+
tpd.DefDef(sym.asTerm, { paramss =>
567+
val params = paramss.head
568+
tpd.Apply(params.head.select(origSym), params.tail)
569+
.withAttachment(BCodeHelpers.UseInvokeSpecial, ())
570+
})
540571

541572
def genDefDef(dd: DefDef): Unit = {
542573
val rhs = dd.rhs

compiler/src/dotty/tools/dotc/Compiler.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ class Compiler {
110110
// Note: constructors changes decls in transformTemplate, no InfoTransformers should be added after it
111111
new FunctionalInterfaces, // Rewrites closures to implement @specialized types of Functions.
112112
new Instrumentation) :: // Count closure allocations under -Yinstrument-closures
113-
List(new LinkScala2Impls, // Redirect calls to trait methods defined by Scala 2.x, so that they now go to
113+
List(//new LinkScala2Impls, // Redirect calls to trait methods defined by Scala 2.x, so that they now go to
114114
new LambdaLift, // Lifts out nested functions to class scope, storing free variables in environments
115115
// Note: in this mini-phase block scopes are incorrect. No phases that rely on scopes should be here
116116
new ElimStaticThis, // Replace `this` references to static objects by global identifiers

0 commit comments

Comments
 (0)