From 7a57c6eec6c37e8ca3a7f182f0cf2604d7bc80df Mon Sep 17 00:00:00 2001 From: Adriaan Moors Date: Wed, 30 Nov 2016 13:42:36 -0800 Subject: SI-10075 annotations go to lazy val's underlying field This likely regressed in #5294. Review feedback from retronym: - Tie annotation triaging a bit closer together durban kindly provided initial version of test/files/run/t10075.scala And pointed out you must force `lazy val`, since `null`-valued field is serializable regardless of its type. Test test/files/run/t10075b courtesy of retronym --- test/files/run/t10075.scala | 35 ++++++++++++++ test/files/run/t10075b.check | 60 ++++++++++++++++++++++++ test/files/run/t10075b/RetainedAnnotation_1.java | 4 ++ test/files/run/t10075b/Test_2.scala | 56 ++++++++++++++++++++++ 4 files changed, 155 insertions(+) create mode 100644 test/files/run/t10075.scala create mode 100644 test/files/run/t10075b.check create mode 100644 test/files/run/t10075b/RetainedAnnotation_1.java create mode 100644 test/files/run/t10075b/Test_2.scala (limited to 'test') diff --git a/test/files/run/t10075.scala b/test/files/run/t10075.scala new file mode 100644 index 0000000000..e7564c5c8b --- /dev/null +++ b/test/files/run/t10075.scala @@ -0,0 +1,35 @@ +class NotSerializable + +trait SerializableActually { + @transient + lazy val notSerializedTLV: NotSerializable = new NotSerializable + + @transient + val notSerializedTL: NotSerializable = new NotSerializable + + @transient + var notSerializedTR: NotSerializable = new NotSerializable +} + +class SerializableBecauseTransient extends Serializable with SerializableActually { + @transient + lazy val notSerializedLV: NotSerializable = new NotSerializable + + @transient + val notSerializedL: NotSerializable = new NotSerializable + + @transient + var notSerializedR: NotSerializable = new NotSerializable +} + +// Indirectly check that the @transient annotation on `notSerialized` made it to the underyling field in bytecode. +// If it doesn't, `writeObject` will fail to serialize the field `notSerialized`, because `NotSerializable` is not serializable +object Test { + def main(args: Array[String]): Unit = { + val obj = new SerializableBecauseTransient + // must force, since `null` valued field is serialized regardless of its type + val forceTLV = obj.notSerializedTLV + val forceLV = obj.notSerializedLV + new java.io.ObjectOutputStream(new java.io.ByteArrayOutputStream) writeObject obj + } +} diff --git a/test/files/run/t10075b.check b/test/files/run/t10075b.check new file mode 100644 index 0000000000..dc64e95ac7 --- /dev/null +++ b/test/files/run/t10075b.check @@ -0,0 +1,60 @@ + private volatile byte C.bitmap$0 +@RetainedAnnotation() private int C.lzyValFieldAnnotation + public int C.lzyValFieldAnnotation() + private int C.lzyValFieldAnnotation$lzycompute() + private int C.lzyValGetterAnnotation +@RetainedAnnotation() public int C.lzyValGetterAnnotation() + private int C.lzyValGetterAnnotation$lzycompute() +@RetainedAnnotation() private final int C.valFieldAnnotation + public int C.valFieldAnnotation() + private final int C.valGetterAnnotation +@RetainedAnnotation() public int C.valGetterAnnotation() +@RetainedAnnotation() private int C.varFieldAnnotation + public int C.varFieldAnnotation() + public void C.varFieldAnnotation_$eq(int) + private int C.varGetterAnnotation +@RetainedAnnotation() public int C.varGetterAnnotation() + public void C.varGetterAnnotation_$eq(int) + private int C.varSetterAnnotation + public int C.varSetterAnnotation() +@RetainedAnnotation() public void C.varSetterAnnotation_$eq(int) + public static void T.$init$(T) + public abstract void T.T$_setter_$valFieldAnnotation_$eq(int) + public abstract void T.T$_setter_$valGetterAnnotation_$eq(int) + public default int T.lzyValFieldAnnotation() + public static int T.lzyValFieldAnnotation$(T) +@RetainedAnnotation() public default int T.lzyValGetterAnnotation() + public static int T.lzyValGetterAnnotation$(T) +@RetainedAnnotation() public default int T.method() + public static int T.method$(T) + public abstract int T.valFieldAnnotation() +@RetainedAnnotation() public abstract int T.valGetterAnnotation() + public abstract int T.varFieldAnnotation() + public abstract void T.varFieldAnnotation_$eq(int) +@RetainedAnnotation() public abstract int T.varGetterAnnotation() + public abstract void T.varGetterAnnotation_$eq(int) + public abstract int T.varSetterAnnotation() +@RetainedAnnotation() public abstract void T.varSetterAnnotation_$eq(int) + public void TMix.T$_setter_$valFieldAnnotation_$eq(int) + public void TMix.T$_setter_$valGetterAnnotation_$eq(int) + private volatile byte TMix.bitmap$0 +@RetainedAnnotation() private int TMix.lzyValFieldAnnotation + public int TMix.lzyValFieldAnnotation() + private int TMix.lzyValFieldAnnotation$lzycompute() + private int TMix.lzyValGetterAnnotation +@RetainedAnnotation() public int TMix.lzyValGetterAnnotation() + private int TMix.lzyValGetterAnnotation$lzycompute() +@RetainedAnnotation() public int TMix.method() +@RetainedAnnotation() private final int TMix.valFieldAnnotation + public int TMix.valFieldAnnotation() + private final int TMix.valGetterAnnotation +@RetainedAnnotation() public int TMix.valGetterAnnotation() +@RetainedAnnotation() private int TMix.varFieldAnnotation + public int TMix.varFieldAnnotation() + public void TMix.varFieldAnnotation_$eq(int) + private int TMix.varGetterAnnotation +@RetainedAnnotation() public int TMix.varGetterAnnotation() + public void TMix.varGetterAnnotation_$eq(int) + private int TMix.varSetterAnnotation + public int TMix.varSetterAnnotation() +@RetainedAnnotation() public void TMix.varSetterAnnotation_$eq(int) diff --git a/test/files/run/t10075b/RetainedAnnotation_1.java b/test/files/run/t10075b/RetainedAnnotation_1.java new file mode 100644 index 0000000000..86ac939ec7 --- /dev/null +++ b/test/files/run/t10075b/RetainedAnnotation_1.java @@ -0,0 +1,4 @@ +import java.lang.annotation.*; + +@Retention(RetentionPolicy.RUNTIME) +@interface RetainedAnnotation { } diff --git a/test/files/run/t10075b/Test_2.scala b/test/files/run/t10075b/Test_2.scala new file mode 100644 index 0000000000..89ba2bd488 --- /dev/null +++ b/test/files/run/t10075b/Test_2.scala @@ -0,0 +1,56 @@ +class C { + @(RetainedAnnotation @annotation.meta.field) + lazy val lzyValFieldAnnotation = 42 + + @(RetainedAnnotation @annotation.meta.getter) + lazy val lzyValGetterAnnotation = 42 + + @(RetainedAnnotation @annotation.meta.field) + val valFieldAnnotation = 42 + + @(RetainedAnnotation @annotation.meta.getter) + val valGetterAnnotation = 42 + + @(RetainedAnnotation @annotation.meta.field) + var varFieldAnnotation = 42 + + @(RetainedAnnotation @annotation.meta.getter) + var varGetterAnnotation = 42 + + @(RetainedAnnotation @annotation.meta.setter) + var varSetterAnnotation = 42 +} + +trait T { + @(RetainedAnnotation @annotation.meta.field) + lazy val lzyValFieldAnnotation = 42 + + @(RetainedAnnotation @annotation.meta.getter) + lazy val lzyValGetterAnnotation = 42 + + @(RetainedAnnotation @annotation.meta.field) + val valFieldAnnotation = 42 + + @(RetainedAnnotation @annotation.meta.getter) + val valGetterAnnotation = 42 + + @(RetainedAnnotation @annotation.meta.field) + var varFieldAnnotation = 42 + + @(RetainedAnnotation @annotation.meta.getter) + var varGetterAnnotation = 42 + + @(RetainedAnnotation @annotation.meta.setter) + var varSetterAnnotation = 42 + + @RetainedAnnotation + def method = 42 +} +class TMix extends T + +object Test extends App { + (List(classOf[C], classOf[T], classOf[TMix]). + flatMap(cls => cls.getDeclaredFields ++ cls.getDeclaredMethods)). + sortBy(x => (x.getDeclaringClass.getName, x.getName, x.toString)). + foreach(x => println(x.getAnnotations.toList.mkString(" ") + " " + x)) +} \ No newline at end of file -- cgit v1.2.3