diff options
author | Hubert Plociniczak <hubert.plociniczak@epfl.ch> | 2010-11-02 00:15:16 +0000 |
---|---|---|
committer | Hubert Plociniczak <hubert.plociniczak@epfl.ch> | 2010-11-02 00:15:16 +0000 |
commit | bcfe76ee680852c66781882d70ac02bd76e09ac9 (patch) | |
tree | 72d8a56d40bec04f0290a9909a6cff384d1ff4fb | |
parent | b80f27780458da880d47392e4ac747d196af355e (diff) | |
download | scala-bcfe76ee680852c66781882d70ac02bd76e09ac9.tar.gz scala-bcfe76ee680852c66781882d70ac02bd76e09ac9.tar.bz2 scala-bcfe76ee680852c66781882d70ac02bd76e09ac9.zip |
Added separate bitmaps for private and transien...
Added separate bitmaps for private and transient lazy vals. Closes
#3038, #1573. Review by dragos. I had to fix a couple of initialization
issues that checkinit forced me to do and that weren't a problem before
because the bitmap was serialized even for @transitive. For that I
needed to change the setters in checkinit so that they also update the
bitmap.
-rw-r--r-- | src/compiler/scala/tools/nsc/symtab/StdNames.scala | 13 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/transform/Mixin.scala | 100 | ||||
-rw-r--r-- | src/library/scala/collection/mutable/FlatHashTable.scala | 1 | ||||
-rw-r--r-- | src/library/scala/collection/mutable/HashTable.scala | 3 | ||||
-rw-r--r-- | src/library/scala/collection/mutable/LinkedHashMap.scala | 2 | ||||
-rw-r--r-- | test/files/jvm/serialization.check | 4 | ||||
-rw-r--r-- | test/files/jvm/serialization.scala | 30 | ||||
-rw-r--r-- | test/files/run/t3038.check | 19 | ||||
-rw-r--r-- | test/files/run/t3038.scala | 68 | ||||
-rw-r--r-- | test/files/run/t3038b.flags | 1 | ||||
-rw-r--r-- | test/files/run/t3038b.scala | 20 | ||||
-rw-r--r-- | test/files/run/t3038c.check | 2 | ||||
-rw-r--r-- | test/files/run/t3038c/A_1.scala | 83 | ||||
-rw-r--r-- | test/files/run/t3038c/B_2.scala | 24 | ||||
-rw-r--r-- | test/files/run/t3038d.flags | 1 | ||||
-rw-r--r-- | test/files/run/t3038d.scala | 60 | ||||
-rw-r--r-- | test/files/run/t3895.scala | 6 |
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]) { |