From 2b307b4551ea3cb5827ee6db2e0c08f5852b4770 Mon Sep 17 00:00:00 2001 From: Dmitry Petrashko Date: Wed, 15 Apr 2015 21:11:52 +0200 Subject: [PATCH 1/6] Make dotty Idents transparent for common interface Scalac in some location(assigns for example) assumes that tree is a Select. In dotty it could also be an Ident. Simulate this. Fixes #477 --- .../tools/backend/jvm/DottyBackendInterface.scala | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/dotty/tools/backend/jvm/DottyBackendInterface.scala b/src/dotty/tools/backend/jvm/DottyBackendInterface.scala index e9c8dbc80362..bdba2935ec3b 100644 --- a/src/dotty/tools/backend/jvm/DottyBackendInterface.scala +++ b/src/dotty/tools/backend/jvm/DottyBackendInterface.scala @@ -61,7 +61,7 @@ class DottyBackendInterface()(implicit ctx: Context) extends BackendInterface{ type Alternative = tpd.Alternative type DefDef = tpd.DefDef type Template = tpd.Template - type Select = tpd.Select + type Select = tpd.Tree // Actually tpd.Select || tpd.Ident type Bind = tpd.Bind type New = tpd.New type Super = tpd.Super @@ -857,8 +857,19 @@ class DottyBackendInterface()(implicit ctx: Context) extends BackendInterface{ } object Select extends SelectDeconstructor { - def _1: Tree = field.qualifier + + override def isEmpty: Boolean = field match { + case t: tpd.Select => false + case t: tpd.Ident => desugarIdent(t).isEmpty + case _ => true + } + + def _1: Tree = field match { + case t: tpd.Select => t.qualifier + case t: tpd.Ident => desugarIdent(t).get + } def _2: Name = field.name + } object Apply extends ApplyDeconstructor { From 62ac97d16a9231b71de84a50b3c0d32f554b34e4 Mon Sep 17 00:00:00 2001 From: Dmitry Petrashko Date: Wed, 15 Apr 2015 21:15:05 +0200 Subject: [PATCH 2/6] Refactor BackendInterface.Select: desuggar only once. --- .../backend/jvm/DottyBackendInterface.scala | 30 ++++++++++++------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/src/dotty/tools/backend/jvm/DottyBackendInterface.scala b/src/dotty/tools/backend/jvm/DottyBackendInterface.scala index bdba2935ec3b..a1137896b73f 100644 --- a/src/dotty/tools/backend/jvm/DottyBackendInterface.scala +++ b/src/dotty/tools/backend/jvm/DottyBackendInterface.scala @@ -858,18 +858,28 @@ class DottyBackendInterface()(implicit ctx: Context) extends BackendInterface{ object Select extends SelectDeconstructor { - override def isEmpty: Boolean = field match { - case t: tpd.Select => false - case t: tpd.Ident => desugarIdent(t).isEmpty - case _ => true - } + var desugared: tpd.Select = null + + override def isEmpty: Boolean = + desugared eq null + + def _1: Tree = desugared.qualifier - def _1: Tree = field match { - case t: tpd.Select => t.qualifier - case t: tpd.Ident => desugarIdent(t).get + def _2: Name = desugared.name + + override def unapply(s: Select): this.type = { + s match { + case t: Select => desugared = t + case t: Ident => + desugarIdent(t) match { + case Some(t) => desugared = t + case None => desugared = null + } + case _ => desugared = null + } + + this } - def _2: Name = field.name - } object Apply extends ApplyDeconstructor { From 7a347a0c9b9e6c1030eff7d994bf3c502ee8d297 Mon Sep 17 00:00:00 2001 From: Dmitry Petrashko Date: Wed, 15 Apr 2015 21:18:18 +0200 Subject: [PATCH 3/6] Give more precise types in desugarIdent. It is known to return an actual Select. --- src/dotty/tools/backend/jvm/DottyBackendInterface.scala | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/dotty/tools/backend/jvm/DottyBackendInterface.scala b/src/dotty/tools/backend/jvm/DottyBackendInterface.scala index a1137896b73f..1df5646888d3 100644 --- a/src/dotty/tools/backend/jvm/DottyBackendInterface.scala +++ b/src/dotty/tools/backend/jvm/DottyBackendInterface.scala @@ -243,7 +243,7 @@ class DottyBackendInterface()(implicit ctx: Context) extends BackendInterface{ } case t: TypeApply if (t.fun.symbol == Predef_classOf) => av.visit(name, t.args.head.tpe.classSymbol.denot.info.toTypeKind(bcodeStore)(innerClasesStore).toASMType) - case t: Select => + case t: tpd.Select => if (t.symbol.denot.is(Flags.Enum)) { val edesc = innerClasesStore.typeDescriptor(t.tpe.asInstanceOf[bcodeStore.int.Type]) // the class descriptor of the enumeration class. val evalue = t.symbol.name.toString // value the actual enumeration value. @@ -416,7 +416,7 @@ class DottyBackendInterface()(implicit ctx: Context) extends BackendInterface{ def isQualifierSafeToElide(qual: Tree): Boolean = tpd.isIdempotentExpr(qual) - def desugarIdent(i: Ident): Option[Select] = { + def desugarIdent(i: Ident): Option[tpd.Select] = { i.tpe match { case TermRef(prefix: TermRef, name) => Some(tpd.ref(prefix).select(i.symbol)) @@ -869,7 +869,7 @@ class DottyBackendInterface()(implicit ctx: Context) extends BackendInterface{ override def unapply(s: Select): this.type = { s match { - case t: Select => desugared = t + case t: tpd.Select => desugared = t case t: Ident => desugarIdent(t) match { case Some(t) => desugared = t From 58a6c76019bde728dcfe43bd6a7c682cc33d71ee Mon Sep 17 00:00:00 2001 From: Dmitry Petrashko Date: Fri, 10 Apr 2015 01:23:33 +0200 Subject: [PATCH 4/6] Force loading LambdaMetaFactory. Common interface with scalac tries not to load it it wasn't loaded already. We need it. --- src/dotty/tools/backend/jvm/DottyBackendInterface.scala | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/dotty/tools/backend/jvm/DottyBackendInterface.scala b/src/dotty/tools/backend/jvm/DottyBackendInterface.scala index 1df5646888d3..afe9b6f77508 100644 --- a/src/dotty/tools/backend/jvm/DottyBackendInterface.scala +++ b/src/dotty/tools/backend/jvm/DottyBackendInterface.scala @@ -103,6 +103,10 @@ class DottyBackendInterface()(implicit ctx: Context) extends BackendInterface{ val BoxesRunTimeModule = ctx.requiredModule("scala.runtime.BoxesRunTime") val BoxesRunTimeClass = toDenot(BoxesRunTimeModule).moduleClass.asClass + // require LambdaMetafactory: scalac uses getClassIfDefined, but we need those always. + override lazy val LambdaMetaFactory = ctx.requiredClass("java.lang.invoke.LambdaMetafactory") + override lazy val MethodHandle = ctx.requiredClass("java.lang.invoke.MethodHandle") + val nme_valueOf: Name = StdNames.nme.valueOf val nme_apply = StdNames.nme.apply val NothingClass: Symbol = defn.NothingClass From 235df32bffcfbc58f83f113bec81072f8de50ee9 Mon Sep 17 00:00:00 2001 From: Dmitry Petrashko Date: Thu, 16 Apr 2015 15:41:13 +0200 Subject: [PATCH 5/6] Update version of scalac-compiler fork. This update allows to have non-static lambdas. It doesn't mean that we should emit such, as they are potential memory leak. See #480 Fixes #470 --- bin/dotc | 10 +++++----- project/Build.scala | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/bin/dotc b/bin/dotc index 3d6e15a54b64..2ffe20f0781b 100755 --- a/bin/dotc +++ b/bin/dotc @@ -6,7 +6,7 @@ # Configuration SCALA_VERSION=2.11.5 SCALA_BINARY_VERSION=2.11 -SCALA_COMPILER_VERSION=2.11.5-20150402-193021-0c75410da3 +SCALA_COMPILER_VERSION=2.11.5-20150416-144435-09c4a520e1 DOTTY_VERSION=0.1 JLINE_VERSION=2.12 bootcp=true @@ -57,13 +57,13 @@ checkjar $TEST_JAR test:package # Autodetecting the scala-library location, in case it wasn't provided by an environment variable if [ "$SCALA_LIBRARY_JAR" == "" ] -then +then SCALA_LIBRARY_JAR=$HOME/.ivy2/cache/org.scala-lang/scala-library/jars/scala-library-$SCALA_VERSION.jar # this is location where sbt stores it in ivy cache fi # save as for scala-library now for scala-reflect if [ "$SCALA_REFLECT_JAR" == "" ] -then +then SCALA_REFLECT_JAR=$HOME/.ivy2/cache/org.scala-lang/scala-reflect/jars/scala-reflect-$SCALA_VERSION.jar fi if [ "$SCALA_COMPILER_JAR" == "" ] @@ -72,13 +72,13 @@ then fi if [ "$JLINE_JAR" == "" ] -then +then JLINE_JAR=$HOME/.ivy2//cache/jline/jline/jars/jline-$JLINE_VERSION.jar fi if [ ! -f "$SCALA_LIBRARY_JAR" -o ! -f "$SCALA_REFLECT_JAR" -o ! -f "$SCALA_COMPILER_JAR" -o ! -f "$JLINE_JAR" ] then - echo To use this script please set + echo To use this script please set echo SCALA_LIBRARY_JAR to point to scala-library-$SCALA_VERSION.jar "(currently $SCALA_LIBRARY_JAR)" echo SCALA_REFLECT_JAR to point to scala-reflect-$SCALA_VERSION.jar "(currently $SCALA_REFLECT_JAR)" echo SCALA_COMPILER_JAR to point to scala-compiler-$SCALA_VERSION.jar with bcode patches "(currently $SCALA_COMPILER_JAR)" diff --git a/project/Build.scala b/project/Build.scala index e5c4a0699e3d..edb730815b4d 100644 --- a/project/Build.scala +++ b/project/Build.scala @@ -31,7 +31,7 @@ object DottyBuild extends Build { // get reflect and xml onboard libraryDependencies ++= Seq("org.scala-lang" % "scala-reflect" % scalaVersion.value, "org.scala-lang.modules" %% "scala-xml" % "1.0.1", - "me.d-d" % "scala-compiler" % "2.11.5-20150402-193021-0c75410da3", + "me.d-d" % "scala-compiler" % "2.11.5-20150416-144435-09c4a520e1", "jline" % "jline" % "2.12"), // get junit onboard From 42b541ad055ab0fae42991362bc88ec16b74f30a Mon Sep 17 00:00:00 2001 From: Dmitry Petrashko Date: Thu, 16 Apr 2015 17:00:15 +0200 Subject: [PATCH 6/6] Better workaround for #342. This one works also for symbols which are InSuperCall. --- src/dotty/tools/backend/jvm/DottyBackendInterface.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dotty/tools/backend/jvm/DottyBackendInterface.scala b/src/dotty/tools/backend/jvm/DottyBackendInterface.scala index afe9b6f77508..009b7fb2b9f7 100644 --- a/src/dotty/tools/backend/jvm/DottyBackendInterface.scala +++ b/src/dotty/tools/backend/jvm/DottyBackendInterface.scala @@ -427,7 +427,7 @@ class DottyBackendInterface()(implicit ctx: Context) extends BackendInterface{ case TermRef(prefix: ThisType, name) => Some(tpd.This(prefix.cls).select(i.symbol)) case TermRef(NoPrefix, name) => - if (i.symbol is Flags.Method) Some(This(i.symbol.enclosingClass).select(i.symbol)) // workaround #342 todo: remove after fixed + if (i.symbol is Flags.Method) Some(This(i.symbol.topLevelClass).select(i.symbol)) // workaround #342 todo: remove after fixed else None case _ => None }