From 1b6661b8b586637ba5d54510c7bda1144acab23b Mon Sep 17 00:00:00 2001 From: James Iry Date: Wed, 20 Feb 2013 15:31:32 -0800 Subject: SI-7015 Removes redundant aconst_null; pop; aconst_null creation In an effort to adapt methods and field accesses of type Null to other types, we were always emitting aconst_null pop aconst_null The problem is we were doing that even when the JVM was in a position to know it had null value, e.g. when the user had written a null constant. This commit fixes that and includes a test to show that the resulting byte code still works even without repeating ourselves and/or repeating ourselves. This commit also makes the scala.runtim.Null$ constructor private. It was a sealed abstract class which prevented subclassing in Scala, but it didn't prevent subclassing in Java. A private constructor takes care of that hole so now the only value of type Null$ should be null. Along the way I found some other questionable things in adapt and I've added TODO's and issue https://issues.scala-lang.org/browse/SI-7159 to track. --- test/files/run/t7015.check | 11 +++++++++++ test/files/run/t7015.scala | 49 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+) create mode 100644 test/files/run/t7015.check create mode 100644 test/files/run/t7015.scala (limited to 'test/files') diff --git a/test/files/run/t7015.check b/test/files/run/t7015.check new file mode 100644 index 0000000000..7651fe06b0 --- /dev/null +++ b/test/files/run/t7015.check @@ -0,0 +1,11 @@ +Method returns Null type: null +Method takes non Null type: null +call through method null +call through bridge null +fetch field: null +fetch field on companion: null +fetch local: null +fetch array element: null +method that takes object: null +method that takes anyref: null +method that takes any: null diff --git a/test/files/run/t7015.scala b/test/files/run/t7015.scala new file mode 100644 index 0000000000..9344ca2906 --- /dev/null +++ b/test/files/run/t7015.scala @@ -0,0 +1,49 @@ +object Test { + def main(args : Array[String]) : Unit = { + println(s"Method returns Null type: $f") + println(s"Method takes non Null type: ${g(null)}") + + // pass things through the g function because it expects + // a string. If we haven't adapted properly then we'll + // get verify errors + val b = new B + println(s"call through method ${g(b.f(null))}") + println(s"call through bridge ${g((b: A).f(null))}") + + println(s"fetch field: ${g(b.nullField)}") + println(s"fetch field on companion: ${g(B.nullCompanionField)}") + + val x = f + println(s"fetch local: ${g(x)}") + + val nulls = Array(f, f, f) + println(s"fetch array element: ${g(nulls(0))}") + + println(s"method that takes object: ${q(f)}") + println(s"method that takes anyref: ${r(f)}") + println(s"method that takes any: ${s(f)}") + } + + def f = null + + def g(x: String) = x + + def q(x: java.lang.Object) = x + def r(x: AnyRef) = x + def s(x: Any) = x +} + +abstract class A { + def f(x: String): String +} + +class B extends A { + val nullField = null + + // this forces a bridge method because the return type is different + override def f(x: String) : Null = null +} + +object B { + val nullCompanionField = null +} \ No newline at end of file -- cgit v1.2.3 From 62fcd3d922056407703ac3363b897f82980b0926 Mon Sep 17 00:00:00 2001 From: James Iry Date: Fri, 22 Feb 2013 09:17:30 -0800 Subject: SI-7015 Cleanup from review of null duplication Based on feedback on https://github.com/scala/scala/pull/2147 * Assertion in GenICode#adaptNullRef reports the erroneous type * Test makes the Null type explicit for greater clarity --- src/compiler/scala/tools/nsc/backend/icode/GenICode.scala | 2 +- test/files/run/t7015.scala | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'test/files') diff --git a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala index 439bb74267..7e17495035 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala @@ -1025,7 +1025,7 @@ abstract class GenICode extends SubComponent { // this value into a local of type Null and we want the JVM to see that it's // a null value so we don't have to also adapt local loads. if (from == NullReference && to != UNIT && to != ObjectReference && to != AnyRefReference) { - assert(to.isReferenceType, "Attempt to adapt a null to a non reference type") + assert(to.isReferenceType, "Attempt to adapt a null to a non reference type $to.") // adapt by dropping what we've got and pushing a null which // will convince the JVM we really do have null ctx.bb.emit(DROP(from), pos) diff --git a/test/files/run/t7015.scala b/test/files/run/t7015.scala index 9344ca2906..37a73a9fc4 100644 --- a/test/files/run/t7015.scala +++ b/test/files/run/t7015.scala @@ -24,7 +24,7 @@ object Test { println(s"method that takes any: ${s(f)}") } - def f = null + def f: Null = null def g(x: String) = x -- cgit v1.2.3