Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit b60a244

Browse files
committed
Emit trait method bodies in statics
And use this as the target of the default methods or statically resolved super or $init calls. The call-site change is predicated on `-Yuse-trait-statics` as a stepping stone for experimentation / bootstrapping. I have performed this transformation in the backend, rather than trying to reflect this in the view from Scala symbols + ASTs. Once we commit to this change, we can remove the `lateInterfaces` bookkeeping from the backend, as we no long will need to add ancestor interfaces as direct parents to allow use of invokespecial for super calls. ``` > ;scalac sandbox/test.scala ; scala Test [info] Running scala.tools.nsc.MainGenericRunner -usejavacp Test T C [success] Total time: 2 s, completed 04/05/2016 11:07:13 AM > eval "javap -classpath . -c -private C".!! [info] ans: String = Compiled from "test.scala" [info] public class C implements T { [info] public C(); [info] Code: [info] 0: aload_0 [info] 1: invokespecial #14 // Method java/lang/Object."<init>":()V [info] 4: aload_0 [info] 5: invokespecial #17 // Method T.$init$:()V [info] 8: getstatic #23 // Field scala/Predef$.MODULE$:Lscala/Predef$; [info] 11: ldc #24 // String C [info] 13: invokevirtual #28 // Method scala/Predef$.println:(Ljava/lang/Object;)V [info] 16: aload_0 [info] 17: invokespecial #32 // Method T.foo:()I [info] 20: pop [info] 21: return [info] } > ;scalac -Yuse-trait-statics sandbox/test.scala ; scala Test [info] Running scala.tools.nsc.MainGenericRunner -usejavacp Test T C [success] Total time: 2 s, completed 04/05/2016 11:07:39 AM > eval "javap -classpath . -c -private C".!! [info] ans: String = Compiled from "test.scala" [info] public class C implements T { [info] public C(); [info] Code: [info] 0: aload_0 [info] 1: invokespecial #14 // Method java/lang/Object."<init>":()V [info] 4: aload_0 [info] 5: invokestatic #18 // Method T.$init$:(LT;)V [info] 8: getstatic #24 // Field scala/Predef$.MODULE$:Lscala/Predef$; [info] 11: ldc #25 // String C [info] 13: invokevirtual #29 // Method scala/Predef$.println:(Ljava/lang/Object;)V [info] 16: aload_0 [info] 17: invokestatic #33 // Method T.foo:(LT;)I [info] 20: pop [info] 21: return [info] } > eval "javap -classpath . -c -private T".!! [info] ans: String = Compiled from "test.scala" [info] public interface T { [info] public static int foo(T); [info] Code: [info] 0: iconst_0 [info] 1: ireturn [info] [info] public int foo(); [info] Code: [info] 0: aload_0 [info] 1: invokestatic #15 // Method foo:(LT;)I [info] 4: ireturn [info] [info] public static void $init$(T); [info] Code: [info] 0: getstatic #24 // Field scala/Predef$.MODULE$:Lscala/Predef$; [info] 3: ldc #25 // String T [info] 5: invokevirtual #29 // Method scala/Predef$.println:(Ljava/lang/Object;)V [info] 8: return [info] [info] public void $init$(); [info] Code: [info] 0: aload_0 [info] 1: invokestatic #32 // Method $init$:(LT;)V [info] 4: return [info] } ```
1 parent d0f7944 commit b60a244

File tree

4 files changed

+20
-4
lines changed

4 files changed

+20
-4
lines changed

project/ScalaOptionParser.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ object ScalaOptionParser {
9090
"-Ypresentation-strict", "-Ypresentation-verbose", "-Yquasiquote-debug", "-Yrangepos", "-Yreify-copypaste", "-Yreify-debug", "-Yrepl-class-based",
9191
"-Yrepl-sync", "-Yshow-member-pos", "-Yshow-symkinds", "-Yshow-symowners", "-Yshow-syms", "-Yshow-trees", "-Yshow-trees-compact", "-Yshow-trees-stringified", "-Ytyper-debug",
9292
"-Ywarn-adapted-args", "-Ywarn-dead-code", "-Ywarn-inaccessible", "-Ywarn-infer-any", "-Ywarn-nullary-override", "-Ywarn-nullary-unit", "-Ywarn-numeric-widen", "-Ywarn-unused", "-Ywarn-unused-import", "-Ywarn-value-discard",
93-
"-deprecation", "-explaintypes", "-feature", "-help", "-no-specialization", "-nobootcp", "-nowarn", "-optimise", "-print", "-unchecked", "-uniqid", "-usejavacp", "-usemanifestcp", "-verbose", "-version")
93+
"-deprecation", "-explaintypes", "-feature", "-help", "-no-specialization", "-nobootcp", "-nowarn", "-optimise", "-print", "-unchecked", "-uniqid", "-usejavacp", "-usemanifestcp", "-verbose", "-version", "-Yuse-trait-statics")
9494
private def stringSettingNames = List("-Xgenerate-phase-graph", "-Xmain-class", "-Xpluginsdir", "-Xshow-class", "-Xshow-object", "-Xsource-reader", "-Ydump-classes", "-Ygen-asmp",
9595
"-Ypresentation-log", "-Ypresentation-replay", "-Yrepl-outdir", "-d", "-dependencyfile", "-encoding", "-Xscript")
9696
private def pathSettingNames = List("-bootclasspath", "-classpath", "-extdirs", "-javabootclasspath", "-javaextdirs", "-sourcepath", "-toolcp")

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

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1061,7 +1061,7 @@ abstract class BCodeBodyBuilder extends BCodeSkelBuilder {
10611061
val receiverName = internalName(receiverClass)
10621062

10631063
// super calls are only allowed to direct parents
1064-
if (style.isSuper && receiverClass.isTraitOrInterface && !cnode.interfaces.contains(receiverName)) {
1064+
if (!settings.YuseTraitStatics.value && style.isSuper && receiverClass.isTraitOrInterface && !cnode.interfaces.contains(receiverName)) {
10651065
thisBType.info.get.inlineInfo.lateInterfaces += receiverName
10661066
cnode.interfaces.add(receiverName)
10671067
}
@@ -1082,7 +1082,11 @@ abstract class BCodeBodyBuilder extends BCodeSkelBuilder {
10821082
case Virtual =>
10831083
if (needsInterfaceCall(receiverClass)) bc.invokeinterface(receiverName, jname, mdescr, pos)
10841084
else bc.invokevirtual (receiverName, jname, mdescr, pos)
1085-
case Super => bc.invokespecial (receiverName, jname, mdescr, pos)
1085+
case Super =>
1086+
if (receiverClass.isTraitOrInterface && settings.YuseTraitStatics.value) {
1087+
val staticDesc = MethodBType(typeToBType(method.owner.info) :: method.info.paramTypes.map(typeToBType), typeToBType(method.info.resultType)).descriptor
1088+
bc.invokestatic(receiverName, jname, staticDesc, pos)
1089+
} else bc.invokespecial (receiverName, jname, mdescr, pos)
10861090
}
10871091

10881092
bmType.returnType

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

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -489,7 +489,18 @@ abstract class BCodeSkelBuilder extends BCodeHelpers {
489489

490490
case ValDef(mods, name, tpt, rhs) => () // fields are added in `genPlainClass()`, via `addClassFields()`
491491

492-
case dd : DefDef => genDefDef(dd)
492+
case dd : DefDef =>
493+
if (dd.symbol.owner.isTrait && dd.rhs != EmptyTree && !dd.symbol.isPrivate && !dd.symbol.hasFlag(Flags.STATIC)) {
494+
// Split concrete methods in traits (including mixin constructors) into a static method
495+
// with an explicit this parameter, and a non-static forwarder method.
496+
val staticDefDef = global.gen.mkStatic(dd, _.cloneSymbol)
497+
val forwarderDefDef = {
498+
val forwarderBody = Apply(global.gen.mkAttributedRef(staticDefDef.symbol), This(dd.symbol.owner).setType(dd.symbol.owner.info) :: dd.vparamss.head.map(p => global.gen.mkAttributedIdent(p.symbol))).setType(dd.symbol.info.resultType)
499+
deriveDefDef(dd)(_ => global.atPos(dd.pos)(forwarderBody))
500+
}
501+
genDefDef(staticDefDef)
502+
genDefDef(forwarderDefDef)
503+
} else genDefDef(dd)
493504

494505
case Template(_, _, body) => body foreach gen
495506

src/compiler/scala/tools/nsc/settings/ScalaSettings.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,7 @@ trait ScalaSettings extends AbsScalaSettings
201201
val etaExpandKeepsStar = BooleanSetting ("-Yeta-expand-keeps-star", "Eta-expand varargs methods to T* rather than Seq[T]. This is a temporary option to ease transition.").withDeprecationMessage(removalIn212)
202202
val inferByName = BooleanSetting ("-Yinfer-by-name", "Allow inference of by-name types. This is a temporary option to ease transition. See SI-7899.").withDeprecationMessage(removalIn212)
203203
val YdisableFlatCpCaching = BooleanSetting ("-YdisableFlatCpCaching", "Do not cache flat classpath representation of classpath elements from jars across compiler instances.")
204+
val YuseTraitStatics = BooleanSetting ("-Yuse-trait-statics", "Emit super calls to trait methods with invokestatic")
204205

205206
val exposeEmptyPackage = BooleanSetting ("-Yexpose-empty-package", "Internal only: expose the empty package.").internalOnly()
206207
val Ydelambdafy = ChoiceSetting ("-Ydelambdafy", "strategy", "Strategy used for translating lambdas into JVM code.", List("inline", "method"), "method")

0 commit comments

Comments
 (0)