summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/compiler/scala/tools/nsc/transform/CleanUp.scala96
-rw-r--r--test/files/run/bug1766.scala16
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
+
+}