diff options
author | Hubert Plociniczak <hubert.plociniczak@epfl.ch> | 2010-10-20 13:26:07 +0000 |
---|---|---|
committer | Hubert Plociniczak <hubert.plociniczak@epfl.ch> | 2010-10-20 13:26:07 +0000 |
commit | add9be644fd7b2864e4dcdd792980622622c934a (patch) | |
tree | 6db3295dcbbcc453ac9f57ae8993ff0e3a68c4b9 | |
parent | de3e8492e61e02777520e8876e9e1bccb4b0f065 (diff) | |
download | scala-add9be644fd7b2864e4dcdd792980622622c934a.tar.gz scala-add9be644fd7b2864e4dcdd792980622622c934a.tar.bz2 scala-add9be644fd7b2864e4dcdd792980622622c934a.zip |
Closes #3670, #3877.
-rw-r--r-- | src/compiler/scala/tools/nsc/transform/LazyVals.scala | 60 | ||||
-rw-r--r-- | test/files/pos/t3670.scala | 43 | ||||
-rw-r--r-- | test/files/run/t3670.check | 5 | ||||
-rw-r--r-- | test/files/run/t3670.scala | 31 | ||||
-rw-r--r-- | test/files/run/t3877.check | 104 | ||||
-rw-r--r-- | test/files/run/t3877.scala | 81 |
6 files changed, 319 insertions, 5 deletions
diff --git a/src/compiler/scala/tools/nsc/transform/LazyVals.scala b/src/compiler/scala/tools/nsc/transform/LazyVals.scala index 98b98b06ac..02da067619 100644 --- a/src/compiler/scala/tools/nsc/transform/LazyVals.scala +++ b/src/compiler/scala/tools/nsc/transform/LazyVals.scala @@ -16,6 +16,28 @@ abstract class LazyVals extends Transform with TypingTransformers with ast.TreeD def newTransformer(unit: CompilationUnit): Transformer = new LazyValues(unit) + object LocalLazyValFinder extends Traverser { + var result: Boolean = _ + + def find(t: Tree) = {result = false; traverse(t); result} + def find(ts: List[Tree]) = {result = false; traverseTrees(ts); result} + + override def traverse(t: Tree) { + if (!result) + t match { + case v@ValDef(_, _, _, _) if v.symbol.isLazy => + result = true + + case ClassDef(_, _, _, _) | DefDef(_, _, _, _, _, _) | ModuleDef(_, _, _) => + + case LabelDef(name, _, _) if nme.isLoopHeaderLabel(name) => + + case _ => + super.traverse(t) + } + } + } + /** * Transform local lazy accessors to check for the initialized bit. */ @@ -46,14 +68,15 @@ abstract class LazyVals extends Transform with TypingTransformers with ast.TreeD val enclosingDummyOrMethod = if (sym.enclMethod == NoSymbol) sym.owner else sym.enclMethod val idx = lazyVals(enclosingDummyOrMethod) + lazyVals(enclosingDummyOrMethod) = idx + 1 val rhs1 = mkLazyDef(enclosingDummyOrMethod, super.transform(rhs), idx) - lazyVals(sym.owner) = idx + 1 sym.resetFlag(LAZY | ACCESSOR) rhs1 } else super.transform(rhs) + treeCopy.DefDef(tree, mods, name, tparams, vparams, tpt, - typed(addBitmapDefs(sym, res))) + if (LocalLazyValFinder.find(res)) typed(addBitmapDefs(sym, res)) else res) } case Template(parents, self, body) => atOwner(currentOwner) { @@ -61,9 +84,13 @@ abstract class LazyVals extends Transform with TypingTransformers with ast.TreeD var added = false val stats = for (stat <- body1) yield stat match { - case Block(_, _) if !added => - added = true - typed(addBitmapDefs(sym, stat)) + case Block(_, _) | Apply(_, _) | If(_, _, _) if !added => + // Avoid adding bitmaps when they are fully overshadowed by those + // that are added inside loops + if (LocalLazyValFinder.find(stat)) { + added = true + typed(addBitmapDefs(sym, stat)) + } else stat case ValDef(mods, name, tpt, rhs) => typed(treeCopy.ValDef(stat, mods, name, tpt, addBitmapDefs(stat.symbol, rhs))) case _ => @@ -72,6 +99,29 @@ abstract class LazyVals extends Transform with TypingTransformers with ast.TreeD treeCopy.Template(tree, parents, self, stats) } + case ValDef(mods, name, tpt, rhs0) if (!sym.owner.isModule && !sym.owner.isClass) => + val rhs = super.transform(rhs0) + treeCopy.ValDef(tree, mods, name, tpt, + if (LocalLazyValFinder.find(rhs)) typed(addBitmapDefs(sym, rhs)) else rhs) + + case l@LabelDef(name0, params0, ifp0@If(_, _, _)) if name0.startsWith(nme.WHILE_PREFIX) => + val ifp1 = super.transform(ifp0) + val If(cond0, thenp0, elsep0) = ifp1 + if (LocalLazyValFinder.find(thenp0)) + treeCopy.LabelDef(l, name0, params0, + treeCopy.If(ifp1, cond0, typed(addBitmapDefs(sym.owner, thenp0)), elsep0)) + else + l + + case l@LabelDef(name0, params0, block@Block(stats0, _)) + if name0.startsWith(nme.WHILE_PREFIX) || name0.startsWith(nme.DO_WHILE_PREFIX) => + val stats1 = super.transformTrees(stats0) + if (LocalLazyValFinder.find(stats1)) + treeCopy.LabelDef(l, name0, params0, + treeCopy.Block(block, typed(addBitmapDefs(sym.owner, stats1.head))::stats1.tail, block.expr)) + else + l + case _ => super.transform(tree) } } diff --git a/test/files/pos/t3670.scala b/test/files/pos/t3670.scala new file mode 100644 index 0000000000..ec4fbe5b4f --- /dev/null +++ b/test/files/pos/t3670.scala @@ -0,0 +1,43 @@ +class A { + val n = { + val z = { + lazy val bb = 1 + bb + } + val a = { + lazy val cc = 2 + cc + } + lazy val b = { + lazy val dd = 3 + dd + } + z + } +} + +class B { + locally { + lazy val ms = "as" + ms + } +} + +class C { + val things = List("things") + if(things.size < 100) { + lazy val msg = "foo" + msg + } +} + +class D { + val things = List("things") + if(things.size < 100) { + if (things.size > 10) { + lazy val msg = "foo" + msg + } + } +} + diff --git a/test/files/run/t3670.check b/test/files/run/t3670.check new file mode 100644 index 0000000000..bc49bb6437 --- /dev/null +++ b/test/files/run/t3670.check @@ -0,0 +1,5 @@ +a +b +1 +2 +42 diff --git a/test/files/run/t3670.scala b/test/files/run/t3670.scala new file mode 100644 index 0000000000..a37c3a242c --- /dev/null +++ b/test/files/run/t3670.scala @@ -0,0 +1,31 @@ +class C { + val things = List("abcs") + + if (things.length < 30) { + lazy val a = "a" + println(a) + } + if (things.length < 30) { + lazy val b = "b" + println(b) + } +} + +class M extends Application { + def foo { + lazy val a = { + lazy val b = 1 + lazy val c = 2 + println(b) + println(c) + } + a + lazy val d = 42 + println(d) + } +} + +object Test extends Application { + new C() + new M().foo +}
\ No newline at end of file diff --git a/test/files/run/t3877.check b/test/files/run/t3877.check new file mode 100644 index 0000000000..72aa5577f6 --- /dev/null +++ b/test/files/run/t3877.check @@ -0,0 +1,104 @@ +test1: 3 +test1: 4 +test1: 5 +test1: 6 +test1: 7 +test1: 8 +test1: 9 +test1: 10 +test2: 3 +test2: 4 +test2: 5 +test2: 6 +test2: 7 +test2: 8 +test2: 9 +test2: 10 +test3: 3 +test3: 4 +test3: 5 +test3: 6 +test3: 7 +test3: 8 +test3: 9 +test3: 10 +test4: 3 +test4: 4 +test4: 5 +test4: 6 +test4: 7 +test4: 8 +test4: 9 +test4: 10 +test5.1: 3 +test5.2: 3 +test5.2: 4 +test5.2: 5 +test5.2: 6 +test5.2: 7 +test5.2: 8 +test5.2: 9 +test5.2: 10 +test5.1: 4 +test5.2: 3 +test5.2: 4 +test5.2: 5 +test5.2: 6 +test5.2: 7 +test5.2: 8 +test5.2: 9 +test5.2: 10 +test5.1: 5 +test5.2: 3 +test5.2: 4 +test5.2: 5 +test5.2: 6 +test5.2: 7 +test5.2: 8 +test5.2: 9 +test5.2: 10 +test5.1: 6 +test5.2: 3 +test5.2: 4 +test5.2: 5 +test5.2: 6 +test5.2: 7 +test5.2: 8 +test5.2: 9 +test5.2: 10 +test5.1: 7 +test5.2: 3 +test5.2: 4 +test5.2: 5 +test5.2: 6 +test5.2: 7 +test5.2: 8 +test5.2: 9 +test5.2: 10 +test5.1: 8 +test5.2: 3 +test5.2: 4 +test5.2: 5 +test5.2: 6 +test5.2: 7 +test5.2: 8 +test5.2: 9 +test5.2: 10 +test5.1: 9 +test5.2: 3 +test5.2: 4 +test5.2: 5 +test5.2: 6 +test5.2: 7 +test5.2: 8 +test5.2: 9 +test5.2: 10 +test5.1: 10 +test5.2: 3 +test5.2: 4 +test5.2: 5 +test5.2: 6 +test5.2: 7 +test5.2: 8 +test5.2: 9 +test5.2: 10 diff --git a/test/files/run/t3877.scala b/test/files/run/t3877.scala new file mode 100644 index 0000000000..5710e982a0 --- /dev/null +++ b/test/files/run/t3877.scala @@ -0,0 +1,81 @@ +object Test { + val LIMIT = 10 + + def test1 { + var d = 2 + var i = 0 // avoid infinite loops + while (d < LIMIT && i < LIMIT) { + lazy val b = d + 1 + d = b + i += 1 + println("test1: " + d) + } + } + + def test2 { + var d = 2 + var i = 0 + while (true) { + lazy val b = d + 1 + d = b + i += 1 + println("test2: " + d) + + if (d >= LIMIT || i >= LIMIT) + return + } + } + + def test3 { + var d = 2 + var i = 0 + do { + lazy val b = d + 1 + d = b + i += 1 + println("test3: " + d) + } while (d < LIMIT && i < LIMIT) + } + + def test4 { + var d = 2 + var i = 0 + do { + lazy val b = d + 1 + d = b + i += 1 + println("test4: " + d) + if (d >= LIMIT || i >= LIMIT) + return + } while (true) + } + + def test5 { + var d = 2 + var i = 0 + while (d < LIMIT && i < LIMIT) { + lazy val b = d + 1 + d = b + i += 1 + println("test5.1: " + d) + + var e = 2 + var j = 0 + while (e < LIMIT && j < LIMIT) { + lazy val f = e + 1 + e = f + j += 1 + println("test5.2: " + e) + } + } + } + + + def main(args: Array[String]) { + test1 + test2 + test3 + test4 + test5 + } +} |