From afb21953f75beda26a14b447e2caa0a2cb21904a Mon Sep 17 00:00:00 2001 From: Dmitry Petrashko Date: Fri, 11 Apr 2014 15:11:46 +0200 Subject: [PATCH 1/8] Constructors stub --- src/dotty/tools/dotc/Compiler.scala | 1 + .../tools/dotc/transform/Constructors.scala | 27 +++++++++++++++++++ 2 files changed, 28 insertions(+) create mode 100644 src/dotty/tools/dotc/transform/Constructors.scala diff --git a/src/dotty/tools/dotc/Compiler.scala b/src/dotty/tools/dotc/Compiler.scala index 457238da4926..5f2f4f7b0821 100644 --- a/src/dotty/tools/dotc/Compiler.scala +++ b/src/dotty/tools/dotc/Compiler.scala @@ -21,6 +21,7 @@ class Compiler { List( List(new FrontEnd), List(new LazyValsCreateCompanionObjects, + /* new Constructors, */ new TailRec), //force separataion between lazyVals and LVCreateCO List(new PatternMatcher, new LazyValTranformContext().transformer, diff --git a/src/dotty/tools/dotc/transform/Constructors.scala b/src/dotty/tools/dotc/transform/Constructors.scala new file mode 100644 index 000000000000..bc9d6ea61cbf --- /dev/null +++ b/src/dotty/tools/dotc/transform/Constructors.scala @@ -0,0 +1,27 @@ +package dotty.tools.dotc.transform + +import TreeTransforms._ +import dotty.tools.dotc.ast.tpd._ +import dotty.tools.dotc.core.Contexts.Context +import dotty.tools.dotc.core.StdNames._ + +/** This transform moves initializers from body to constructor. + * Right now it's a dummy. + * Awaiting for real implemetation + */ +class Constructors extends TreeTransform { + + override def name: String = "constructors" + override def transformDefDef(tree: DefDef)(implicit ctx: Context, info: TransformerInfo): Tree = { + if(tree.symbol.isClassConstructor) { + val claz = tree.symbol.enclosingClass.asClass + val zuper = claz.info.parents.head.typeSymbol + cpy.DefDef(tree, tree.mods, tree.name, tree.tparams, tree.vparamss, tree.tpt, rhs = { + val parentCall = Apply(Select(Super(This(claz), tpnme.EMPTY, true), zuper.primaryConstructor), Nil) + if(tree.rhs.isEmpty) parentCall + else Block(List(parentCall), tree.rhs) + + }) + } else tree + } +} \ No newline at end of file From 0b585c662a1422914e549c142521cab46ccd2cb9 Mon Sep 17 00:00:00 2001 From: Dmitry Petrashko Date: Fri, 11 Apr 2014 15:13:14 +0200 Subject: [PATCH 2/8] CollectEntryPoints. Collect entry points for backend. Previously this was done by cleanup. --- src/dotty/tools/dotc/Compiler.scala | 2 +- .../tools/dotc/config/JavaPlatform.scala | 20 ++- .../dotc/transform/CollectEntryPoints.scala | 115 ++++++++++++++++++ 3 files changed, 135 insertions(+), 2 deletions(-) create mode 100644 src/dotty/tools/dotc/transform/CollectEntryPoints.scala diff --git a/src/dotty/tools/dotc/Compiler.scala b/src/dotty/tools/dotc/Compiler.scala index 5f2f4f7b0821..36af6a438035 100644 --- a/src/dotty/tools/dotc/Compiler.scala +++ b/src/dotty/tools/dotc/Compiler.scala @@ -30,7 +30,7 @@ class Compiler { new TypeTestsCasts, new InterceptedMethods), List(new Erasure), - List(new UncurryTreeTransform) + List(new UncurryTreeTransform, new CollectEntryPoints) ) var runId = 1 diff --git a/src/dotty/tools/dotc/config/JavaPlatform.scala b/src/dotty/tools/dotc/config/JavaPlatform.scala index c4421d16ba24..043f41a44467 100644 --- a/src/dotty/tools/dotc/config/JavaPlatform.scala +++ b/src/dotty/tools/dotc/config/JavaPlatform.scala @@ -5,7 +5,9 @@ package config import io.{AbstractFile,ClassPath,JavaClassPath,MergedClassPath,DeltaClassPath} import ClassPath.{ JavaContext, DefaultJavaContext } import core.Contexts._ -import core.SymDenotations._, core.Symbols._, core.{SymbolLoader, ClassfileLoader} +import core.SymDenotations._, core.Symbols._, dotty.tools.dotc.core._ +import Types._, Contexts._, Symbols._, Denotations._, SymDenotations._, StdNames._, Names._ +import Flags._, Scopes._, Decorators._, NameOps._, util.Positions._ class JavaPlatform extends Platform { @@ -17,6 +19,22 @@ class JavaPlatform extends Platform { currentClassPath.get } + // The given symbol is a method with the right name and signature to be a runnable java program. + def isJavaMainMethod(sym: SymDenotation)(implicit ctx: Context) = { + val dn = defn + (sym.name == nme.main) && (sym.info match { + case t@MethodType(_, dn.ArrayType(el) :: Nil) => el =:= defn.StringType && (t.resultType isRef defn.UnitClass) + case _ => false + }) + } + + // The given class has a main method. + def hasJavaMainMethod(sym: Symbol)(implicit ctx: Context): Boolean = + (sym.info member nme.main).hasAltWith { + case x: SymDenotation => isJavaMainMethod(x) + case _ => false + } + /** Update classpath with a substituted subentry */ def updateClassPath(subst: Map[ClassPath, ClassPath]) = currentClassPath = Some(new DeltaClassPath(currentClassPath.get, subst)) diff --git a/src/dotty/tools/dotc/transform/CollectEntryPoints.scala b/src/dotty/tools/dotc/transform/CollectEntryPoints.scala new file mode 100644 index 000000000000..0e9f98e79496 --- /dev/null +++ b/src/dotty/tools/dotc/transform/CollectEntryPoints.scala @@ -0,0 +1,115 @@ +package dotty.tools.dotc.transform + +import dotty.tools.dotc.transform.TreeTransforms.{TransformerInfo, TreeTransform, TreeTransformer} +import dotty.tools.dotc.ast.tpd +import dotty.tools.dotc.core.Contexts.Context +import scala.collection.mutable.ListBuffer +import dotty.tools.dotc.core.{Scopes, Flags} +import dotty.tools.dotc.core.Symbols.NoSymbol +import scala.annotation.tailrec +import dotty.tools.dotc.core._ +import Symbols._ +import scala.Some +import dotty.tools.dotc.transform.TreeTransforms.{NXTransformations, TransformerInfo, TreeTransform, TreeTransformer} +import dotty.tools.dotc.ast.tpd +import dotty.tools.dotc.core.Contexts.Context +import scala.collection.mutable +import dotty.tools.dotc.core.Names.Name +import NameOps._ +import Types._ +import scala.collection.SortedSet +import Decorators._ +import StdNames._ +import dotty.tools.dotc.util.Positions.Position +import dotty.tools.dotc.config.JavaPlatform + +class CollectEntryPoints extends TreeTransform { + + /** perform context-dependant initialization */ + override def init(implicit ctx: Context, info: TransformerInfo): Unit = { + entryPoints = collection.immutable.TreeSet.empty[Symbol](new SymbolOrdering()) + assert(ctx.platform.isInstanceOf[JavaPlatform], "Java platform specific phase") + } + + private var entryPoints: Set[Symbol] = _ + + def getEntryPoints = entryPoints.toList + + override def name: String = "collectEntryPoints" + override def transformDefDef(tree: tpd.DefDef)(implicit ctx: Context, info: TransformerInfo): tpd.Tree = { + if (tree.symbol.owner.isClass && isJavaEntryPoint(tree.symbol)) { + // collecting symbols for entry points here (as opposed to GenBCode where they are used) + // has the advantage of saving an additional pass over all ClassDefs. + entryPoints += tree.symbol + } + tree + } + + def isJavaEntryPoint(sym: Symbol)(implicit ctx: Context): Boolean = { + def fail(msg: String, pos: Position = sym.pos) = { + ctx.warning(sym.name + + s" has a main method with parameter type Array[String], but ${sym.fullName} will not be a runnable program.\n Reason: $msg", + sourcePos(sym.pos) + // TODO: make this next claim true, if possible + // by generating valid main methods as static in module classes + // not sure what the jvm allows here + // + " You can still run the program by calling it as " + javaName(sym) + " instead." + ) + false + } + def failNoForwarder(msg: String) = { + fail(s"$msg, which means no static forwarder can be generated.\n") + } + val possibles = if (sym.flags is Flags.Module) (sym.info nonPrivateMember nme.main).alternatives else Nil + val hasApproximate = possibles exists { + m => + m.info match { + case MethodType(_, p :: Nil) => + p.typeSymbol == defn.ArrayClass + case _ => false + } + } + def precise(implicit ctx: Context) = { + val companion = sym.companionClass //sym.asClass.linkedClassOfClass + val javaPlatform = ctx.platform.asInstanceOf[JavaPlatform] + if (javaPlatform.hasJavaMainMethod(companion)) + failNoForwarder("companion contains its own main method") + else if (companion != NoSymbol && companion.info.member(nme.main) != NoSymbol) + // this is only because forwarders aren't smart enough yet + failNoForwarder("companion contains its own main method (implementation restriction: no main is allowed, regardless of signature)") + else if (companion.flags is Flags.Trait) + failNoForwarder("companion is a trait") + // Now either succeeed, or issue some additional warnings for things which look like + // attempts to be java main methods. + else (possibles exists (x => javaPlatform.isJavaMainMethod(x.symbol))) || { + possibles exists { + m => + m.symbol.info match { + case t: PolyType => + fail("main methods cannot be generic.") + case t@MethodType(paramNames, paramTypes) => + if (t.resultType :: paramTypes exists (_.typeSymbol.isAbstractType)) + fail("main methods cannot refer to type parameters or abstract types.", m.symbol.pos) + else + javaPlatform.isJavaMainMethod(m.symbol) || fail("main method must have exact signature (Array[String])Unit", m.symbol.pos) + case tp => + fail(s"don't know what this is: $tp", m.symbol.pos) + } + } + } + } + + // At this point it's a module with a main-looking method, so either succeed or warn that it isn't. + hasApproximate && precise(ctx.withPhase(ctx.erasurePhase)) + // Before erasure so we can identify generic mains. + + +} + +} + +class SymbolOrdering(implicit ctx: Context) extends Ordering[Symbol] { + override def compare(x: Symbol, y: Symbol): Int = { + x.fullName.toString.compareTo(y.fullName.toString) + } +} \ No newline at end of file From ffe0131a4fb464a49bb6799c4e7fcafc4603f609 Mon Sep 17 00:00:00 2001 From: Dmitry Petrashko Date: Mon, 14 Apr 2014 14:39:44 +0200 Subject: [PATCH 3/8] Helper method to get all members of type. --- src/dotty/tools/dotc/core/Types.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dotty/tools/dotc/core/Types.scala b/src/dotty/tools/dotc/core/Types.scala index 66f0279150b4..5ce13ad55a98 100644 --- a/src/dotty/tools/dotc/core/Types.scala +++ b/src/dotty/tools/dotc/core/Types.scala @@ -427,7 +427,7 @@ object Types { Set() } - private def memberDenots(keepOnly: NameFilter, f: (Name, mutable.Buffer[SingleDenotation]) => Unit)(implicit ctx: Context): Seq[SingleDenotation] = { + def memberDenots(keepOnly: NameFilter, f: (Name, mutable.Buffer[SingleDenotation]) => Unit)(implicit ctx: Context): Seq[SingleDenotation] = { val buf = mutable.ArrayBuffer[SingleDenotation]() for (name <- memberNames(keepOnly)) f(name, buf) buf From 9e5cfe27f5d4b34b30102e78222c222ad7604414 Mon Sep 17 00:00:00 2001 From: Dmitry Petrashko Date: Mon, 14 Apr 2014 15:19:47 +0200 Subject: [PATCH 4/8] Fix error in box\unbox logic. TermRef's for primitive types are of primitive-type. --- src/dotty/tools/dotc/transform/Erasure.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dotty/tools/dotc/transform/Erasure.scala b/src/dotty/tools/dotc/transform/Erasure.scala index 562a30682046..791df341ad09 100644 --- a/src/dotty/tools/dotc/transform/Erasure.scala +++ b/src/dotty/tools/dotc/transform/Erasure.scala @@ -205,7 +205,7 @@ object Erasure { else recur(cast(qual, erasedPre)) def recur(qual: Tree): Tree = { - val qualIsPrimitive = isPrimitiveValueType(qual.tpe) + val qualIsPrimitive = isPrimitiveValueType(qual.tpe.widen) val symIsPrimitive = sym.owner.isPrimitiveValueClass if ((sym.owner eq defn.AnyClass) || (sym.owner eq defn.AnyValClass)) select(qual, defn.ObjectClass.info.decl(sym.name).symbol) From 026b86da4c11a2e4933af00fe65cb2c37851ed3c Mon Sep 17 00:00:00 2001 From: Dmitry Petrashko Date: Mon, 14 Apr 2014 16:13:11 +0200 Subject: [PATCH 5/8] Fix TailRec to use Label flag. Conflicts: src/dotty/tools/dotc/backend/jvm/BCodeBodyBuilder.scala src/dotty/tools/dotc/core/Definitions.scala --- src/dotty/tools/dotc/transform/TailRec.scala | 22 ++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/src/dotty/tools/dotc/transform/TailRec.scala b/src/dotty/tools/dotc/transform/TailRec.scala index 543510dd75b4..b0d5c643834d 100644 --- a/src/dotty/tools/dotc/transform/TailRec.scala +++ b/src/dotty/tools/dotc/transform/TailRec.scala @@ -83,10 +83,11 @@ class TailRec extends TreeTransform with DenotTransformer { override def name: String = "tailrec" final val labelPrefix = "tailLabel" + final val labelFlags = Flags.Synthetic | Flags.Label private def mkLabel(method: Symbol, tp: Type)(implicit c: Context): TermSymbol = { val name = c.freshName(labelPrefix) - c.newSymbol(method, name.toTermName, Flags.Synthetic, tp) + c.newSymbol(method, name.toTermName, labelFlags , tp) } override def transformDefDef(tree: tpd.DefDef)(implicit ctx: Context, info: TransformerInfo): tpd.Tree = { @@ -95,7 +96,7 @@ class TailRec extends TreeTransform with DenotTransformer { if (dd.symbol.isEffectivelyFinal) && !((dd.symbol is Flags.Accessor) || (rhs0 eq EmptyTree)) => val mandatory = dd.symbol.hasAnnotation(defn.TailrecAnnotationClass) cpy.DefDef(tree, mods, name, tparams, vparamss0, tpt, rhs = { - val owner = ctx.owner.enclosingClass + val owner = ctx.owner.enclosingClass.asClass val thisTpe = owner.thisType @@ -112,16 +113,25 @@ class TailRec extends TreeTransform with DenotTransformer { // than first one will collect info about which transformations and rewritings should be applied // and second one will actually apply, // now this speculatively transforms tree and throws away result in many cases - val res = tpd.Closure(label, args => { + val res = tpd.DefDef(label, args => { val thiz = args.head.head val argMapping: Map[Symbol, Tree] = (vparamss0.flatten.map(_.symbol) zip args.tail.flatten).toMap val transformer = new TailRecElimination(dd.symbol, thiz, argMapping, owner, mandatory, label) val rhs = transformer.transform(rhs0)(ctx.withPhase(ctx.phase.next)) rewrote = transformer.rewrote rhs - }, tparams) - - if (rewrote) res + }) + + if (rewrote) { + val call = + if (tparams.isEmpty) Ident(label.termRef) + else TypeApply(Ident(label.termRef), tparams) + Block( + List(res), + vparamss0.foldLeft(Apply(call, List(This(owner)))) + {case (call, args) => Apply(call, args.map(x=> Ident(x.symbol.termRef)))} + ) + } else { if (mandatory) ctx.error("TailRec optimisation not applicable, method not tail recursive", dd.pos) From 54034c1f56b6d9a10cbe2985a5cd90e5dc354f7e Mon Sep 17 00:00:00 2001 From: Dmitry Petrashko Date: Mon, 14 Apr 2014 16:13:11 +0200 Subject: [PATCH 6/8] Definitions used by backend. --- src/dotty/tools/dotc/core/Definitions.scala | 23 +++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/dotty/tools/dotc/core/Definitions.scala b/src/dotty/tools/dotc/core/Definitions.scala index f1c69027ed6e..9497438f2f33 100644 --- a/src/dotty/tools/dotc/core/Definitions.scala +++ b/src/dotty/tools/dotc/core/Definitions.scala @@ -156,6 +156,8 @@ class Definitions { lazy val ScalaPredefModule = ctx.requiredModule("scala.Predef") lazy val ScalaRuntimeModule = ctx.requiredModule("scala.runtime.ScalaRunTime") + lazy val BoxesRunTimeModule = ctx.requiredModule("scala.runtime.BoxesRunTime") + lazy val BoxesRunTimeClass = BoxesRunTimeModule.moduleClass lazy val DottyPredefModule = ctx.requiredModule("dotty.DottyPredef") lazy val NilModule = ctx.requiredModule("scala.collection.immutable.Nil") @@ -168,6 +170,10 @@ class Definitions { List(AnyClass.typeRef), EmptyScope) lazy val SeqClass: ClassSymbol = ctx.requiredClass("scala.collection.Seq") lazy val ArrayClass: ClassSymbol = ctx.requiredClass("scala.Array") + lazy val Array_apply = ctx.requiredMethod(ArrayClass, nme.apply) + lazy val Array_update = ctx.requiredMethod(ArrayClass, nme.update) + lazy val Array_length = ctx.requiredMethod(ArrayClass, nme.length) + lazy val Array_clone = ctx.requiredMethod(ArrayClass, nme.clone_) lazy val uncheckedStableClass: ClassSymbol = ctx.requiredClass("scala.annotation.unchecked.uncheckedStable") lazy val UnitClass = valueClassSymbol("scala.Unit", BoxedUnitClass, java.lang.Void.TYPE, UnitEnc) @@ -211,8 +217,20 @@ class Definitions { // fundamental classes lazy val StringClass = ctx.requiredClass("java.lang.String") + lazy val StringModule = StringClass.moduleClass lazy val String_+ = newMethod(StringClass, nme.raw.PLUS, methOfAny(StringType), Final) + lazy val String_valueOf_Object = StringModule.info.member(nme.valueOf).suchThat(_.info.firstParamTypes match { + case List(pt) => pt isRef ObjectClass + case _ => false + }).symbol + + // in scalac modified to have Any as parrent + + lazy val SerializableClass = ctx.requiredClass("scala.Serializable") + lazy val JavaCloneableClass = ctx.requiredClass("java.lang.Cloneable") + lazy val StringBuilderClass = ctx.requiredClass("scala.collection.mutable.StringBuilder") + lazy val NullPointerExceptionClass = ctx.requiredClass(jnme.NPException) lazy val StringAddClass = ctx.requiredClass("scala.runtime.StringAdd") @@ -238,6 +256,11 @@ class Definitions { lazy val ClassfileAnnotationClass = ctx.requiredClass("scala.annotation.ClassfileAnnotation") lazy val StaticAnnotationClass = ctx.requiredClass("scala.annotation.StaticAnnotation") lazy val TailrecAnnotationClass = ctx.requiredClass("scala.annotation.tailrec") + lazy val RemoteAnnot = ctx.requiredClass("scala.remote") + lazy val SerialVersionUIDAnnot = ctx.requiredClass("scala.SerialVersionUID") + lazy val TransientAnnot = ctx.requiredClass("scala.transient") + lazy val NativeAnnot = ctx.requiredClass("scala.native") + lazy val ScalaStrictFPAnnot = ctx.requiredClass("scala.annotation.strictfp") // Annotation classes lazy val AliasAnnot = ctx.requiredClass("dotty.annotation.internal.Alias") From a0dd4ca40f6e7fd2d1e594b6580aa329f78e9768 Mon Sep 17 00:00:00 2001 From: Dmitry Petrashko Date: Tue, 15 Apr 2014 13:31:23 +0200 Subject: [PATCH 7/8] Fix invalid flags in lazy vals. --- src/dotty/tools/dotc/transform/LazyVals.scala | 25 +++++++++++-------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/src/dotty/tools/dotc/transform/LazyVals.scala b/src/dotty/tools/dotc/transform/LazyVals.scala index 840ca0cdb3ff..9e5ddffa4249 100644 --- a/src/dotty/tools/dotc/transform/LazyVals.scala +++ b/src/dotty/tools/dotc/transform/LazyVals.scala @@ -45,6 +45,8 @@ class LazyValTranformContext { def transformer = new LazyValsTransform + val containerFlags = Flags.Synthetic | Flags.Mutable + /** this map contains mutable state of transformation: OffsetDefs to be appended to companion object definitions, * and number of bits currently used */ class OffsetInfo(var defs: List[Tree], var ord:Int) @@ -140,9 +142,12 @@ class LazyValTranformContext { val holderImpl = ctx.requiredClass("dotty.runtime." + holderType) - val holderSymbol = ctx.newSymbol(x.symbol.owner, holderName, Flags.Synthetic, holderImpl.typeRef, coord = x.symbol.coord) + val holderSymbol = ctx.newSymbol(x.symbol.owner, holderName, containerFlags, holderImpl.typeRef, coord = x.symbol.coord) val holderTree = ValDef(holderSymbol, New(holderImpl.typeRef, List(valueInitter))) - val methodTree = DefDef(x.symbol.asTerm, Select(Ident(holderSymbol.termRef), "value".toTermName)) + val methodBody = + if(holderType != "LazyRef") Select(Ident(holderSymbol.termRef), "value".toTermName) + else TypeApply(Select(Select(Ident(holderSymbol.termRef), "value".toTermName), defn.Any_asInstanceOf), List(TypeTree(tpe))) + val methodTree = DefDef(x.symbol.asTerm, methodBody) ctx.debuglog(s"found a lazy val ${x.show},\n rewrote with ${holderTree.show}") Thicket(holderTree, methodTree) } @@ -201,7 +206,7 @@ class LazyValTranformContext { val tpe = x.tpe.widen assert(!(mods is Flags.Mutable)) val containerName = ctx.freshName(name.toString + StdNames.nme.LAZY_LOCAL).toTermName - val containerSymbol = ctx.newSymbol(claz, containerName, (mods &~ Flags.Lazy & Flags.Synthetic).flags, tpe, coord = x.symbol.coord) + val containerSymbol = ctx.newSymbol(claz, containerName, (mods &~ Flags.Lazy | containerFlags).flags, tpe, coord = x.symbol.coord) addSym(claz, containerSymbol) val containerTree = ValDef(containerSymbol, Literal(initValue(tpe))) @@ -211,7 +216,7 @@ class LazyValTranformContext { } else { val flagName = ctx.freshName(name.toString + StdNames.nme.BITMAP_PREFIX).toTermName - val flagSymbol = ctx.newSymbol(x.symbol.owner, flagName, Flags.Synthetic, defn.BooleanType) + val flagSymbol = ctx.newSymbol(x.symbol.owner, flagName, containerFlags, defn.BooleanType) val flag = ValDef(flagSymbol, Literal(Constants.Constant(false))) val slowPath = DefDef(x.symbol.asTerm, mkNonThreadSafeDef(containerSymbol, flagSymbol, rhs)) Thicket(List(containerTree, flag, slowPath)) @@ -256,15 +261,15 @@ class LazyValTranformContext { val computeState = Literal(Constants.Constant(1)) val notifyState = Literal(Constants.Constant(2)) val computedState = Literal(Constants.Constant(3)) - val flagSymbol = ctx.newSymbol(methodSymbol, "flag".toTermName, Flags.Mutable & Flags.Synthetic, defn.LongType) + val flagSymbol = ctx.newSymbol(methodSymbol, "flag".toTermName, containerFlags, defn.LongType) val flagDef = ValDef(flagSymbol, Literal(Constant(0L))) val thiz = This(claz)(ctx.fresh.setOwner(claz)) - val resultSymbol = ctx.newSymbol(methodSymbol, "result".toTermName, Flags.Mutable & Flags.Synthetic, tp) + val resultSymbol = ctx.newSymbol(methodSymbol, "result".toTermName, containerFlags, tp) val resultDef = ValDef(resultSymbol, Literal(initValue(tp.widen))) - val retrySymbol = ctx.newSymbol(methodSymbol, "retry".toTermName, Flags.Mutable & Flags.Synthetic, defn.BooleanType) + val retrySymbol = ctx.newSymbol(methodSymbol, "retry".toTermName, containerFlags, defn.BooleanType) val retryDef = ValDef(retrySymbol, Literal(Constants.Constant(true))) val whileCond = Ident(retrySymbol.termRef) @@ -345,7 +350,7 @@ class LazyValTranformContext { } else { // need to create a new flag offsetSymbol = ctx.newSymbol(companion.moduleClass, (StdNames.nme.LAZY_FIELD_OFFSET + id.toString).toTermName, Flags.Synthetic, defn.LongType).entered val flagName = (StdNames.nme.BITMAP_PREFIX + id.toString).toTermName - val flagSymbol = ctx.newSymbol(claz, flagName, Flags.Synthetic, defn.LongType) + val flagSymbol = ctx.newSymbol(claz, flagName, containerFlags, defn.LongType) addSym(claz, flagSymbol) flag = ValDef(flagSymbol, Literal(Constants.Constant(0L))) val offsetTree = ValDef(offsetSymbol, Apply(getOffset, List(thiz, Literal(Constant(flagName.toString))))) @@ -355,7 +360,7 @@ class LazyValTranformContext { case None => offsetSymbol = ctx.newSymbol(companion.moduleClass, (StdNames.nme.LAZY_FIELD_OFFSET + "0").toTermName, Flags.Synthetic, defn.LongType).entered val flagName = (StdNames.nme.BITMAP_PREFIX + "0").toTermName - val flagSymbol = ctx.newSymbol(claz, flagName, Flags.Synthetic, defn.LongType) + val flagSymbol = ctx.newSymbol(claz, flagName, containerFlags, defn.LongType) addSym(claz, flagSymbol) flag = ValDef(flagSymbol, Literal(Constants.Constant(0L))) val offsetTree = ValDef(offsetSymbol, Apply(getOffset, List(thiz, Literal(Constant(flagName.toString))))) @@ -363,7 +368,7 @@ class LazyValTranformContext { } val containerName = ctx.freshName(name.toString + StdNames.nme.LAZY_LOCAL).toTermName - val containerSymbol = ctx.newSymbol(claz, containerName, (mods &~ Flags.Lazy & Flags.Synthetic).flags, tpe, coord = x.symbol.coord) + val containerSymbol = ctx.newSymbol(claz, containerName, (mods &~ Flags.Lazy | containerFlags).flags, tpe, coord = x.symbol.coord) addSym(claz, containerSymbol) val containerTree = ValDef(containerSymbol, Literal(initValue(tpe))) From 20010624fe079297ae9039d9b31efbcfa7483bf0 Mon Sep 17 00:00:00 2001 From: Dmitry Petrashko Date: Sat, 3 May 2014 11:47:03 +0200 Subject: [PATCH 8/8] Better error message if position of tree isn't set. --- src/dotty/tools/dotc/typer/Typer.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dotty/tools/dotc/typer/Typer.scala b/src/dotty/tools/dotc/typer/Typer.scala index 165ae70ddca0..e4acff53631d 100644 --- a/src/dotty/tools/dotc/typer/Typer.scala +++ b/src/dotty/tools/dotc/typer/Typer.scala @@ -956,7 +956,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit } def typed(tree: untpd.Tree, pt: Type = WildcardType)(implicit ctx: Context): Tree = /*>|>*/ ctx.traceIndented (i"typing $tree", typr, show = true) /*<|<*/ { - if (!tree.isEmpty && ctx.typerState.isGlobalCommittable) assert(tree.pos.exists, tree) + if (!tree.isEmpty && ctx.typerState.isGlobalCommittable) assert(tree.pos.exists, i"position not set for $tree") try adapt(typedUnadapted(tree, pt), pt) catch { case ex: CyclicReference => errorTree(tree, cyclicErrorMsg(ex))