summaryrefslogtreecommitdiff
path: root/test/files/run/t720.scala
diff options
context:
space:
mode:
authorJason Zaugg <jzaugg@gmail.com>2015-07-27 15:33:30 +1000
committerJason Zaugg <jzaugg@gmail.com>2015-07-27 16:05:06 +1000
commit0c99742c51706ee4b60a56a8f5babb13682f9b10 (patch)
tree52ed40408595538c74da8f0fa8c8e6effc18875c /test/files/run/t720.scala
parent0e9525aa618a2eca143a1c7379ff1e6efd23b86e (diff)
downloadscala-0c99742c51706ee4b60a56a8f5babb13682f9b10.tar.gz
scala-0c99742c51706ee4b60a56a8f5babb13682f9b10.tar.bz2
scala-0c99742c51706ee4b60a56a8f5babb13682f9b10.zip
SI-9365 Don't null out dependencies of transient lazy vals
As per Iulian's analysis: > When lazy vals are transient, the optimization in SI-720 is invalid, > leading to NPEs. These NPEs appear when recomputing the lazy val when deserializaing the object. This commit disables the field nulling if the lazy val is marked transient. The post-mixin tree in the enclosed test changes as follows: ``` --- sandbox/old.log 2015-07-27 15:48:03.000000000 +1000 +++ sandbox/new.log 2015-07-27 15:47:56.000000000 +1000 @@ -1,61 +1,54 @@ [[syntax trees at end of mixin]] // t9365.scala package <empty> { class Test extends Object with Serializable { @transient @volatile private[this] var bitmap$trans$0: Boolean = false; private def foo$lzycompute(): Object = { { Test.this.synchronized({ if (Test.this.bitmap$trans$0.unary_!()) { Test.this.foo = Test.this.x.apply(); Test.this.bitmap$trans$0 = true; () }; scala.runtime.BoxedUnit.UNIT }); - Test.this.x = null + () }; Test.this.foo }; ``` In addition to the test from the ticket, I've added a reflection based test that directly tests the nulling. This complements the test added in 449f2a7473, the fix for SI-720, which passes by virtue of not exhausting the heap.
Diffstat (limited to 'test/files/run/t720.scala')
-rw-r--r--test/files/run/t720.scala48
1 files changed, 48 insertions, 0 deletions
diff --git a/test/files/run/t720.scala b/test/files/run/t720.scala
new file mode 100644
index 0000000000..a5cb2495cf
--- /dev/null
+++ b/test/files/run/t720.scala
@@ -0,0 +1,48 @@
+class Lazy(f: => Int) {
+ lazy val get: Int = f
+}
+
+class UsedLater(f: => Int) {
+ lazy val get: Int = f
+ def other = f
+}
+
+class TransientLazy(f: => Int) {
+ @transient
+ lazy val get: Int = f
+}
+
+object Test {
+ def main(args: Array[String]): Unit = {
+ testLazy()
+ testUsedLater()
+ }
+
+ def testLazy() {
+ val o = new Lazy("".length)
+ val f = classOf[Lazy].getDeclaredField("f")
+ f.setAccessible(true)
+ assert(f.get(o) != null)
+ o.get
+ assert(f.get(o) == null)
+ }
+
+ def testUsedLater() {
+ val o = new UsedLater("".length)
+ val f = classOf[UsedLater].getDeclaredField("f")
+ f.setAccessible(true)
+ assert(f.get(o) != null)
+ o.get
+ assert(f.get(o) != null)
+ }
+
+ def testTransientLazy() {
+ val o = new TransientLazy("".length)
+ val f = classOf[TransientLazy].getDeclaredField("f")
+ f.setAccessible(true)
+ assert(f.get(o) != null)
+ o.get
+ assert(f.get(o) != null) // SI-9365
+ }
+}
+