summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/compiler/scala/tools/nsc/symtab/StdNames.scala13
-rw-r--r--src/compiler/scala/tools/nsc/transform/Mixin.scala100
-rw-r--r--src/library/scala/collection/mutable/FlatHashTable.scala1
-rw-r--r--src/library/scala/collection/mutable/HashTable.scala3
-rw-r--r--src/library/scala/collection/mutable/LinkedHashMap.scala2
-rw-r--r--test/files/jvm/serialization.check4
-rw-r--r--test/files/jvm/serialization.scala30
-rw-r--r--test/files/run/t3038.check19
-rw-r--r--test/files/run/t3038.scala68
-rw-r--r--test/files/run/t3038b.flags1
-rw-r--r--test/files/run/t3038b.scala20
-rw-r--r--test/files/run/t3038c.check2
-rw-r--r--test/files/run/t3038c/A_1.scala83
-rw-r--r--test/files/run/t3038c/B_2.scala24
-rw-r--r--test/files/run/t3038d.flags1
-rw-r--r--test/files/run/t3038d.scala60
-rw-r--r--test/files/run/t3895.scala6
17 files changed, 405 insertions, 32 deletions
diff --git a/src/compiler/scala/tools/nsc/symtab/StdNames.scala b/src/compiler/scala/tools/nsc/symtab/StdNames.scala
index e0158ecec0..10c5d69371 100644
--- a/src/compiler/scala/tools/nsc/symtab/StdNames.scala
+++ b/src/compiler/scala/tools/nsc/symtab/StdNames.scala
@@ -198,8 +198,17 @@ trait StdNames extends reflect.generic.StdNames { self: SymbolTable =>
/** The name of a setter for protected symbols. Used for inherited Java fields. */
def protSetterName(name: Name): Name = newTermName(PROTECTED_PREFIX + "set" + name)
- /** The name of bitmaps for initialized lazy vals. */
- def bitmapName(n: Int): Name = newTermName("bitmap$" + n)
+ private def bitmapName(n: Int, suffix: String): Name = newTermName("bitmap$" + suffix + n)
+
+ /** The name of bitmaps for initialized (public or protected) lazy vals. */
+ def bitmapName(n: Int): Name = bitmapName(n, "")
+
+ /** The name of bitmaps for initialized transitive lazy vals. */
+ def bitmapNameForTransitive(n: Int): Name = bitmapName(n, "trans$")
+
+ /** The name of bitmaps for initialized private lazy vals. */
+ def bitmapNameForPrivate(n: Int): Name = bitmapName(n, "priv$")
+
/** The label prefixes for generated while and do loops. */
val WHILE_PREFIX = "while$"
diff --git a/src/compiler/scala/tools/nsc/transform/Mixin.scala b/src/compiler/scala/tools/nsc/transform/Mixin.scala
index e1e4375378..3d4c41ed93 100644
--- a/src/compiler/scala/tools/nsc/transform/Mixin.scala
+++ b/src/compiler/scala/tools/nsc/transform/Mixin.scala
@@ -646,30 +646,59 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL {
import lazyVals._
+ def bitmapOperation[T](field: Symbol, transientCase: => T, privateCase: => T, rest: => T): T =
+ if (field.accessed.hasAnnotation(TransientAttr))
+ transientCase
+ else if (field.hasFlag(PRIVATE))
+ privateCase
+ else
+ rest
+
+ /**
+ * Private or transient lazy vals use bitmaps that are private for the class context,
+ * unlike public or protected vals, which can use inherited bitmaps.
+ */
+ def localBitmapField(field: Symbol) =
+ field.accessed.hasAnnotation(TransientAttr) || field.hasFlag(PRIVATE)
+
/**
* Return the bitmap field for 'offset'. Depending on the hierarchy it is possible to reuse
* the bitmap of its parents. If that does not exist yet we create one.
*/
- def bitmapFor(clazz0: Symbol, offset: Int, searchParents:Boolean = true): Symbol = {
+ def bitmapFor(clazz0: Symbol, offset: Int, field: Symbol, searchParents:Boolean = true): Symbol = {
+ def bitmapName: Name =
+ bitmapOperation(field, nme.bitmapNameForTransitive(offset / FLAGS_PER_WORD),
+ nme.bitmapNameForPrivate(offset / FLAGS_PER_WORD),
+ nme.bitmapName(offset / FLAGS_PER_WORD))
def createBitmap: Symbol = {
- val sym = clazz0.newVariable(clazz0.pos, nme.bitmapName(offset / FLAGS_PER_WORD))
+ val sym = clazz0.newVariable(clazz0.pos, bitmapName)
.setInfo(IntClass.tpe)
- .setFlag(PROTECTED)
atPhase(currentRun.typerPhase) {
sym addAnnotation AnnotationInfo(VolatileAttr.tpe, Nil, Nil)
}
+
+ bitmapOperation(field,
+ {sym.addAnnotation(AnnotationInfo(TransientAttr.tpe, Nil, Nil)); sym.setFlag(PRIVATE | LOCAL)},
+ sym.setFlag(PRIVATE | LOCAL), sym.setFlag(PROTECTED))
+
clazz0.info.decls.enter(sym)
if (clazz0 == clazz)
addDef(clazz.pos, VAL(sym) === ZERO)
- else
+ else {
+ //FIXME: the assertion below will not work because of the way bitmaps are added.
+ // They should be added during inforTransform, so that in separate compilation, bitmap
+ // is a member of clazz and doesn't fail the condition couple lines below.
+ // This works, as long as we assume that the previous classes were compiled correctly.
+ //assert(clazz0.sourceFile != null)
addDeferredBitmap(clazz0, VAL(sym) === ZERO)
+ }
sym
}
- var sym = clazz0.info.member(nme.bitmapName(offset / FLAGS_PER_WORD))
+ var sym = clazz0.info.member(bitmapName)
assert(!sym.hasFlag(OVERLOADED))
if (sym == NoSymbol) {
- if (searchParents)
- bitmapForParents(clazz0, offset) match {
+ if (searchParents && !localBitmapField(field))
+ bitmapForParents(clazz0, offset, field) match {
case Some(bitmap) =>
sym = bitmap
case None =>
@@ -678,26 +707,26 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL {
else
sym = createBitmap
}
- //assert(sym != NoSymbol)
sym
}
- def bitmapForParents(clazz0: Symbol, offset: Int): Option[Symbol] = {
+ def bitmapForParents(clazz0: Symbol, offset: Int, valSym: Symbol): Option[Symbol] = {
def requiredBitmaps(fs: Int): Int = if (fs == 0) -1 else (fs - 1) / FLAGS_PER_WORD
var res:Option[Symbol] = None
val bitmapNum = offset / FLAGS_PER_WORD
+
+ // filter private and transient
// on what else should we filter?
for (cl <- clazz0.info.baseClasses.tail.filter(c => !c.isTrait && !c.hasFlag(JAVA))
if res == None) {
val fields0 = usedBits(cl)
if (requiredBitmaps(fields0) < bitmapNum) {
- val fields1 = cl.info.decls.filter(fieldWithBitmap).size
+ val fields1 = cl.info.decls.filter(decl => fieldWithBitmap(decl) && !localBitmapField(decl)).size
if (requiredBitmaps(fields0 + fields1) >= bitmapNum)
- // assert(cl.sourceFile != null)
- res = Some(bitmapFor(cl, offset, false))
+ res = Some(bitmapFor(cl, offset, valSym, false))
else return None // Don't waste time, since we won't find bitmap anyway
}
}
@@ -705,8 +734,8 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL {
}
/** Return an (untyped) tree of the form 'Clazz.this.bmp = Clazz.this.bmp | mask'. */
- def mkSetFlag(clazz: Symbol, offset: Int): Tree = {
- val bmp = bitmapFor(clazz, offset)
+ def mkSetFlag(clazz: Symbol, offset: Int, valSym: Symbol): Tree = {
+ val bmp = bitmapFor(clazz, offset, valSym)
val mask = LIT(1 << (offset % FLAGS_PER_WORD))
def x = This(clazz) DOT bmp
@@ -754,19 +783,19 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL {
Select(This(clazz), sym1) === LIT(null)
}
- val bitmapSym = bitmapFor(clazz, offset)
+ val bitmapSym = bitmapFor(clazz, offset, lzyVal)
val mask = LIT(1 << (offset % FLAGS_PER_WORD))
def cond = mkTest(clazz, mask, bitmapSym, true)
val nulls = (lazyValNullables(lzyVal).toList sortBy (_.id) map nullify)
- def syncBody = init ::: List(mkSetFlag(clazz, offset), UNIT)
+ def syncBody = init ::: List(mkSetFlag(clazz, offset, lzyVal), UNIT)
log("nulling fields inside " + lzyVal + ": " + nulls)
val result = gen.mkDoubleCheckedLocking(clazz, cond, syncBody, nulls)
typedPos(init.head.pos)(BLOCK(result, retVal))
}
- def mkCheckedAccessor(clazz: Symbol, retVal: Tree, offset: Int, pos: Position): Tree = {
- val bitmapSym = bitmapFor(clazz, offset)
+ def mkCheckedAccessor(clazz: Symbol, retVal: Tree, offset: Int, pos: Position, fieldSym: Symbol): Tree = {
+ val bitmapSym = bitmapFor(clazz, offset, fieldSym.getter(fieldSym.owner))
val mask = LIT(1 << (offset % FLAGS_PER_WORD))
val msg = "Uninitialized field: " + unit.source + ": " + pos.line
val result =
@@ -798,8 +827,7 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL {
case DefDef(mods, name, tp, vp, tpt, rhs)
if needsInitFlag(sym) && rhs != EmptyTree && !clazz.isImplClass && !clazz.isTrait =>
assert(fieldOffset.isDefinedAt(sym))
-
- val rhs1 = (mkCheckedAccessor(clazz, _: Tree, fieldOffset(sym), stat.pos))(
+ val rhs1 = (mkCheckedAccessor(clazz, _: Tree, fieldOffset(sym), stat.pos, sym))(
if (sym.tpe.resultType.typeSymbol == UnitClass) UNIT else rhs
)
treeCopy.DefDef(stat, mods, name, tp, vp, tpt, rhs1)
@@ -807,6 +835,15 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL {
case DefDef(mods, name, tp, vp, tpt, rhs) if sym.isConstructor =>
treeCopy.DefDef(stat, mods, name, tp, vp, tpt, addInitBits(clazz, rhs))
+ case DefDef(mods, name, tp, vp, tpt, rhs)
+ if settings.checkInit.value && !clazz.isTrait && sym.isSetter =>
+ val getter = sym.getter(clazz)
+ if (needsInitFlag(getter) && fieldOffset.isDefinedAt(getter))
+ treeCopy.DefDef(stat, mods, name, tp, vp, tpt,
+ Block(List(rhs, localTyper.typed(mkSetFlag(clazz, fieldOffset(getter), getter))), UNIT))
+ else
+ stat
+
case _ => stat
}
stats1
@@ -847,7 +884,7 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL {
List()
else if (sym != NoSymbol && needsInitFlag(sym) && fieldOffset.isDefinedAt(sym)) {
log("adding checked getter for: " + sym + " " + Flags.flagsToString(lhs.symbol.flags))
- List(stat, localTyper.typed(mkSetFlag(clazz, fieldOffset(sym))))
+ List(stat, localTyper.typed(mkSetFlag(clazz, fieldOffset(sym), sym)))
} else {
List(stat)
}
@@ -877,10 +914,9 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL {
def needsBitmap(field: Symbol) =
field.owner != clazz0 &&
fieldWithBitmap(field)
-
val fs = for {
cl <- clazz0.info.baseClasses.tail.filter(cl => !cl.isTrait && !cl.hasFlag(JAVA))
- field <- cl.info.decls.iterator.toList if needsBitmap(field)
+ field <- cl.info.decls.iterator.toList if needsBitmap(field) && !localBitmapField(field)
} yield field
fs.length
}
@@ -891,11 +927,16 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL {
*/
def buildFieldPositions(clazz0: Symbol) {
var fields = usedBits(clazz0)
+ var fieldsPrivate = 0
+ var fieldsTransient = 0
for (f <- clazz0.info.decls.iterator if fieldWithBitmap(f)) {
if (settings.debug.value) log(f.fullName + " -> " + fields)
- fieldOffset(f) = fields
- fields += 1
+ val (idx, _) =
+ bitmapOperation(f, (fieldsTransient, fieldsTransient += 1),
+ (fieldsPrivate, fieldsPrivate += 1),
+ (fields, fields += 1))
+ fieldOffset(f) = idx
}
}
@@ -959,13 +1000,14 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL {
case Literal(_) => accessedRef
case _ =>
val init = Assign(accessedRef, Ident(vparams.head))
- if (settings.checkInit.value && needsInitFlag(sym.getter(clazz))) {
- Block(List(init, mkSetFlag(clazz, fieldOffset(sym.getter(clazz)))), UNIT)
- } else
+ val getter = sym.getter(clazz)
+ if (settings.checkInit.value && needsInitFlag(getter))
+ Block(List(init, mkSetFlag(clazz, fieldOffset(getter), getter)), UNIT)
+ else
init
}
} else if (!sym.hasFlag(LAZY) && needsInitFlag(sym)) {
- mkCheckedAccessor(clazz, accessedRef, fieldOffset(sym), sym.pos)
+ mkCheckedAccessor(clazz, accessedRef, fieldOffset(sym), sym.pos, sym)
} else
gen.mkCheckInit(accessedRef)
})
diff --git a/src/library/scala/collection/mutable/FlatHashTable.scala b/src/library/scala/collection/mutable/FlatHashTable.scala
index d46c59173b..aa2cd2deba 100644
--- a/src/library/scala/collection/mutable/FlatHashTable.scala
+++ b/src/library/scala/collection/mutable/FlatHashTable.scala
@@ -65,6 +65,7 @@ trait FlatHashTable[A] {
assert(_loadFactor > 0)
val size = in.readInt
+ tableSize = 0
assert(size >= 0)
table = new Array(capacity(size * loadFactorDenum / _loadFactor))
diff --git a/src/library/scala/collection/mutable/HashTable.scala b/src/library/scala/collection/mutable/HashTable.scala
index c233bd2719..ceb6d6e0e8 100644
--- a/src/library/scala/collection/mutable/HashTable.scala
+++ b/src/library/scala/collection/mutable/HashTable.scala
@@ -62,6 +62,7 @@ trait HashTable[A, Entry >: Null <: HashEntry[A, Entry]] extends HashTable.HashU
assert(_loadFactor > 0)
val size = in.readInt
+ tableSize = 0
assert(size >= 0)
val smDefined = in.readBoolean
@@ -69,7 +70,7 @@ trait HashTable[A, Entry >: Null <: HashEntry[A, Entry]] extends HashTable.HashU
table = new Array(capacity(sizeForThreshold(_loadFactor, size)))
threshold = newThreshold(_loadFactor, table.size)
- if (smDefined) sizeMapInit(table.size)
+ if (smDefined) sizeMapInit(table.size) else sizemap = null
var index = 0
while (index < size) {
diff --git a/src/library/scala/collection/mutable/LinkedHashMap.scala b/src/library/scala/collection/mutable/LinkedHashMap.scala
index 203adcc966..f52aebed81 100644
--- a/src/library/scala/collection/mutable/LinkedHashMap.scala
+++ b/src/library/scala/collection/mutable/LinkedHashMap.scala
@@ -140,6 +140,8 @@ class LinkedHashMap[A, B] extends Map[A, B]
}
private def readObject(in: java.io.ObjectInputStream) {
+ firstEntry = null
+ lastEntry = null
init[B](in, { (key, value) =>
val entry = new Entry(key, value)
updateLinkedEntries(entry)
diff --git a/test/files/jvm/serialization.check b/test/files/jvm/serialization.check
index 5713c3881e..bfd25301bb 100644
--- a/test/files/jvm/serialization.check
+++ b/test/files/jvm/serialization.check
@@ -263,3 +263,7 @@ x = Paul
y = Paul
x equals y: true, y equals x: true
+1
+2
+1
+2 \ No newline at end of file
diff --git a/test/files/jvm/serialization.scala b/test/files/jvm/serialization.scala
index 2db13c76fd..0c33ab7df8 100644
--- a/test/files/jvm/serialization.scala
+++ b/test/files/jvm/serialization.scala
@@ -557,6 +557,35 @@ object Test7 {
}
+
+// Verify that transient lazy vals don't get serialized
+@serializable
+class WithTransient {
+ @transient lazy val a1 = 1
+ @transient private lazy val a2 = 2
+ @transient @serializable object B
+
+ def test = {
+ println(a1)
+ println(a2)
+ if (B == null)
+ println("Transient nested object failed to serialize properly")
+ }
+}
+
+object Test8 {
+ val x = new WithTransient
+ x.test
+ try {
+ val y:WithTransient = read(write(x))
+ y.test
+ }
+ catch {
+ case e: Exception =>
+ println("Error in Test8: " + e)
+ }
+}
+
//############################################################################
// Test code
@@ -569,6 +598,7 @@ object Test {
Test5
Test6
Test7
+ Test8
}
}
diff --git a/test/files/run/t3038.check b/test/files/run/t3038.check
new file mode 100644
index 0000000000..9a325c4c18
--- /dev/null
+++ b/test/files/run/t3038.check
@@ -0,0 +1,19 @@
+a1
+a2
+a3
+a4
+a5
+a6
+a7
+a8
+a9
+c1
+c2
+c3
+c4
+c5
+c6
+c7
+c8
+c9
+c10
diff --git a/test/files/run/t3038.scala b/test/files/run/t3038.scala
new file mode 100644
index 0000000000..cf26001beb
--- /dev/null
+++ b/test/files/run/t3038.scala
@@ -0,0 +1,68 @@
+class A {
+ private lazy val a1 = "a1"
+ object B
+ private lazy val a2 = "a2"
+
+
+ @transient lazy val a3 = "a3"
+ @transient private lazy val a4 = "a4"
+ @transient lazy val a5 = "a5"
+ @transient private lazy val a6 = "a6"
+
+ final val a7 = "a7"
+ private final val a8 = "a8"
+ @transient final val a9 = "a9"
+
+
+
+
+ def run = {
+ println(a1)
+ B
+ println(a2)
+ println(a3)
+ println(a4)
+ println(a5)
+ println(a6)
+ println(a7)
+ println(a8)
+ println(a9)
+ }
+}
+
+class C extends A {
+ private lazy val c1 = "c1"
+ lazy val c2 = "c2"
+
+ private lazy val c3 = "c3"
+
+ @transient lazy val c4 = "c4"
+ @transient private lazy val c5 = "c5"
+ @transient lazy val c6 = "c6"
+ @transient private lazy val c7 = "c7"
+ lazy val c8 = "c8"
+
+ final val c9 = "c9"
+ private final val c10 = "c10"
+
+
+
+ override def run = {
+ super.run
+ println(c1)
+ println(c2)
+ println(c3)
+ println(c4)
+ println(c5)
+ println(c6)
+ println(c7)
+ println(c8)
+ println(c9)
+ println(c10)
+ }
+}
+
+object Test extends Application {
+ (new C).run
+}
+
diff --git a/test/files/run/t3038b.flags b/test/files/run/t3038b.flags
new file mode 100644
index 0000000000..ae08446055
--- /dev/null
+++ b/test/files/run/t3038b.flags
@@ -0,0 +1 @@
+-Xcheckinit \ No newline at end of file
diff --git a/test/files/run/t3038b.scala b/test/files/run/t3038b.scala
new file mode 100644
index 0000000000..5237ee941e
--- /dev/null
+++ b/test/files/run/t3038b.scala
@@ -0,0 +1,20 @@
+class A {
+ val a1 = 1
+ val a2 = 2
+ private val b1 = 3
+ private val b2 = 4
+ @transient val c1 = 5
+ @transient val c2 = 6
+ def run = {
+ a1
+ a2
+ b1
+ b2
+ c1
+ c2
+ }
+}
+
+object Test extends Application {
+ new A().run
+} \ No newline at end of file
diff --git a/test/files/run/t3038c.check b/test/files/run/t3038c.check
new file mode 100644
index 0000000000..a7e7ae9bda
--- /dev/null
+++ b/test/files/run/t3038c.check
@@ -0,0 +1,2 @@
+List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70)
+List(71, 72, 73, 74, 75, 76, 77, 78, 79, 80)
diff --git a/test/files/run/t3038c/A_1.scala b/test/files/run/t3038c/A_1.scala
new file mode 100644
index 0000000000..91564e3021
--- /dev/null
+++ b/test/files/run/t3038c/A_1.scala
@@ -0,0 +1,83 @@
+class A {
+ lazy val a0 = 1
+ lazy val a1 = 2
+ lazy val a2 = 3
+ lazy val a3 = 4
+ lazy val a4 = 5
+ lazy val a5 = 6
+ lazy val a6 = 7
+ lazy val a7 = 8
+ lazy val a8 = 9
+ lazy val a9 = 10
+ lazy val a10 = 11
+ lazy val a11 = 12
+ lazy val a12 = 13
+ lazy val a13 = 14
+ lazy val a14 = 15
+ lazy val a15 = 16
+ lazy val a16 = 17
+ lazy val a17 = 18
+ lazy val a18 = 19
+ lazy val a19 = 20
+ lazy val a20 = 21
+ lazy val a21 = 22
+ lazy val a22 = 23
+ lazy val a23 = 24
+ lazy val a24 = 25
+ lazy val a25 = 26
+ lazy val a26 = 27
+ lazy val a27 = 28
+ lazy val a28 = 29
+ lazy val a29 = 30
+ lazy val a30 = 31
+ lazy val a31 = 32
+ lazy val a32 = 33
+ lazy val a33 = 34
+ lazy val a34 = 35
+ lazy val a35 = 36
+ lazy val a36 = 37
+ lazy val a37 = 38
+ lazy val a38 = 39
+ lazy val a39 = 40
+ lazy val a40 = 41
+ lazy val a41 = 42
+ lazy val a42 = 43
+ lazy val a43 = 44
+ lazy val a44 = 45
+ lazy val a45 = 46
+ lazy val a46 = 47
+ lazy val a47 = 48
+ lazy val a48 = 49
+ lazy val a49 = 50
+ lazy val a50 = 51
+ lazy val a51 = 52
+ lazy val a52 = 53
+ lazy val a53 = 54
+ lazy val a54 = 55
+ lazy val a55 = 56
+ lazy val a56 = 57
+ lazy val a57 = 58
+ lazy val a58 = 59
+ lazy val a59 = 60
+ private lazy val a60 = 61
+ private lazy val a61 = 62
+ private lazy val a62 = 63
+ private lazy val a63 = 64
+ private lazy val a64 = 65
+ private lazy val a65 = 66
+ private lazy val a66 = 67
+ private lazy val a67 = 68
+ private lazy val a68 = 69
+ private lazy val a69 = 70
+
+ def run = {
+ println(List(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, a13, a14, a15, a16, a17, a18, a19,
+ a20, a21, a22, a23, a24, a25, a26, a27, a28, a29,
+ a30, a31, a32, a33, a34, a35, a36, a37, a38, a39,
+ a40, a41, a42, a43, a44, a45, a46, a47, a48, a49,
+ a50, a51, a52, a53, a54, a55, a56, a57, a58, a59,
+ a60, a61, a62, a63, a64, a65, a66, a67, a68, a69))
+ }
+
+}
diff --git a/test/files/run/t3038c/B_2.scala b/test/files/run/t3038c/B_2.scala
new file mode 100644
index 0000000000..81f3f8d481
--- /dev/null
+++ b/test/files/run/t3038c/B_2.scala
@@ -0,0 +1,24 @@
+
+class B extends A {
+ lazy val b0 = 71
+ lazy val b1 = 72
+ lazy val b2 = 73
+ lazy val b3 = 74
+ lazy val b4 = 75
+ lazy val b5 = 76
+ lazy val b6 = 77
+ lazy val b7 = 78
+ lazy val b8 = 79
+ lazy val b9 = 80
+ override def run = {
+ super.run
+ println(List(b0, b1, b2, b3, b4, b5, b6, b7, b8, b9))
+ }
+
+}
+
+object Test {
+ def main(args: Array[String]) {
+ new B().run
+ }
+}
diff --git a/test/files/run/t3038d.flags b/test/files/run/t3038d.flags
new file mode 100644
index 0000000000..ae08446055
--- /dev/null
+++ b/test/files/run/t3038d.flags
@@ -0,0 +1 @@
+-Xcheckinit \ No newline at end of file
diff --git a/test/files/run/t3038d.scala b/test/files/run/t3038d.scala
new file mode 100644
index 0000000000..a92e3532a8
--- /dev/null
+++ b/test/files/run/t3038d.scala
@@ -0,0 +1,60 @@
+trait Foo {
+ @transient protected var load = 1
+ @transient protected var a = 12
+
+ protected def init[B](in: java.io.ObjectInputStream) {
+ in.defaultReadObject
+ load = in.readInt
+ val sizea = in.readInt
+ a = 12
+ }
+
+ protected def serializeTo(out: java.io.ObjectOutputStream) {
+ out.defaultWriteObject
+ out.writeInt(load)
+ out.writeInt(a)
+ }
+}
+
+
+@serializable
+class Bar extends Foo {
+ @transient protected var first: Any = null
+ def size = a
+ @transient var second: Any = null
+
+ def checkMember { first }
+
+ private def writeObject(out: java.io.ObjectOutputStream) {
+ serializeTo(out)
+ }
+
+ private def readObject(in: java.io.ObjectInputStream) {
+ first = null
+ init(in)
+ }
+}
+
+object Test {
+ private def toObject[A](bytes: Array[Byte]): A = {
+ val in = new java.io.ObjectInputStream(new java.io.ByteArrayInputStream(bytes))
+ in.readObject.asInstanceOf[A]
+ }
+
+ private def toBytes(o: AnyRef): Array[Byte] = {
+ val bos = new java.io.ByteArrayOutputStream
+ val out = new java.io.ObjectOutputStream(bos)
+ out.writeObject(o)
+ out.close
+ bos.toByteArray
+ }
+
+
+ def main(args: Array[String]) {
+ val a1 = new Bar()
+ val serialized:Array[Byte] = toBytes(a1)
+ val deserialized: Bar = toObject(serialized)
+ deserialized.size
+ deserialized.checkMember
+ }
+}
diff --git a/test/files/run/t3895.scala b/test/files/run/t3895.scala
index dfc4a34a32..9028e0a08a 100644
--- a/test/files/run/t3895.scala
+++ b/test/files/run/t3895.scala
@@ -20,6 +20,12 @@ class B extends A{
val b = 12
}
+trait T {
+ private final val a = false
+}
+
+class Impl extends T
+
object Test {
def main(args: Array[String]) {