diff options
-rw-r--r-- | src/compiler/scala/tools/nsc/transform/CleanUp.scala | 96 | ||||
-rw-r--r-- | test/files/run/bug1766.scala | 16 |
2 files changed, 54 insertions, 58 deletions
diff --git a/src/compiler/scala/tools/nsc/transform/CleanUp.scala b/src/compiler/scala/tools/nsc/transform/CleanUp.scala index c3c60253b9..9b92a230cd 100644 --- a/src/compiler/scala/tools/nsc/transform/CleanUp.scala +++ b/src/compiler/scala/tools/nsc/transform/CleanUp.scala @@ -8,7 +8,7 @@ package transform import symtab._ import Flags._ -import scala.collection.mutable.{ListBuffer, HashMap} +import scala.collection._ abstract class CleanUp extends Transform with ast.TreeDSL { import global._ @@ -22,11 +22,12 @@ abstract class CleanUp extends Transform with ast.TreeDSL { new CleanUpTransformer(unit) class CleanUpTransformer(unit: CompilationUnit) extends Transformer { - private val newDefs = new ListBuffer[Tree] - private val newInits = new ListBuffer[Tree] + private val newStaticMembers = mutable.Buffer.empty[Tree] + private val newStaticInits = mutable.Buffer.empty[Tree] + private val symbolsStoredAsStatic = mutable.Map.empty[String, Symbol] - private val classConstantMeth = new HashMap[String, Symbol] - private val symbolStaticFields = new HashMap[String, (Symbol, Tree, Tree)] + //private val classConstantMeth = new HashMap[String, Symbol] + //private val symbolStaticFields = new HashMap[String, (Symbol, Tree, Tree)] private var localTyper: analyzer.Typer = null @@ -116,10 +117,10 @@ abstract class CleanUp extends Transform with ast.TreeDSL { currentClass.info.decls enter varSym val varDef = typedPos( VAL(varSym) === forInit ) - newDefs append transform(varDef) + newStaticMembers append transform(varDef) val varInit = typedPos( REF(varSym) === forInit ) - newInits append transform(varInit) + newStaticInits append transform(varInit) varSym } @@ -133,7 +134,7 @@ abstract class CleanUp extends Transform with ast.TreeDSL { currentClass.info.decls enter methSym val methDef = typedPos( DefDef(methSym, { forBody(Pair(methSym, methSym.paramss(0))) }) ) - newDefs append transform(methDef) + newStaticMembers append transform(methDef) methSym } @@ -516,39 +517,25 @@ abstract class CleanUp extends Transform with ast.TreeDSL { /* Some cleanup transformations add members to templates (classes, traits, etc). * When inside a template (i.e. the body of one of its members), two maps - * (newDefs and newInits) are available in the tree transformer. Any mapping from - * a symbol to a MemberDef (DefDef, ValDef, etc.) that is in newDefs once the + * (newStaticMembers and newStaticInits) are available in the tree transformer. Any mapping from + * a symbol to a MemberDef (DefDef, ValDef, etc.) that is in newStaticMembers once the * transformation of the template is finished will be added as a member to the - * template. Any mapping from a symbol to a tree that is in newInits, will be added + * template. Any mapping from a symbol to a tree that is in newStaticInits, will be added * as a statement of the form "symbol = tree" to the beginning of the default * constructor. */ case Template(parents, self, body) => localTyper = typer.atOwner(tree, currentClass) - val transformedTemplate = if (!forMSIL) { - classConstantMeth.clear - newDefs.clear - newInits.clear - var newBody = - transformTrees(body) - val firstConstructor = - treeInfo.firstConstructor(newBody) - newBody = - transformTrees(newDefs.toList) ::: ( - for (member <- newBody) yield member match { - case thePrimaryConstructor@DefDef(mods, name, tparams, vparamss, tpt, rhs) if (thePrimaryConstructor == firstConstructor) => - val newRhs = rhs match { - case theRhs@Block(stats, expr) => - treeCopy.Block(theRhs, transformTrees(newInits.toList) ::: stats, expr) - } - treeCopy.DefDef(thePrimaryConstructor, mods, name, tparams, vparamss, tpt, newRhs) - case notThePrimaryConstructor => - notThePrimaryConstructor - } - ) - treeCopy.Template(tree, parents, self, newBody) - } - else super.transform(tree) - applySymbolFieldInitsToStaticCtor(transformedTemplate.asInstanceOf[Template]) // postprocess to include static ctors + newStaticMembers.clear + newStaticInits.clear + symbolsStoredAsStatic.clear + val transformedTemplate: Template = + if (!forMSIL) { + var newBody = + transformTrees(body) + treeCopy.Template(tree, parents, self, transformTrees(newStaticMembers.toList) ::: newBody) + } + else super.transform(tree).asInstanceOf[Template] + addStaticInits(transformedTemplate) // postprocess to include static ctors case Literal(c) if (c.tag == ClassTag) && !forMSIL=> val tpe = c.typeValue @@ -628,7 +615,7 @@ abstract class CleanUp extends Transform with ast.TreeDSL { List(Literal(Constant(symname: String)))) => // add the symbol name to a map if it's not there already val rhs = gen.mkCast(Apply(gen.scalaDot(nme.Symbol), List(Literal(Constant(symname)))), symbolType) - val (staticFieldSym, sfdef, sfinit) = getSymbolStaticField(symapp.pos, symname, rhs, symapp) + val staticFieldSym = getSymbolStaticField(symapp.pos, symname, rhs, symapp) // create a reference to a static field val ntree = typedWithPos(symapp.pos)(REF(staticFieldSym)) @@ -642,8 +629,8 @@ abstract class CleanUp extends Transform with ast.TreeDSL { * If it doesn't exist, i.e. the symbol is encountered the first time, * it creates a new static field definition and initialization and returns it. */ - private def getSymbolStaticField(pos: Position, symname: String, rhs: Tree, tree: Tree): (Symbol, Tree, Tree) = - symbolStaticFields.getOrElseUpdate(symname, { + private def getSymbolStaticField(pos: Position, symname: String, rhs: Tree, tree: Tree): Symbol = + symbolsStoredAsStatic.getOrElseUpdate(symname, { val freshname = unit.fresh.newName(pos, "symbol$") val theTyper = typer.atOwner(tree, currentClass) @@ -658,20 +645,14 @@ abstract class CleanUp extends Transform with ast.TreeDSL { val stfieldInit = theTyper.typed { atPos(pos)(REF(stfieldSym) === rhs) } // add field definition to new defs - newDefs append stfieldDef + newStaticMembers append stfieldDef + newStaticInits append stfieldInit - (stfieldSym, stfieldDef, stfieldInit) + stfieldSym }) - /* returns a list of all trees for symbol static fields, and clear the list */ - private def flushSymbolFieldsInitializations: List[Tree] = { - val fields = (symbolStaticFields.valuesIterator map (_._3)).toList - symbolStaticFields.clear - fields - } - /* finds the static ctor DefDef tree within the template if it exists. */ - def findStaticCtor(template: Template): Option[Tree] = + private def findStaticCtor(template: Template): Option[Tree] = template.body find { case defdef @ DefDef(mods, nme.CONSTRUCTOR, tparam, vparam, tp, rhs) => defdef.symbol hasFlag STATIC case _ => false @@ -680,11 +661,10 @@ abstract class CleanUp extends Transform with ast.TreeDSL { /* changes the template for the class so that it contains a static constructor with symbol fields inits, * augments an existing static ctor if one already existed. */ - def applySymbolFieldInitsToStaticCtor(template: Template): Template = { - val symbolInitTrees = flushSymbolFieldsInitializations - if (symbolInitTrees.isEmpty) template + private def addStaticInits(template: Template): Template = + if (newStaticInits.isEmpty) + template else { - val theTyper = typer.atOwner(template, currentClass) val newCtor = findStaticCtor(template) match { // in case there already were static ctors - augment existing ones // currently, however, static ctors aren't being generated anywhere else @@ -693,10 +673,10 @@ abstract class CleanUp extends Transform with ast.TreeDSL { val newBlock = rhs match { case block @ Block(stats, expr) => // need to add inits to existing block - treeCopy.Block(block, symbolInitTrees ::: stats, expr) + treeCopy.Block(block, newStaticInits.toList ::: stats, expr) case term: TermTree => // need to create a new block with inits and the old term - treeCopy.Block(term, symbolInitTrees, term) + treeCopy.Block(term, newStaticInits.toList, term) } treeCopy.DefDef(ctor, mods, name, tparams, vparamss, tpt, newBlock) case None => @@ -704,13 +684,13 @@ abstract class CleanUp extends Transform with ast.TreeDSL { val staticCtorSym = currentClass.newConstructor(template.pos) .setFlag(STATIC) .setInfo(UnitClass.tpe) - val rhs = Block(symbolInitTrees, Literal(())) + val rhs = Block(newStaticInits.toList, Literal(())) val staticCtorTree = DefDef(staticCtorSym, rhs) - theTyper.typed { atPos(template.pos)(staticCtorTree) } + localTyper.typed { atPos(template.pos)(staticCtorTree) } } treeCopy.Template(template, template.parents, template.self, newCtor :: template.body) } - } + } // CleanUpTransformer } diff --git a/test/files/run/bug1766.scala b/test/files/run/bug1766.scala new file mode 100644 index 0000000000..901f9ae664 --- /dev/null +++ b/test/files/run/bug1766.scala @@ -0,0 +1,16 @@ +object Test extends Application { + + class C(s: String) { + + def this(i: Int) = this("bar") + + def f = { + val v: { def n: Int } = new { val n = 3 } + v.n + } + + } + + new C("foo").f + +} |