diff options
-rw-r--r-- | src/compiler/scala/tools/nsc/ast/TreeInfo.scala | 2 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/backend/opt/DeadCodeElimination.scala | 2 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/transform/Erasure.scala | 8 | ||||
-rw-r--r-- | test/files/run/t4047.check | 5 | ||||
-rw-r--r-- | test/files/run/t4047.scala | 34 |
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 +} |