diff options
-rw-r--r-- | src/library/scala/collection/immutable/List.scala | 21 | ||||
-rw-r--r-- | src/library/scala/collection/immutable/Stream.scala | 10 | ||||
-rw-r--r-- | src/library/scala/collection/mutable/ListBuffer.scala | 46 | ||||
-rw-r--r-- | test/files/run/macro-range/macro_range_1.scala | 17 | ||||
-rw-r--r-- | test/files/run/macro-range/macro_range_2.scala | 17 | ||||
-rw-r--r-- | test/files/run/si5262.check | 2 | ||||
-rw-r--r-- | test/files/run/si5262.scala | 26 | ||||
-rw-r--r-- | test/files/run/si5374.check | 3 | ||||
-rw-r--r-- | test/files/run/si5374.scala | 42 | ||||
-rw-r--r-- | test/files/run/t4835.check | 7 | ||||
-rw-r--r-- | test/files/run/t4835.scala | 38 |
11 files changed, 193 insertions, 36 deletions
diff --git a/src/library/scala/collection/immutable/List.scala b/src/library/scala/collection/immutable/List.scala index c6f056bd81..e9ecc75e0f 100644 --- a/src/library/scala/collection/immutable/List.scala +++ b/src/library/scala/collection/immutable/List.scala @@ -316,28 +316,7 @@ final case class ::[B](private var hd: B, private[scala] var tl: List[B]) extend override def tail : List[B] = tl override def isEmpty: Boolean = false - import java.io._ - private def writeObject(out: ObjectOutputStream) { - var xs: List[B] = this - while (!xs.isEmpty) { out.writeObject(xs.head); xs = xs.tail } - out.writeObject(ListSerializeEnd) - } - - private def readObject(in: ObjectInputStream) { - hd = in.readObject.asInstanceOf[B] - assert(hd != ListSerializeEnd) - var current: ::[B] = this - while (true) in.readObject match { - case ListSerializeEnd => - current.tl = Nil - return - case a : Any => - val list : ::[B] = new ::(a.asInstanceOf[B], Nil) - current.tl = list - current = list - } - } } /** $factoryInfo diff --git a/src/library/scala/collection/immutable/Stream.scala b/src/library/scala/collection/immutable/Stream.scala index e6587f9615..2eb2f8eb09 100644 --- a/src/library/scala/collection/immutable/Stream.scala +++ b/src/library/scala/collection/immutable/Stream.scala @@ -929,13 +929,19 @@ self => /** A specialized, extra-lazy implementation of a stream iterator, so it can * iterate as lazily as it traverses the tail. */ -final class StreamIterator[+A](self: Stream[A]) extends AbstractIterator[A] with Iterator[A] { +final class StreamIterator[+A] private() extends AbstractIterator[A] with Iterator[A] { + def this(self: Stream[A]) { + this() + these = new LazyCell(self) + } + // A call-by-need cell. class LazyCell(st: => Stream[A]) { lazy val v = st } - private var these = new LazyCell(self) + private var these: LazyCell = _ + def hasNext: Boolean = these.v.nonEmpty def next(): A = if (isEmpty) Iterator.empty.next diff --git a/src/library/scala/collection/mutable/ListBuffer.scala b/src/library/scala/collection/mutable/ListBuffer.scala index 131cdd0005..eb871135df 100644 --- a/src/library/scala/collection/mutable/ListBuffer.scala +++ b/src/library/scala/collection/mutable/ListBuffer.scala @@ -13,6 +13,7 @@ package mutable import generic._ import immutable.{List, Nil, ::} +import java.io._ /** A `Buffer` implementation back up by a list. It provides constant time * prepend and append. Most other operations are linear. @@ -53,6 +54,7 @@ final class ListBuffer[A] override def companion: GenericCompanion[ListBuffer] = ListBuffer import scala.collection.Traversable + import scala.collection.immutable.ListSerializeEnd private var start: List[A] = Nil private var last0: ::[A] = _ @@ -60,7 +62,49 @@ final class ListBuffer[A] private var len = 0 protected def underlying: immutable.Seq[A] = start - + + private def writeObject(out: ObjectOutputStream) { + // write start + var xs: List[A] = start + while (!xs.isEmpty) { out.writeObject(xs.head); xs = xs.tail } + out.writeObject(ListSerializeEnd) + + // no need to write last0 + + // write if exported + out.writeBoolean(exported) + + // write the length + out.writeInt(len) + } + + private def readObject(in: ObjectInputStream) { + // read start, set last0 appropriately + var elem: A = in.readObject.asInstanceOf[A] + if (elem == ListSerializeEnd) { + start = Nil + last0 = null + } else { + var current = new ::(elem, Nil) + start = current + elem = in.readObject.asInstanceOf[A] + while (elem != ListSerializeEnd) { + val list = new ::(elem, Nil) + current.tl = list + current = list + elem = in.readObject.asInstanceOf[A] + } + last0 = current + start + } + + // read if exported + exported = in.readBoolean() + + // read the length + len = in.readInt() + } + /** The current length of the buffer. * * This operation takes constant time. diff --git a/test/files/run/macro-range/macro_range_1.scala b/test/files/run/macro-range/macro_range_1.scala index 15a018fcff..fdfe7169ad 100644 --- a/test/files/run/macro-range/macro_range_1.scala +++ b/test/files/run/macro-range/macro_range_1.scala @@ -29,12 +29,13 @@ abstract class Utils { } } def makeApply(fn: Tree, args: List[Tree]): Tree = fn match { - case Function(vparams, body) => + case Function(vparams, body) => new TreeSubstituter(vparams map (_.symbol), args) transform body case Block(stats, expr) => Block(stats, makeApply(expr, args)) - case _ => - println("no beta on "+fn+" "+fn.getClass) + case _ => + // todo. read the compiler config and print if -Ydebug is set + //println("no beta on "+fn+" "+fn.getClass) Apply(fn, args) } def makeWhile(lname: TermName, cond: Tree, body: Tree): Tree = { @@ -48,7 +49,8 @@ abstract class Utils { class Range(val from: Int, val to: Int) extends RangeDefault { override def macro foreach(f: Int => Unit): Unit = { - println("macro-expand, _this = "+ _this) + // todo. read the compiler config and print if -Ydebug is set + //println("macro-expand, _this = "+ _this) import _context._ object utils extends Utils { val context: _context.type = _context @@ -71,12 +73,15 @@ class Range(val from: Int, val to: Int) extends RangeDefault { val body = Block( List(makeApply(f, List(iref))), Assign(iref, makeBinop(iref, "$plus", Literal(Constant(1))))) - tools.nsc.util.trace("generated: ")( + val generated = Block( List( ValDef(Modifiers(Set(Modifier.mutable)), iname, TypeTree(), lo), ValDef(Modifiers(), hname, TypeTree(), hi)), - makeWhile(labelname, cond, body))) + makeWhile(labelname, cond, body)) + // todo. read the compiler config and print if -Ydebug is set + //tools.nsc.util.trace("generated: ")(generated) + generated case _ => Apply( Select( diff --git a/test/files/run/macro-range/macro_range_2.scala b/test/files/run/macro-range/macro_range_2.scala index 15a018fcff..fdfe7169ad 100644 --- a/test/files/run/macro-range/macro_range_2.scala +++ b/test/files/run/macro-range/macro_range_2.scala @@ -29,12 +29,13 @@ abstract class Utils { } } def makeApply(fn: Tree, args: List[Tree]): Tree = fn match { - case Function(vparams, body) => + case Function(vparams, body) => new TreeSubstituter(vparams map (_.symbol), args) transform body case Block(stats, expr) => Block(stats, makeApply(expr, args)) - case _ => - println("no beta on "+fn+" "+fn.getClass) + case _ => + // todo. read the compiler config and print if -Ydebug is set + //println("no beta on "+fn+" "+fn.getClass) Apply(fn, args) } def makeWhile(lname: TermName, cond: Tree, body: Tree): Tree = { @@ -48,7 +49,8 @@ abstract class Utils { class Range(val from: Int, val to: Int) extends RangeDefault { override def macro foreach(f: Int => Unit): Unit = { - println("macro-expand, _this = "+ _this) + // todo. read the compiler config and print if -Ydebug is set + //println("macro-expand, _this = "+ _this) import _context._ object utils extends Utils { val context: _context.type = _context @@ -71,12 +73,15 @@ class Range(val from: Int, val to: Int) extends RangeDefault { val body = Block( List(makeApply(f, List(iref))), Assign(iref, makeBinop(iref, "$plus", Literal(Constant(1))))) - tools.nsc.util.trace("generated: ")( + val generated = Block( List( ValDef(Modifiers(Set(Modifier.mutable)), iname, TypeTree(), lo), ValDef(Modifiers(), hname, TypeTree(), hi)), - makeWhile(labelname, cond, body))) + makeWhile(labelname, cond, body)) + // todo. read the compiler config and print if -Ydebug is set + //tools.nsc.util.trace("generated: ")(generated) + generated case _ => Apply( Select( diff --git a/test/files/run/si5262.check b/test/files/run/si5262.check new file mode 100644 index 0000000000..4c7a875de5 --- /dev/null +++ b/test/files/run/si5262.check @@ -0,0 +1,2 @@ +List(1, 2, 3, 4) +List(1, 2, null, 4)
\ No newline at end of file diff --git a/test/files/run/si5262.scala b/test/files/run/si5262.scala new file mode 100644 index 0000000000..fc4e57aa96 --- /dev/null +++ b/test/files/run/si5262.scala @@ -0,0 +1,26 @@ + + + + + + + +object Test { + + def serializationDeserialization(obj : Any) { + val bos = new java.io.ByteArrayOutputStream() + val out = new java.io.ObjectOutputStream(bos) + out.writeObject(obj) + + val arr = bos.toByteArray() + val in = new java.io.ObjectInputStream(new java.io.ByteArrayInputStream(arr)) + val o = in.readObject() + println(o) + } + + def main(args : Array[String]) { + serializationDeserialization(List(1,2,3,4)) + serializationDeserialization(List(1,2,null,4)) + } + +} diff --git a/test/files/run/si5374.check b/test/files/run/si5374.check new file mode 100644 index 0000000000..cdf0bc7e5b --- /dev/null +++ b/test/files/run/si5374.check @@ -0,0 +1,3 @@ +ListBuffer(1, 2, 3, 1) +ListBuffer(1, 2, 3, 1) +ListBuffer()
\ No newline at end of file diff --git a/test/files/run/si5374.scala b/test/files/run/si5374.scala new file mode 100644 index 0000000000..a5678c3a81 --- /dev/null +++ b/test/files/run/si5374.scala @@ -0,0 +1,42 @@ + + + +import collection.mutable.ListBuffer +import java.io._ + + + +object Test { + + def main(args: Array[String]) { + ticketExample() + emptyListBuffer() + } + + def ticketExample() { + val baos = new ByteArrayOutputStream + val oos = new ObjectOutputStream(baos) + oos.writeObject( ListBuffer(1,2,3) ) + val bais = new ByteArrayInputStream( baos.toByteArray ) + val ois = new ObjectInputStream(bais) + val lb = ois.readObject.asInstanceOf[ListBuffer[Int]] + val lb2 = ListBuffer[Int]() ++= lb + + lb2 ++= List(1) + lb ++= List(1) + println(lb) + println(lb2) + } + + def emptyListBuffer() { + val baos = new ByteArrayOutputStream + val oos = new ObjectOutputStream(baos) + oos.writeObject( ListBuffer() ) + val bais = new ByteArrayInputStream( baos.toByteArray ) + val ois = new ObjectInputStream(bais) + val lb = ois.readObject.asInstanceOf[ListBuffer[Int]] + + println(lb) + } + +} diff --git a/test/files/run/t4835.check b/test/files/run/t4835.check new file mode 100644 index 0000000000..531c3d7bb6 --- /dev/null +++ b/test/files/run/t4835.check @@ -0,0 +1,7 @@ +-1 0 1 2 3 4 5 6 7 8 9
+-1 1 3 5 7 9 11 13 15 17 19
+1 1
+2 1 2
+2 1 A 2
+3 1 2 3
+3 1 A 2 B 3
diff --git a/test/files/run/t4835.scala b/test/files/run/t4835.scala new file mode 100644 index 0000000000..50d161be40 --- /dev/null +++ b/test/files/run/t4835.scala @@ -0,0 +1,38 @@ +/*
+ * Test case for SI-4835. This tests confirm that the fix
+ * doesn't break laziness. To test memory consumption,
+ * I need to confirm that OutOfMemoryError doesn't occur.
+ * I could create such tests. However, such tests consume
+ * too much time and memory.
+ */
+object Test {
+ private final val INFINITE = -1
+ def testStreamIterator(num: Int, stream: Stream[Int]): Unit = {
+ val iter = stream.iterator
+ print(num)
+ // if num == -1, then steram is infinite sequence
+ if (num == INFINITE) {
+ for(i <- 0 until 10) {
+ print(" " + iter.next())
+ }
+ } else {
+ while(iter.hasNext) {
+ print(" " + iter.next())
+ }
+ }
+ println()
+ }
+
+ def main(args: Array[String]): Unit = {
+ import Stream.{from, cons, empty}
+ testStreamIterator(INFINITE, from(0))
+ testStreamIterator(INFINITE, from(0).filter(_ % 2 == 1))
+ testStreamIterator(1, Stream(1))
+ testStreamIterator(2, Stream(1, 2))
+ //Stream with side effect
+ testStreamIterator(2, cons(1, cons({ print(" A"); 2}, empty)))
+ testStreamIterator(3, Stream(1, 2, 3))
+ //Stream with side effect
+ testStreamIterator(3, cons(1, cons({ print(" A"); 2}, cons({ print(" B"); 3}, Stream.empty))))
+ }
+}
|