summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHubert Plociniczak <hubert.plociniczak@epfl.ch>2011-02-24 10:41:37 +0000
committerHubert Plociniczak <hubert.plociniczak@epfl.ch>2011-02-24 10:41:37 +0000
commitb0b63f1901668d0d2acd7de00dd26157f28751f3 (patch)
treea1ec44683918a7ea68f4db9c6a1c9ff1a323386b
parentdd45d81acf8b4e8961406b5b940e1dd70153c2a4 (diff)
downloadscala-b0b63f1901668d0d2acd7de00dd26157f28751f3.tar.gz
scala-b0b63f1901668d0d2acd7de00dd26157f28751f3.tar.bz2
scala-b0b63f1901668d0d2acd7de00dd26157f28751f3.zip
lazy val calls shouldn't be included in pure ex...
lazy val calls shouldn't be included in pure expressions in general. closes 4047. fixed also bug in optimizer (was eliminating a.foo call in the test). review by dragos
-rw-r--r--src/compiler/scala/tools/nsc/ast/TreeInfo.scala2
-rw-r--r--src/compiler/scala/tools/nsc/backend/opt/DeadCodeElimination.scala2
-rw-r--r--src/compiler/scala/tools/nsc/transform/Erasure.scala8
-rw-r--r--test/files/run/t4047.check5
-rw-r--r--test/files/run/t4047.scala34
5 files changed, 45 insertions, 6 deletions
diff --git a/src/compiler/scala/tools/nsc/ast/TreeInfo.scala b/src/compiler/scala/tools/nsc/ast/TreeInfo.scala
index 800b5c2816..8a6f26c9b1 100644
--- a/src/compiler/scala/tools/nsc/ast/TreeInfo.scala
+++ b/src/compiler/scala/tools/nsc/ast/TreeInfo.scala
@@ -87,7 +87,7 @@ abstract class TreeInfo {
* However, before typing, applications of nullary functional values are also
* Apply(function, Nil) trees. To prevent them from being treated as pure,
* we check that the callee is a method. */
- fn.symbol.isMethod && isPureExpr(fn)
+ fn.symbol.isMethod && !fn.symbol.isLazy && isPureExpr(fn)
case Typed(expr, _) =>
isPureExpr(expr)
case Block(stats, expr) =>
diff --git a/src/compiler/scala/tools/nsc/backend/opt/DeadCodeElimination.scala b/src/compiler/scala/tools/nsc/backend/opt/DeadCodeElimination.scala
index 5e58806588..e1774523a5 100644
--- a/src/compiler/scala/tools/nsc/backend/opt/DeadCodeElimination.scala
+++ b/src/compiler/scala/tools/nsc/backend/opt/DeadCodeElimination.scala
@@ -271,7 +271,7 @@ abstract class DeadCodeElimination extends SubComponent {
/** Is 'sym' a side-effecting method? TODO: proper analysis. */
private def isSideEffecting(sym: Symbol): Boolean = {
- !((sym.isGetter && !sym.isLazy)
+ !((sym.isGetter && sym.isFinal && !sym.isLazy)
|| (sym.isConstructor
&& !(sym.owner == method.symbol.owner && method.symbol.isConstructor) // a call to another constructor
&& sym.owner.owner == definitions.RuntimePackage.moduleClass)
diff --git a/src/compiler/scala/tools/nsc/transform/Erasure.scala b/src/compiler/scala/tools/nsc/transform/Erasure.scala
index 70ecea4db5..a9a9180495 100644
--- a/src/compiler/scala/tools/nsc/transform/Erasure.scala
+++ b/src/compiler/scala/tools/nsc/transform/Erasure.scala
@@ -766,15 +766,15 @@ abstract class Erasure extends AddInterfaces
while (opc.hasNext) {
val member = opc.overriding
val other = opc.overridden
- //Console.println("bridge? " + member + ":" + member.tpe + member.locationString + " to " + other + ":" + other.tpe + other.locationString);//DEBUG
+ //Console.println("bridge? " + member + ":" + member.tpe + member.locationString + " to " + other + ":" + other.tpe + other.locationString)//DEBUG
if (atPhase(currentRun.explicitouterPhase)(!member.isDeferred)) {
- val otpe = erasure(other.tpe);
+ val otpe = erasure(other.tpe)
val bridgeNeeded = atPhase(phase.next) (
!(other.tpe =:= member.tpe) &&
!(deconstMap(other.tpe) =:= deconstMap(member.tpe)) &&
{ var e = bridgesScope.lookupEntry(member.name)
while ((e ne null) && !((e.sym.tpe =:= otpe) && (bridgeTarget(e.sym) == member)))
- e = bridgesScope.lookupNextEntry(e);
+ e = bridgesScope.lookupNextEntry(e)
(e eq null)
}
);
@@ -808,7 +808,7 @@ abstract class Erasure extends AddInterfaces
log("generating bridge from " + other + "(" + Flags.flagsToString(bridge.flags) + ")" + ":" + otpe + other.locationString + " to " + member + ":" + erasure(member.tpe) + member.locationString + " =\n " + bridgeDef);
bridgeDef
}
- } :: bridges;
+ } :: bridges
}
}
opc.next
diff --git a/test/files/run/t4047.check b/test/files/run/t4047.check
new file mode 100644
index 0000000000..2a942a70e0
--- /dev/null
+++ b/test/files/run/t4047.check
@@ -0,0 +1,5 @@
+Unit: called A.foo
+Unit: called B.foo
+Unit: called C.foo
+Unit: called D.foo
+Unit: called D.foo
diff --git a/test/files/run/t4047.scala b/test/files/run/t4047.scala
new file mode 100644
index 0000000000..cd42a8b4df
--- /dev/null
+++ b/test/files/run/t4047.scala
@@ -0,0 +1,34 @@
+trait Foo[T] { val foo: T}
+
+class A extends Foo[Unit]{
+ lazy val foo = println("Unit: called A.foo")
+}
+
+class B extends Foo[Unit]{
+ val foo = println("Unit: called B.foo")
+}
+
+trait Bar[T] { def foo: T}
+
+class C extends Bar[Unit]{
+ lazy val foo = println("Unit: called C.foo")
+}
+
+class D extends Bar[Unit]{
+ def foo = println("Unit: called D.foo")
+}
+
+object Test extends Application {
+ val a: Foo[Unit] = new A
+ a.foo
+ a.foo
+ val b: Foo[Unit] = new B
+ b.foo
+ b.foo
+ val c: Bar[Unit] = new C
+ c.foo
+ c.foo
+ val d: Bar[Unit] = new D
+ d.foo
+ d.foo
+}