summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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
+}