From 6611977aa169d108142e2416f6802e43972c4caa Mon Sep 17 00:00:00 2001 From: Lukas Rytz Date: Fri, 6 Apr 2018 11:42:20 +0200 Subject: [PATCH 01/10] Changes to compile with Scala 2.13.0-M4 Co-authored-by: julienrf --- build.sbt | 3 +- doc/UserGuide.md | 28 ++-- .../src/test/scala/CommandsLevelDB.scala | 4 +- .../src/test/scala/CommandsNix.scala | 4 +- .../src/test/scala/CommandsRedis.scala | 4 +- .../org/scalacheck/CogenSpecification.scala | 2 +- .../org/scalacheck/GenSpecification.scala | 4 +- .../PropertyFilterSpecification.scala | 8 +- .../commands/CommandsSpecification.scala | 4 +- src/main/scala/org/scalacheck/Arbitrary.scala | 8 +- src/main/scala/org/scalacheck/Cogen.scala | 2 +- src/main/scala/org/scalacheck/Gen.scala | 38 ++--- src/main/scala/org/scalacheck/Prop.scala | 6 +- .../scala/org/scalacheck/Properties.scala | 2 +- .../org/scalacheck/ScalaCheckFramework.scala | 2 +- src/main/scala/org/scalacheck/Shrink.scala | 130 +++++++++--------- src/main/scala/org/scalacheck/Test.scala | 2 +- .../org/scalacheck/commands/Commands.scala | 12 +- .../scalacheck/util/ArrayListBuilder.scala | 17 +++ .../scala/org/scalacheck/util/Buildable.scala | 45 +++--- .../scala/org/scalacheck/util/FreqMap.scala | 4 +- .../org/scalacheck/ShrinkSpecification.scala | 6 +- .../util/BuildableSpecification.scala | 4 +- 23 files changed, 173 insertions(+), 166 deletions(-) create mode 100644 src/main/scala/org/scalacheck/util/ArrayListBuilder.scala diff --git a/build.sbt b/build.sbt index 07f12bb27..71913fcae 100644 --- a/build.sbt +++ b/build.sbt @@ -10,7 +10,7 @@ lazy val travisCommit = Option(System.getenv().get("TRAVIS_COMMIT")) lazy val scalaVersionSettings = Seq( scalaVersion := "2.12.6", - crossScalaVersions := Seq("2.10.7", "2.11.12", "2.13.0-M3", scalaVersion.value) + crossScalaVersions := Seq("2.10.7", "2.11.12", "2.13.0-M4", scalaVersion.value) ) lazy val sharedSettings = MimaSettings.settings ++ scalaVersionSettings ++ Seq( @@ -56,7 +56,6 @@ lazy val sharedSettings = MimaSettings.settings ++ scalaVersionSettings ++ Seq( "-unchecked", "-Xfatal-warnings", "-Xfuture", - "-Yno-adapted-args", "-Ywarn-dead-code", "-Ywarn-inaccessible", "-Ywarn-nullary-override", diff --git a/doc/UserGuide.md b/doc/UserGuide.md index 522b04aea..c16949876 100644 --- a/doc/UserGuide.md +++ b/doc/UserGuide.md @@ -471,17 +471,17 @@ responsible for generating the individual items. You can use it in the following way: ```scala -val genIntList = Gen.containerOf[List,Int](Gen.oneOf(1, 3, 5)) +val genIntList = Gen.containerOf[List,Int](Gen.oneOf(1, 3, 5)) -val genStringStream = Gen.containerOf[Stream,String](Gen.alphaStr) +val genStringLazyList = Gen.containerOf[LazyList,String](Gen.alphaStr) -val genBoolArray = Gen.containerOf[Array,Boolean](true) +val genBoolArray = Gen.containerOf[Array,Boolean](true) ``` -By default, ScalaCheck supports generation of `List`, `Stream`, `Set`, `Array`, -and `ArrayList` (from `java.util`). You can add support for additional -containers by adding implicit `Buildable` instances. See `Buildable.scala` for -examples. +By default, ScalaCheck supports generation of `List`, `Stream` (Scala 2.10 - +2.12, deprecated in 2.13), `LazyList` (Scala 2.13), `Set`, `Array`, and +`ArrayList` (from `java.util`). You can add support for additional containers +by adding implicit `Buildable` instances. See `Buildable.scala` for examples. There is also `Gen.nonEmptyContainerOf` for generating non-empty containers, and `Gen.containerOfN` for generating containers of a given size. @@ -778,9 +778,9 @@ can also define default shrinking methods. This is done by defining an implicit method that returns a `Shrink[T]` instance. This is done by using the `Shrink(...)` factory method, which as its only parameter takes a function and returns an instance of `Shrink[T]`. In turn, the function should take a value -of the given type `T`, and return a `Stream` of shrank variants of the given -value. As an example, look at the implicit `Shrink` instance for a tuple as it -is defined in ScalaCheck: +of the given type `T`, and return a `Stream` (`LazyList` on Scala 2.13) of shrank +variants of the given value. As an example, look at the implicit `Shrink` instance +for a tuple as it is defined in ScalaCheck: ```scala /** Shrink instance of 2-tuple */ @@ -873,15 +873,15 @@ object CounterSpecification extends Commands { * (a singleton [[Sut]]), implement this method the following way: * * {{{ - * def canCreateNewSut(newState: State, initSuts: Traversable[State] - * runningSuts: Traversable[Sut] + * def canCreateNewSut(newState: State, initSuts: Iterable[State] + * runningSuts: Iterable[Sut] * ) = { * initSuts.isEmpty && runningSuts.isEmpty * } * }}} */ - def canCreateNewSut(newState: State, initSuts: Traversable[State], - runningSuts: Traversable[Sut]): Boolean = true + def canCreateNewSut(newState: State, initSuts: Iterable[State], + runningSuts: Iterable[Sut]): Boolean = true /** The precondition for the initial state, when no commands yet have * run. This is used by ScalaCheck when command sequences are shrinked diff --git a/examples/commands-leveldb/src/test/scala/CommandsLevelDB.scala b/examples/commands-leveldb/src/test/scala/CommandsLevelDB.scala index 28212075e..2c7a9cd75 100644 --- a/examples/commands-leveldb/src/test/scala/CommandsLevelDB.scala +++ b/examples/commands-leveldb/src/test/scala/CommandsLevelDB.scala @@ -30,8 +30,8 @@ object LevelDBSpec extends Commands { def path = s"db_$name" } - def canCreateNewSut(newState: State, initSuts: Traversable[State], - runningSuts: Traversable[Sut] + def canCreateNewSut(newState: State, initSuts: Iterable[State], + runningSuts: Iterable[Sut] ) = { !initSuts.exists(_.name == newState.name) && !runningSuts.exists(_.name == newState.name) diff --git a/examples/commands-nix/src/test/scala/CommandsNix.scala b/examples/commands-nix/src/test/scala/CommandsNix.scala index 9a4916382..9235dec8c 100644 --- a/examples/commands-nix/src/test/scala/CommandsNix.scala +++ b/examples/commands-nix/src/test/scala/CommandsNix.scala @@ -100,8 +100,8 @@ object MachineSpec extends Commands { type Sut = Map[String, org.libvirt.Domain] // TODO we should check for example total amount of memory used here - def canCreateNewSut(newState: State, initSuts: Traversable[State], - runningSuts: Traversable[Sut] + def canCreateNewSut(newState: State, initSuts: Iterable[State], + runningSuts: Iterable[Sut] ): Boolean = true def newSut(state: State): Sut = { diff --git a/examples/commands-redis/src/test/scala/CommandsRedis.scala b/examples/commands-redis/src/test/scala/CommandsRedis.scala index ce30b5554..5e285d77d 100644 --- a/examples/commands-redis/src/test/scala/CommandsRedis.scala +++ b/examples/commands-redis/src/test/scala/CommandsRedis.scala @@ -26,8 +26,8 @@ object RedisSpec extends Commands { connected: Boolean ) - def canCreateNewSut(newState: State, initSuts: Traversable[State], - runningSuts: Traversable[Sut] + def canCreateNewSut(newState: State, initSuts: Iterable[State], + runningSuts: Iterable[Sut] ): Boolean = { initSuts.isEmpty && runningSuts.isEmpty } diff --git a/jvm/src/test/scala/org/scalacheck/CogenSpecification.scala b/jvm/src/test/scala/org/scalacheck/CogenSpecification.scala index 106333f8e..b25a6488f 100644 --- a/jvm/src/test/scala/org/scalacheck/CogenSpecification.scala +++ b/jvm/src/test/scala/org/scalacheck/CogenSpecification.scala @@ -140,7 +140,7 @@ object CogenSpecification extends Properties("Cogen") { include(cogenLaws[String], "cogenString.") include(cogenLaws[List[Int]], "cogenList.") include(cogenLaws[Vector[Int]], "cogenVector.") - include(cogenLaws[Stream[Int]], "cogenStream.") + include(cogenLaws[LazyList[Int]], "cogenLazyList.") include(cogenLaws[Set[Int]], "cogenSet.") include(cogenLaws[Map[Int, Int]], "cogenMap.") include(cogenLaws[() => Int], "cogenFunction0.") diff --git a/jvm/src/test/scala/org/scalacheck/GenSpecification.scala b/jvm/src/test/scala/org/scalacheck/GenSpecification.scala index 59c2b9647..113898a5b 100644 --- a/jvm/src/test/scala/org/scalacheck/GenSpecification.scala +++ b/jvm/src/test/scala/org/scalacheck/GenSpecification.scala @@ -179,7 +179,7 @@ object GenSpecification extends Properties("Gen") { l.length == 0 } - property("infiniteStream") = forAll(infiniteStream(arbitrary[Int]), arbitrary[Short]) { (s, n) => + property("infiniteLazyList") = forAll(infiniteLazyList(arbitrary[Int]), arbitrary[Short]) { (s, n) => s.drop(n & 0xffff).nonEmpty } @@ -201,7 +201,7 @@ object GenSpecification extends Properties("Gen") { property("distributed pick") = { val lst = (0 to 7).toIterable val n = 2 - forAll(pick(n, lst)) { xs: Seq[Int] => + forAll(pick(n, lst)) { xs: collection.Seq[Int] => xs.map { x: Int => Prop.collect(x) { xs.size == n diff --git a/jvm/src/test/scala/org/scalacheck/PropertyFilterSpecification.scala b/jvm/src/test/scala/org/scalacheck/PropertyFilterSpecification.scala index 3a9340a6c..03d52775a 100644 --- a/jvm/src/test/scala/org/scalacheck/PropertyFilterSpecification.scala +++ b/jvm/src/test/scala/org/scalacheck/PropertyFilterSpecification.scala @@ -26,8 +26,8 @@ object PropertyFilterSpecification extends Properties("PropertyFilter") { val nl = System.lineSeparator - private def diff(filter: Option[String], actual: Seq[String], - expected: Seq[String]): String = { + private def diff(filter: Option[String], actual: collection.Seq[String], + expected: collection.Seq[String]): String = { s"filter: ${filter.getOrElse("not supplied")}" + s"${nl}expected values:$nl" + s"\t${expected.mkString(s"$nl\t")}" + @@ -35,8 +35,8 @@ object PropertyFilterSpecification extends Properties("PropertyFilter") { s"\t${actual.mkString(s"$nl\t")}" } - private def prop(filter: Option[String], actualNames: Seq[String], - expectedNames: Seq[String]): Prop = { + private def prop(filter: Option[String], actualNames: collection.Seq[String], + expectedNames: collection.Seq[String]): Prop = { def lengthProp = actualNames.length == expectedNames.length def props = actualNames.forall(expectedNames.contains) diff --git a/jvm/src/test/scala/org/scalacheck/commands/CommandsSpecification.scala b/jvm/src/test/scala/org/scalacheck/commands/CommandsSpecification.scala index c60e276d3..b3757f932 100644 --- a/jvm/src/test/scala/org/scalacheck/commands/CommandsSpecification.scala +++ b/jvm/src/test/scala/org/scalacheck/commands/CommandsSpecification.scala @@ -30,8 +30,8 @@ object CommandsSpecification extends Properties("Commands") { override def shrinkState: Shrink[Int] = implicitly - def canCreateNewSut(newState: State, initSuts: Traversable[State], - runningSuts: Traversable[Sut]) = true + def canCreateNewSut(newState: State, initSuts: Iterable[State], + runningSuts: Iterable[Sut]) = true def newSut(state: State): Sut = Counter(state) diff --git a/src/main/scala/org/scalacheck/Arbitrary.scala b/src/main/scala/org/scalacheck/Arbitrary.scala index f543e95de..e6f057d6c 100644 --- a/src/main/scala/org/scalacheck/Arbitrary.scala +++ b/src/main/scala/org/scalacheck/Arbitrary.scala @@ -357,22 +357,22 @@ private[scalacheck] sealed trait ArbitraryLowPriority { Arbitrary(Gen.oneOf(arbitrary[T].map(Success(_)), arbitrary[Throwable].map(Failure(_)))) /** Arbitrary instance of any [[org.scalacheck.util.Buildable]] container - * (such as lists, arrays, streams, etc). The maximum size of the container + * (such as lists, arrays, lazy lists, etc). The maximum size of the container * depends on the size generation parameter. */ implicit def arbContainer[C[_],T](implicit - a: Arbitrary[T], b: Buildable[T,C[T]], t: C[T] => Traversable[T] + a: Arbitrary[T], b: Buildable[T,C[T]], t: C[T] => Iterable[T] ): Arbitrary[C[T]] = Arbitrary(buildableOf[C[T],T](arbitrary[T])) /** Arbitrary instance of any [[org.scalacheck.util.Buildable]] container * (such as maps). The maximum size of the container depends on the size * generation parameter. */ implicit def arbContainer2[C[_,_],T,U](implicit - a: Arbitrary[(T,U)], b: Buildable[(T,U),C[T,U]], t: C[T,U] => Traversable[(T,U)] + a: Arbitrary[(T,U)], b: Buildable[(T,U),C[T,U]], t: C[T,U] => Iterable[(T,U)] ): Arbitrary[C[T,U]] = Arbitrary(buildableOf[C[T,U],(T,U)](arbitrary[(T,U)])) implicit def arbEnum[A <: java.lang.Enum[A]](implicit A: reflect.ClassTag[A]): Arbitrary[A] = { val values = A.runtimeClass.getEnumConstants.asInstanceOf[Array[A]] - Arbitrary(Gen.oneOf(values)) + Arbitrary(Gen.oneOf(values.toIndexedSeq)) } implicit def arbPartialFunction[A: Cogen, B: Arbitrary]: Arbitrary[PartialFunction[A, B]] = diff --git a/src/main/scala/org/scalacheck/Cogen.scala b/src/main/scala/org/scalacheck/Cogen.scala index c8585d9c9..6af873030 100644 --- a/src/main/scala/org/scalacheck/Cogen.scala +++ b/src/main/scala/org/scalacheck/Cogen.scala @@ -123,7 +123,7 @@ object Cogen extends CogenArities with CogenLowPriority { implicit def cogenVector[A: Cogen]: Cogen[Vector[A]] = Cogen.it(_.iterator) - implicit def cogenStream[A: Cogen]: Cogen[Stream[A]] = + implicit def cogenLazyList[A: Cogen]: Cogen[LazyList[A]] = Cogen.it(_.iterator) implicit def cogenSet[A: Cogen: Ordering]: Cogen[Set[A]] = diff --git a/src/main/scala/org/scalacheck/Gen.scala b/src/main/scala/org/scalacheck/Gen.scala index 638995d71..7d94188a9 100644 --- a/src/main/scala/org/scalacheck/Gen.scala +++ b/src/main/scala/org/scalacheck/Gen.scala @@ -449,7 +449,7 @@ object Gen extends GenArities{ /** Sequences generators. If any of the given generators fails, the * resulting generator will also fail. */ - def sequence[C,T](gs: Traversable[Gen[T]])(implicit b: Buildable[T,C]): Gen[C] = { + def sequence[C,T](gs: Iterable[Gen[T]])(implicit b: Buildable[T,C]): Gen[C] = { val g = gen { (p, seed) => gs.foldLeft(r(Some(Vector.empty[T]), seed)) { case (rs,g) => @@ -559,7 +559,7 @@ object Gen extends GenArities{ builder += ((total, value)) } val tree = builder.result - choose(1L, total).flatMap(r => tree.from(r).head._2).suchThat { x => + choose(1L, total).flatMap(r => tree.rangeFrom(r).head._2).suchThat { x => gs.exists(_._2.sieveCopy(x)) } } @@ -576,7 +576,7 @@ object Gen extends GenArities{ //// List Generators //// - /** Generates a container of any Traversable type for which there exists an + /** Generates a container of any Iterable type for which there exists an * implicit [[org.scalacheck.util.Buildable]] instance. The elements in the * container will be generated by the given generator. The size of the * generated container is limited by `n`. Depending on what kind of container @@ -584,47 +584,47 @@ object Gen extends GenArities{ * `n`, but not more. If the given generator fails generating a value, the * complete container generator will also fail. */ def buildableOfN[C,T](n: Int, g: Gen[T])(implicit - evb: Buildable[T,C], evt: C => Traversable[T] + evb: Buildable[T,C], evt: C => Iterable[T] ): Gen[C] = - sequence[C,T](Traversable.fill(n)(g)) suchThat { c => + sequence[C,T](Iterable.fill(n)(g)) suchThat { c => // TODO: Can we guarantee c.size == n (See issue #89)? c.forall(g.sieveCopy) } - /** Generates a container of any Traversable type for which there exists an + /** Generates a container of any Iterable type for which there exists an * implicit [[org.scalacheck.util.Buildable]] instance. The elements in the * container will be generated by the given generator. The size of the * container is bounded by the size parameter used when generating values. */ def buildableOf[C,T](g: Gen[T])(implicit - evb: Buildable[T,C], evt: C => Traversable[T] + evb: Buildable[T,C], evt: C => Iterable[T] ): Gen[C] = sized(s => choose(0, s max 0).flatMap(buildableOfN[C,T](_,g))) suchThat { c => if (c == null) g.sieveCopy(null) else c.forall(g.sieveCopy) } - /** Generates a non-empty container of any Traversable type for which there + /** Generates a non-empty container of any Iterable type for which there * exists an implicit [[org.scalacheck.util.Buildable]] instance. The * elements in the container will be generated by the given generator. The * size of the container is bounded by the size parameter used when * generating values. */ def nonEmptyBuildableOf[C,T](g: Gen[T])(implicit - evb: Buildable[T,C], evt: C => Traversable[T] + evb: Buildable[T,C], evt: C => Iterable[T] ): Gen[C] = sized(s => choose(1, s max 1).flatMap(buildableOfN[C,T](_,g))) suchThat(_.size > 0) /** A convenience method for calling `buildableOfN[C[T],T](n,g)`. */ def containerOfN[C[_],T](n: Int, g: Gen[T])(implicit - evb: Buildable[T,C[T]], evt: C[T] => Traversable[T] + evb: Buildable[T,C[T]], evt: C[T] => Iterable[T] ): Gen[C[T]] = buildableOfN[C[T],T](n,g) /** A convenience method for calling `buildableOf[C[T],T](g)`. */ def containerOf[C[_],T](g: Gen[T])(implicit - evb: Buildable[T,C[T]], evt: C[T] => Traversable[T] + evb: Buildable[T,C[T]], evt: C[T] => Iterable[T] ): Gen[C[T]] = buildableOf[C[T],T](g) /** A convenience method for calling `nonEmptyBuildableOf[C[T],T](g)`. */ def nonEmptyContainerOf[C[_],T](g: Gen[T])(implicit - evb: Buildable[T,C[T]], evt: C[T] => Traversable[T] + evb: Buildable[T,C[T]], evt: C[T] => Iterable[T] ): Gen[C[T]] = nonEmptyBuildableOf[C[T],T](g) /** Generates a list of random length. The maximum length depends on the @@ -655,15 +655,15 @@ object Gen extends GenArities{ * is equal to calling containerOfN[Map,T,U](n,g). */ def mapOfN[T,U](n: Int, g: Gen[(T,U)]) = buildableOfN[Map[T,U],(T,U)](n,g) - /** Generates an infinite stream. */ - def infiniteStream[T](g: => Gen[T]): Gen[Stream[T]] = { - def unfold[A, S](z: S)(f: S => Option[(A, S)]): Stream[A] = f(z) match { + /** Generates an infinite lazy list. */ + def infiniteLazyList[T](g: => Gen[T]): Gen[LazyList[T]] = { + def unfold[A, S](z: S)(f: S => Option[(A, S)]): LazyList[A] = f(z) match { case Some((h, s)) => h #:: unfold(s)(f) - case None => Stream.empty + case None => LazyList.empty } gen { (p, seed0) => - new R[Stream[T]] { - val result: Option[Stream[T]] = Some(unfold(seed0)(s => Some(g.pureApply(p, s) -> s.next))) + new R[LazyList[T]] { + val result: Option[LazyList[T]] = Some(unfold(seed0)(s => Some(g.pureApply(p, s) -> s.next))) val seed: Seed = seed0.next } } @@ -687,7 +687,7 @@ object Gen extends GenArities{ choose(1, gs.length+2).flatMap(pick(_, g1, g2, gs: _*)) /** A generator that picks a given number of elements from a list, randomly */ - def pick[T](n: Int, l: Iterable[T]): Gen[Seq[T]] = { + def pick[T](n: Int, l: Iterable[T]): Gen[collection.Seq[T]] = { if (n > l.size || n < 0) throw new IllegalArgumentException(s"invalid choice: $n") else if (n == 0) Gen.const(Nil) else gen { (p, seed0) => diff --git a/src/main/scala/org/scalacheck/Prop.scala b/src/main/scala/org/scalacheck/Prop.scala index beddcf662..003bfb4c0 100644 --- a/src/main/scala/org/scalacheck/Prop.scala +++ b/src/main/scala/org/scalacheck/Prop.scala @@ -749,7 +749,7 @@ object Prop { /** Universal quantifier for an explicit generator. Shrinks failed arguments * with the given shrink function */ def forAllShrink[T, P](g: Gen[T], - shrink: T => Stream[T])(f: T => P + shrink: T => LazyList[T])(f: T => P )(implicit pv: P => Prop, pp: T => Pretty ): Prop = Prop { prms0 => @@ -765,8 +765,8 @@ object Prop { /* * Returns the first failed result in Left or success in Right. */ - def getFirstFailure(xs: Stream[T]): Either[(T,Result),(T,Result)] = { - assert(!xs.isEmpty, "Stream cannot be empty") + def getFirstFailure(xs: LazyList[T]): Either[(T,Result),(T,Result)] = { + assert(!xs.isEmpty, "LazyList cannot be empty") val results = xs.map(x => (x, result(x))) results.dropWhile(!_._2.failure).headOption match { case None => Right(results.head) diff --git a/src/main/scala/org/scalacheck/Properties.scala b/src/main/scala/org/scalacheck/Properties.scala index f9abe0702..f726791ce 100644 --- a/src/main/scala/org/scalacheck/Properties.scala +++ b/src/main/scala/org/scalacheck/Properties.scala @@ -41,7 +41,7 @@ class Properties(val name: String) { /** Returns all properties of this collection in a list of name/property * pairs. */ - def properties: Seq[(String,Prop)] = props + def properties: collection.Seq[(String,Prop)] = props /** Convenience method that checks the properties with the given parameters * (or default parameters, if not specified) diff --git a/src/main/scala/org/scalacheck/ScalaCheckFramework.scala b/src/main/scala/org/scalacheck/ScalaCheckFramework.scala index 071b9d251..e69e68da6 100644 --- a/src/main/scala/org/scalacheck/ScalaCheckFramework.scala +++ b/src/main/scala/org/scalacheck/ScalaCheckFramework.scala @@ -51,7 +51,7 @@ private abstract class ScalaCheckRunner extends Runner { abstract class BaseTask(override val taskDef: TaskDef) extends Task { val tags: Array[String] = Array() - val props: Seq[(String,Prop)] = { + val props: collection.Seq[(String,Prop)] = { val fp = taskDef.fingerprint.asInstanceOf[SubclassFingerprint] val obj = if (fp.isModule) Platform.loadModule(taskDef.fullyQualifiedName,loader) else Platform.newInstance(taskDef.fullyQualifiedName, loader, Seq())(Seq()) diff --git a/src/main/scala/org/scalacheck/Shrink.scala b/src/main/scala/org/scalacheck/Shrink.scala index 4547a7d75..d25b66c5c 100644 --- a/src/main/scala/org/scalacheck/Shrink.scala +++ b/src/main/scala/org/scalacheck/Shrink.scala @@ -16,57 +16,57 @@ import util.SerializableCanBuildFroms._ import scala.concurrent.duration.{Duration, FiniteDuration} sealed abstract class Shrink[T] extends Serializable { - def shrink(x: T): Stream[T] + def shrink(x: T): LazyList[T] } trait ShrinkLowPriority { /** Default shrink instance */ - implicit def shrinkAny[T]: Shrink[T] = Shrink(_ => Stream.empty) + implicit def shrinkAny[T]: Shrink[T] = Shrink(_ => LazyList.empty) } object Shrink extends ShrinkLowPriority { - import Stream.{cons, empty} + import LazyList.{cons, empty} import scala.collection._ - /** Interleaves two streams */ - private def interleave[T](xs: Stream[T], ys: Stream[T]): Stream[T] = + /** Interleaves two lazy lists */ + private def interleave[T](xs: LazyList[T], ys: LazyList[T]): LazyList[T] = if(xs.isEmpty) ys else if(ys.isEmpty) xs else cons(xs.head, cons(ys.head, interleave(xs.tail, ys.tail))) /** Shrink instance factory */ - def apply[T](s: T => Stream[T]): Shrink[T] = new Shrink[T] { + def apply[T](s: T => LazyList[T]): Shrink[T] = new Shrink[T] { override def shrink(x: T) = s(x) } /** Shrink a value */ - def shrink[T](x: T)(implicit s: Shrink[T]): Stream[T] = s.shrink(x) + def shrink[T](x: T)(implicit s: Shrink[T]): LazyList[T] = s.shrink(x) /** Shrink a value, but also return the original value as the first element in - * the resulting stream */ - def shrinkWithOrig[T](x: T)(implicit s: Shrink[T]): Stream[T] = + * the resulting lazy list */ + def shrinkWithOrig[T](x: T)(implicit s: Shrink[T]): LazyList[T] = cons(x, s.shrink(x)) /** Shrink instance of container */ - implicit def shrinkContainer[C[_],T](implicit v: C[T] => Traversable[T], s: Shrink[T], + implicit def shrinkContainer[C[_],T](implicit v: C[T] => Iterable[T], s: Shrink[T], b: Buildable[T,C[T]] ): Shrink[C[T]] = Shrink { xs: C[T] => val ys = v(xs) - val zs = ys.toStream - removeChunks(ys.size,zs).append(shrinkOne(zs)).map(b.fromIterable) + val zs = ys.to(LazyList) + removeChunks(ys.size,zs).lazyAppendedAll(shrinkOne(zs)).map(b.fromIterable) } /** Shrink instance of container2 */ - implicit def shrinkContainer2[C[_,_],T,U](implicit v: C[T,U] => Traversable[(T,U)], s: Shrink[(T,U)], + implicit def shrinkContainer2[C[_,_],T,U](implicit v: C[T,U] => Iterable[(T,U)], s: Shrink[(T,U)], b: Buildable[(T,U),C[T,U]] ): Shrink[C[T,U]] = Shrink { xs: C[T,U] => val ys = v(xs) - val zs = ys.toStream - removeChunks(ys.size,zs).append(shrinkOne(zs)).map(b.fromIterable) + val zs = ys.to(LazyList) + removeChunks(ys.size,zs).lazyAppendedAll(shrinkOne(zs)).map(b.fromIterable) } - private def removeChunks[T](n: Int, xs: Stream[T]): Stream[Stream[T]] = + private def removeChunks[T](n: Int, xs: LazyList[T]): LazyList[LazyList[T]] = if (xs.isEmpty) empty else if (xs.tail.isEmpty) cons(empty, empty) else { @@ -75,19 +75,19 @@ object Shrink extends ShrinkLowPriority { lazy val xs1 = xs.take(n1) lazy val xs2 = xs.drop(n1) lazy val xs3 = - for (ys1 <- removeChunks(n1, xs1) if !ys1.isEmpty) yield ys1 append xs2 + for (ys1 <- removeChunks(n1, xs1) if !ys1.isEmpty) yield ys1 lazyAppendedAll xs2 lazy val xs4 = - for (ys2 <- removeChunks(n2, xs2) if !ys2.isEmpty) yield xs1 append ys2 + for (ys2 <- removeChunks(n2, xs2) if !ys2.isEmpty) yield xs1 lazyAppendedAll ys2 cons(xs1, cons(xs2, interleave(xs3, xs4))) } - private def shrinkOne[T : Shrink](zs: Stream[T]): Stream[Stream[T]] = + private def shrinkOne[T : Shrink](zs: LazyList[T]): LazyList[LazyList[T]] = if (zs.isEmpty) empty else { val x = zs.head val xs = zs.tail - shrink(x).map(cons(_,xs)).append(shrinkOne(xs).map(cons(x,_))) + shrink(x).map(cons(_,xs)).lazyAppendedAll(shrinkOne(xs).map(cons(x,_))) } /** Shrink instances for numeric data types */ @@ -114,7 +114,7 @@ object Shrink extends ShrinkLowPriority { T1:Shrink, T2:Shrink ]: Shrink[(T1,T2)] = Shrink { case (t1,t2) => - shrink(t1).map((_,t2)) append + shrink(t1).map((_,t2)) lazyAppendedAll shrink(t2).map((t1,_)) } @@ -123,8 +123,8 @@ object Shrink extends ShrinkLowPriority { T1:Shrink, T2:Shrink, T3:Shrink ]: Shrink[(T1,T2,T3)] = Shrink { case (t1,t2,t3) => - shrink(t1).map((_, t2, t3)) append - shrink(t2).map((t1, _, t3)) append + shrink(t1).map((_, t2, t3)) lazyAppendedAll + shrink(t2).map((t1, _, t3)) lazyAppendedAll shrink(t3).map((t1, t2, _)) } @@ -133,9 +133,9 @@ object Shrink extends ShrinkLowPriority { T1:Shrink, T2:Shrink, T3:Shrink, T4:Shrink ]: Shrink[(T1,T2,T3,T4)] = Shrink { case (t1,t2,t3,t4) => - shrink(t1).map((_, t2, t3, t4)) append - shrink(t2).map((t1, _, t3, t4)) append - shrink(t3).map((t1, t2, _, t4)) append + shrink(t1).map((_, t2, t3, t4)) lazyAppendedAll + shrink(t2).map((t1, _, t3, t4)) lazyAppendedAll + shrink(t3).map((t1, t2, _, t4)) lazyAppendedAll shrink(t4).map((t1, t2, t3, _)) } @@ -144,10 +144,10 @@ object Shrink extends ShrinkLowPriority { T1:Shrink, T2:Shrink, T3:Shrink, T4:Shrink, T5:Shrink ]: Shrink[(T1,T2,T3,T4,T5)] = Shrink { case (t1,t2,t3,t4,t5) => - shrink(t1).map((_, t2, t3, t4, t5)) append - shrink(t2).map((t1, _, t3, t4, t5)) append - shrink(t3).map((t1, t2, _, t4, t5)) append - shrink(t4).map((t1, t2, t3, _, t5)) append + shrink(t1).map((_, t2, t3, t4, t5)) lazyAppendedAll + shrink(t2).map((t1, _, t3, t4, t5)) lazyAppendedAll + shrink(t3).map((t1, t2, _, t4, t5)) lazyAppendedAll + shrink(t4).map((t1, t2, t3, _, t5)) lazyAppendedAll shrink(t5).map((t1, t2, t3, t4, _)) } @@ -156,11 +156,11 @@ object Shrink extends ShrinkLowPriority { T1:Shrink, T2:Shrink, T3:Shrink, T4:Shrink, T5:Shrink, T6:Shrink ]: Shrink[(T1,T2,T3,T4,T5,T6)] = Shrink { case (t1,t2,t3,t4,t5,t6) => - shrink(t1).map((_, t2, t3, t4, t5, t6)) append - shrink(t2).map((t1, _, t3, t4, t5, t6)) append - shrink(t3).map((t1, t2, _, t4, t5, t6)) append - shrink(t4).map((t1, t2, t3, _, t5, t6)) append - shrink(t5).map((t1, t2, t3, t4, _, t6)) append + shrink(t1).map((_, t2, t3, t4, t5, t6)) lazyAppendedAll + shrink(t2).map((t1, _, t3, t4, t5, t6)) lazyAppendedAll + shrink(t3).map((t1, t2, _, t4, t5, t6)) lazyAppendedAll + shrink(t4).map((t1, t2, t3, _, t5, t6)) lazyAppendedAll + shrink(t5).map((t1, t2, t3, t4, _, t6)) lazyAppendedAll shrink(t6).map((t1, t2, t3, t4, t5, _)) } @@ -169,12 +169,12 @@ object Shrink extends ShrinkLowPriority { T1:Shrink, T2:Shrink, T3:Shrink, T4:Shrink, T5:Shrink, T6:Shrink, T7:Shrink ]: Shrink[(T1,T2,T3,T4,T5,T6,T7)] = Shrink { case (t1,t2,t3,t4,t5,t6,t7) => - shrink(t1).map((_, t2, t3, t4, t5, t6, t7)) append - shrink(t2).map((t1, _, t3, t4, t5, t6, t7)) append - shrink(t3).map((t1, t2, _, t4, t5, t6, t7)) append - shrink(t4).map((t1, t2, t3, _, t5, t6, t7)) append - shrink(t5).map((t1, t2, t3, t4, _, t6, t7)) append - shrink(t6).map((t1, t2, t3, t4, t5, _, t7)) append + shrink(t1).map((_, t2, t3, t4, t5, t6, t7)) lazyAppendedAll + shrink(t2).map((t1, _, t3, t4, t5, t6, t7)) lazyAppendedAll + shrink(t3).map((t1, t2, _, t4, t5, t6, t7)) lazyAppendedAll + shrink(t4).map((t1, t2, t3, _, t5, t6, t7)) lazyAppendedAll + shrink(t5).map((t1, t2, t3, t4, _, t6, t7)) lazyAppendedAll + shrink(t6).map((t1, t2, t3, t4, t5, _, t7)) lazyAppendedAll shrink(t7).map((t1, t2, t3, t4, t5, t6, _)) } @@ -184,13 +184,13 @@ object Shrink extends ShrinkLowPriority { T7:Shrink, T8:Shrink ]: Shrink[(T1,T2,T3,T4,T5,T6,T7,T8)] = Shrink { case (t1,t2,t3,t4,t5,t6,t7,t8) => - shrink(t1).map((_, t2, t3, t4, t5, t6, t7, t8)) append - shrink(t2).map((t1, _, t3, t4, t5, t6, t7, t8)) append - shrink(t3).map((t1, t2, _, t4, t5, t6, t7, t8)) append - shrink(t4).map((t1, t2, t3, _, t5, t6, t7, t8)) append - shrink(t5).map((t1, t2, t3, t4, _, t6, t7, t8)) append - shrink(t6).map((t1, t2, t3, t4, t5, _, t7, t8)) append - shrink(t7).map((t1, t2, t3, t4, t5, t6, _, t8)) append + shrink(t1).map((_, t2, t3, t4, t5, t6, t7, t8)) lazyAppendedAll + shrink(t2).map((t1, _, t3, t4, t5, t6, t7, t8)) lazyAppendedAll + shrink(t3).map((t1, t2, _, t4, t5, t6, t7, t8)) lazyAppendedAll + shrink(t4).map((t1, t2, t3, _, t5, t6, t7, t8)) lazyAppendedAll + shrink(t5).map((t1, t2, t3, t4, _, t6, t7, t8)) lazyAppendedAll + shrink(t6).map((t1, t2, t3, t4, t5, _, t7, t8)) lazyAppendedAll + shrink(t7).map((t1, t2, t3, t4, t5, t6, _, t8)) lazyAppendedAll shrink(t8).map((t1, t2, t3, t4, t5, t6, t7, _)) } @@ -200,14 +200,14 @@ object Shrink extends ShrinkLowPriority { T7:Shrink, T8:Shrink, T9:Shrink ]: Shrink[(T1,T2,T3,T4,T5,T6,T7,T8,T9)] = Shrink { case (t1,t2,t3,t4,t5,t6,t7,t8,t9) => - shrink(t1).map((_, t2, t3, t4, t5, t6, t7, t8, t9)) append - shrink(t2).map((t1, _, t3, t4, t5, t6, t7, t8, t9)) append - shrink(t3).map((t1, t2, _, t4, t5, t6, t7, t8, t9)) append - shrink(t4).map((t1, t2, t3, _, t5, t6, t7, t8, t9)) append - shrink(t5).map((t1, t2, t3, t4, _, t6, t7, t8, t9)) append - shrink(t6).map((t1, t2, t3, t4, t5, _, t7, t8, t9)) append - shrink(t7).map((t1, t2, t3, t4, t5, t6, _, t8, t9)) append - shrink(t8).map((t1, t2, t3, t4, t5, t6, t7, _, t9)) append + shrink(t1).map((_, t2, t3, t4, t5, t6, t7, t8, t9)) lazyAppendedAll + shrink(t2).map((t1, _, t3, t4, t5, t6, t7, t8, t9)) lazyAppendedAll + shrink(t3).map((t1, t2, _, t4, t5, t6, t7, t8, t9)) lazyAppendedAll + shrink(t4).map((t1, t2, t3, _, t5, t6, t7, t8, t9)) lazyAppendedAll + shrink(t5).map((t1, t2, t3, t4, _, t6, t7, t8, t9)) lazyAppendedAll + shrink(t6).map((t1, t2, t3, t4, t5, _, t7, t8, t9)) lazyAppendedAll + shrink(t7).map((t1, t2, t3, t4, t5, t6, _, t8, t9)) lazyAppendedAll + shrink(t8).map((t1, t2, t3, t4, t5, t6, t7, _, t9)) lazyAppendedAll shrink(t9).map((t1, t2, t3, t4, t5, t6, t7, t8, _)) } @@ -221,7 +221,7 @@ object Shrink extends ShrinkLowPriority { implicit val shrinkDuration: Shrink[Duration] = Shrink { case d: FiniteDuration => shrinkFiniteDuration.shrink(d) - case _ => Stream.empty + case _ => LazyList.empty } /** Transform a Shrink[T] to a Shrink[U] where T and U are two isomorphic types @@ -244,15 +244,15 @@ final class ShrinkIntegral[T](implicit ev: Integral[T]) extends Shrink[T] { val skipNegation = gteq(negate(one), one) // assumes x is non-zero. - private def halves(x: T): Stream[T] = { + private def halves(x: T): LazyList[T] = { val q = quot(x, two) - if (equiv(q, zero)) Stream(zero) + if (equiv(q, zero)) LazyList(zero) else if (skipNegation) q #:: halves(q) else q #:: negate(q) #:: halves(q) } - def shrink(x: T): Stream[T] = - if (equiv(x, zero)) Stream.empty[T] else halves(x) + def shrink(x: T): LazyList[T] = + if (equiv(x, zero)) LazyList.empty[T] else halves(x) } final class ShrinkFractional[T](implicit ev: Fractional[T]) extends Shrink[T] { @@ -267,9 +267,9 @@ final class ShrinkFractional[T](implicit ev: Fractional[T]) extends Shrink[T] { def closeToZero(x: T): Boolean = lteq(abs(x), small) // assumes x is not close to zero - private def halves(x: T): Stream[T] = { + private def halves(x: T): LazyList[T] = { val q = div(x, two) - if (closeToZero(q)) Stream(zero) + if (closeToZero(q)) LazyList(zero) else q #:: negate(q) #:: halves(q) } @@ -282,7 +282,7 @@ final class ShrinkFractional[T](implicit ev: Fractional[T]) extends Shrink[T] { !lt(div(x, two), x) } - def shrink(x: T): Stream[T] = - if (closeToZero(x) || isUnusual(x)) Stream.empty[T] + def shrink(x: T): LazyList[T] = + if (closeToZero(x) || isUnusual(x)) LazyList.empty[T] else halves(x) } diff --git a/src/main/scala/org/scalacheck/Test.scala b/src/main/scala/org/scalacheck/Test.scala index 67ec6cf46..58fb8e2db 100644 --- a/src/main/scala/org/scalacheck/Test.scala +++ b/src/main/scala/org/scalacheck/Test.scala @@ -370,7 +370,7 @@ object Test { } /** Check a set of properties. */ - def checkProperties(prms: Parameters, ps: Properties): Seq[(String,Result)] = { + def checkProperties(prms: Parameters, ps: Properties): collection.Seq[(String,Result)] = { val params = ps.overrideParameters(prms) val propertyFilter = prms.propFilter.map(_.r) diff --git a/src/main/scala/org/scalacheck/commands/Commands.scala b/src/main/scala/org/scalacheck/commands/Commands.scala index 1cf097c9a..6d8985f72 100644 --- a/src/main/scala/org/scalacheck/commands/Commands.scala +++ b/src/main/scala/org/scalacheck/commands/Commands.scala @@ -55,15 +55,15 @@ trait Commands { * (a singleton [[Sut]]), implement this method the following way: * * {{{ - * def canCreateNewSut(newState: State, initSuts: Traversable[State] - * runningSuts: Traversable[Sut] + * def canCreateNewSut(newState: State, initSuts: Iterable[State] + * runningSuts: Iterable[Sut] * ) = { * initSuts.isEmpty && runningSuts.isEmpty * } * }}} */ - def canCreateNewSut(newState: State, initSuts: Traversable[State], - runningSuts: Traversable[Sut]): Boolean + def canCreateNewSut(newState: State, initSuts: Iterable[State], + runningSuts: Iterable[Sut]): Boolean /** Create a new [[Sut]] instance with an internal state that * corresponds to the provided abstract state instance. The provided state @@ -270,8 +270,8 @@ trait Commands { ) private implicit val shrinkActions = Shrink[Actions] { as => - val shrinkedCmds: Stream[Actions] = - Shrink.shrink(as.seqCmds).map(cs => as.copy(seqCmds = cs)) append + val shrinkedCmds: LazyList[Actions] = + Shrink.shrink(as.seqCmds).map(cs => as.copy(seqCmds = cs)) lazyAppendedAll Shrink.shrink(as.parCmds).map(cs => as.copy(parCmds = cs)) Shrink.shrinkWithOrig[State](as.s)(shrinkState) flatMap { state => diff --git a/src/main/scala/org/scalacheck/util/ArrayListBuilder.scala b/src/main/scala/org/scalacheck/util/ArrayListBuilder.scala new file mode 100644 index 000000000..f74b9ee63 --- /dev/null +++ b/src/main/scala/org/scalacheck/util/ArrayListBuilder.scala @@ -0,0 +1,17 @@ +package org.scalacheck.util + +import java.util +import java.util.ArrayList + +import scala.collection.mutable + +private[scalacheck] class ArrayListBuilder[T] + extends mutable.Builder[T, util.ArrayList[T]] { + val al = new ArrayList[T] + def addOne(x: T) = { + al.add(x) + this + } + def clear() = al.clear() + def result() = al +} diff --git a/src/main/scala/org/scalacheck/util/Buildable.scala b/src/main/scala/org/scalacheck/util/Buildable.scala index 2e8d5fd80..a9226ab67 100644 --- a/src/main/scala/org/scalacheck/util/Buildable.scala +++ b/src/main/scala/org/scalacheck/util/Buildable.scala @@ -9,12 +9,11 @@ package org.scalacheck.util -import collection.{ Map => _, _ } -import generic.CanBuildFrom +import scala.collection.{mutable, Map => _, _} trait Buildable[T,C] extends Serializable { def builder: mutable.Builder[T,C] - def fromIterable(it: Traversable[T]): C = { + def fromIterable(it: Iterable[T]): C = { val b = builder b ++= it b.result() @@ -22,49 +21,41 @@ trait Buildable[T,C] extends Serializable { } /** - * CanBuildFrom instances implementing Serializable, so that the objects capturing those can be + * Factory instances implementing Serializable, so that the objects capturing those can be * serializable too. */ object SerializableCanBuildFroms { - implicit def listCanBuildFrom[T]: CanBuildFrom[List[T], T, List[T]] = - new CanBuildFrom[List[T], T, List[T]] with Serializable { - def apply(from: List[T]) = List.newBuilder[T] - def apply() = List.newBuilder[T] + implicit def listFactory[T]: Factory[T, List[T]] = + new Factory[T, List[T]] with Serializable { + def fromSpecific(source: IterableOnce[T]): List[T] = List.from(source) + def newBuilder: mutable.Builder[T, List[T]] = List.newBuilder[T] } - implicit def bitsetCanBuildFrom[T]: CanBuildFrom[BitSet, Int, BitSet] = - new CanBuildFrom[BitSet, Int, BitSet] with Serializable { - def apply(from: BitSet) = BitSet.newBuilder - def apply() = BitSet.newBuilder + implicit def bitsetFactory[T]: Factory[Int, BitSet] = + new Factory[Int, BitSet] with Serializable { + def fromSpecific(source: IterableOnce[Int]) = BitSet.fromSpecific(source) + def newBuilder: mutable.Builder[Int, BitSet] = BitSet.newBuilder } - implicit def mapCanBuildFrom[T, U]: CanBuildFrom[Map[T, U], (T, U), Map[T, U]] = - new CanBuildFrom[Map[T, U], (T, U), Map[T, U]] with Serializable { - def apply(from: Map[T, U]) = Map.newBuilder[T, U] - def apply() = Map.newBuilder[T, U] + implicit def mapFactory[T, U]: Factory[(T, U), Map[T, U]] = + new Factory[(T, U), Map[T, U]] with Serializable { + def fromSpecific(source: IterableOnce[(T, U)]) = Map.from(source) + def newBuilder: mutable.Builder[(T, U), Map[T, U]] = Map.newBuilder[T, U] } } object Buildable { - implicit def buildableCanBuildFrom[T,F,C](implicit c: CanBuildFrom[F,T,C]) = + implicit def buildableFactory[T,C](implicit f: Factory[T,C]) = new Buildable[T,C] { - def builder = c.apply + def builder = f.newBuilder } import java.util.ArrayList implicit def buildableArrayList[T] = new Buildable[T,ArrayList[T]] { - def builder = new mutable.Builder[T,ArrayList[T]] { - val al = new ArrayList[T] - def +=(x: T) = { - al.add(x) - this - } - def clear() = al.clear() - def result() = al - } + def builder = new ArrayListBuilder[T] } } diff --git a/src/main/scala/org/scalacheck/util/FreqMap.scala b/src/main/scala/org/scalacheck/util/FreqMap.scala index a62512930..be6e2635d 100644 --- a/src/main/scala/org/scalacheck/util/FreqMap.scala +++ b/src/main/scala/org/scalacheck/util/FreqMap.scala @@ -32,7 +32,7 @@ sealed trait FreqMap[T] extends Serializable { def ++(fm: FreqMap[T]): FreqMap[T] = new FreqMap[T] { private val keys = FreqMap.this.underlying.keySet ++ fm.underlying.keySet - private val mappings = keys.toStream.map { x => + private val mappings = keys.to(LazyList).map { x => (x, fm.getCount(x).getOrElse(0) + FreqMap.this.getCount(x).getOrElse(0)) } val underlying = scala.collection.immutable.Map(mappings: _*) @@ -43,7 +43,7 @@ sealed trait FreqMap[T] extends Serializable { val underlying = FreqMap.this.underlying transform { case (x,n) => n - fm.getCount(x).getOrElse(0) } - lazy val total = (0 /: underlying.valuesIterator) (_ + _) + lazy val total = underlying.valuesIterator.foldLeft(0)(_ + _) } def getCount(t: T) = underlying.get(t) diff --git a/src/test/scala/org/scalacheck/ShrinkSpecification.scala b/src/test/scala/org/scalacheck/ShrinkSpecification.scala index ad65260ad..e9a172e18 100644 --- a/src/test/scala/org/scalacheck/ShrinkSpecification.scala +++ b/src/test/scala/org/scalacheck/ShrinkSpecification.scala @@ -16,10 +16,10 @@ import scala.concurrent.duration.{Duration, FiniteDuration} object ShrinkSpecification extends Properties("Shrink") { - def shrinkClosure[T : Shrink](x: T): Stream[T] = { + def shrinkClosure[T : Shrink](x: T): LazyList[T] = { val xs = shrink[T](x) if(xs.isEmpty) xs - else xs.append(xs.take(1).map(shrinkClosure[T]).flatten) + else xs.lazyAppendedAll(xs.take(1).map(shrinkClosure[T]).flatten) } property("byte") = forAll { n: Byte => @@ -104,7 +104,7 @@ object ShrinkSpecification extends Properties("Shrink") { /* Ensure that shrink[T] terminates. (#244) * - * Let's say shrinking "terminates" when the stream of values + * Let's say shrinking "terminates" when the lazy list of values * becomes empty. We can empirically determine the longest possible * sequence for a given type before termination. (Usually this * involves using the type's MinValue.) diff --git a/src/test/scala/org/scalacheck/util/BuildableSpecification.scala b/src/test/scala/org/scalacheck/util/BuildableSpecification.scala index 2311a8a65..cc89afa77 100644 --- a/src/test/scala/org/scalacheck/util/BuildableSpecification.scala +++ b/src/test/scala/org/scalacheck/util/BuildableSpecification.scala @@ -17,12 +17,12 @@ import collection._ object BuildableSpecification { def container[C[_]](implicit evb: Buildable[String, C[String]], - evt: C[String] => Traversable[String] + evt: C[String] => Iterable[String] ) = Gen.containerOf[C, String](Gen.alphaStr) implicit val listGen: Gen[List[String]] = container[List] - implicit val streamGen: Gen[Stream[String]] = container[Stream] + implicit val lazyListGen: Gen[LazyList[String]] = container[LazyList] implicit val arrayGen: Gen[Array[String]] = container[Array] From b64e21f079187b06bc3f4d85adaefb9e23b7a0c7 Mon Sep 17 00:00:00 2001 From: Lukas Rytz Date: Fri, 18 May 2018 18:27:53 +0200 Subject: [PATCH 02/10] Cross-build from a single branch --- .travis.yml | 2 + build.sbt | 26 +++++-- .../org/scalacheck/CogenSpecification.scala | 3 + .../org/scalacheck/GenSpecification.scala | 6 +- project/plugin.sbt | 2 +- .../org/scalacheck/ScalaVersionSpecific.scala | 63 +++++++++++++++++ .../org/scalacheck/ScalaVersionSpecific.scala | 67 +++++++++++++++++++ src/main/scala/org/scalacheck/Cogen.scala | 3 +- src/main/scala/org/scalacheck/Gen.scala | 13 ++-- src/main/scala/org/scalacheck/Prop.scala | 1 + src/main/scala/org/scalacheck/Shrink.scala | 5 +- .../org/scalacheck/commands/Commands.scala | 1 + .../scalacheck/util/ArrayListBuilder.scala | 17 ----- .../scala/org/scalacheck/util/Buildable.scala | 24 ++----- .../scala/org/scalacheck/util/FreqMap.scala | 4 +- .../org/scalacheck/ShrinkSpecification.scala | 1 + .../util/BuildableSpecification.scala | 8 ++- 17 files changed, 189 insertions(+), 57 deletions(-) create mode 100644 src/main/scala-2.13+/org/scalacheck/ScalaVersionSpecific.scala create mode 100644 src/main/scala-2.13-/org/scalacheck/ScalaVersionSpecific.scala delete mode 100644 src/main/scala/org/scalacheck/util/ArrayListBuilder.scala diff --git a/.travis.yml b/.travis.yml index bcc8f5afa..59a41fcbb 100644 --- a/.travis.yml +++ b/.travis.yml @@ -46,3 +46,5 @@ matrix: exclude: - scala: 2.10.7 env: PLATFORM=js SBT_PARALLEL=true WORKERS=1 DEPLOY=true SCALAJS_VERSION=1.0.0-M3 + - scala: 2.13.0-M4 + env: PLATFORM=js SBT_PARALLEL=true WORKERS=1 DEPLOY=true SCALAJS_VERSION=1.0.0-M3 diff --git a/build.sbt b/build.sbt index 71913fcae..54b59a6b4 100644 --- a/build.sbt +++ b/build.sbt @@ -1,5 +1,7 @@ sourceDirectory := file("dummy source directory") +val scalaMajorVersion = SettingKey[Int]("scalaMajorVersion") + scalaVersionSettings lazy val versionNumber = "1.14.1" @@ -10,7 +12,13 @@ lazy val travisCommit = Option(System.getenv().get("TRAVIS_COMMIT")) lazy val scalaVersionSettings = Seq( scalaVersion := "2.12.6", - crossScalaVersions := Seq("2.10.7", "2.11.12", "2.13.0-M4", scalaVersion.value) + crossScalaVersions := Seq("2.10.7", "2.11.12", "2.13.0-M4", scalaVersion.value), + scalaMajorVersion := { + val v = scalaVersion.value + CrossVersion.partialVersion(v).map(_._2.toInt).getOrElse { + throw new RuntimeException(s"could not get Scala major version from $v") + } + } ) lazy val sharedSettings = MimaSettings.settings ++ scalaVersionSettings ++ Seq( @@ -43,6 +51,11 @@ lazy val sharedSettings = MimaSettings.settings ++ scalaVersionSettings ++ Seq( unmanagedSourceDirectories in Compile += (baseDirectory in LocalRootProject).value / "src" / "main" / "scala", + unmanagedSourceDirectories in Compile += { + val s = if (scalaMajorVersion.value >= 13) "+" else "-" + (baseDirectory in LocalRootProject).value / "src" / "main" / s"scala-2.13$s" + }, + unmanagedSourceDirectories in Test += (baseDirectory in LocalRootProject).value / "src" / "test" / "scala", resolvers += "sonatype" at "https://oss.sonatype.org/content/repositories/releases", @@ -54,17 +67,18 @@ lazy val sharedSettings = MimaSettings.settings ++ scalaVersionSettings ++ Seq( "-encoding", "UTF-8", "-feature", "-unchecked", - "-Xfatal-warnings", "-Xfuture", "-Ywarn-dead-code", "-Ywarn-inaccessible", "-Ywarn-nullary-override", "-Ywarn-nullary-unit", "-Ywarn-numeric-widen") ++ { - scalaBinaryVersion.value match { - case "2.10" => Seq("-Xlint") - case "2.11" => Seq("-Xlint", "-Ywarn-infer-any", "-Ywarn-unused-import") - case _ => Seq("-Xlint:-unused", "-Ywarn-infer-any", "-Ywarn-unused-import", "-Ywarn-unused:-patvars,-implicits,-locals,-privates,-explicits") + val modern = Seq("-Xlint:-unused", "-Ywarn-infer-any", "-Ywarn-unused-import", "-Ywarn-unused:-patvars,-implicits,-locals,-privates,-explicits") + scalaMajorVersion.value match { + case 10 => Seq("-Xfatal-warnings", "-Xlint") + case 11 => Seq("-Xfatal-warnings", "-Xlint", "-Ywarn-infer-any", "-Ywarn-unused-import") + case 12 => "-Xfatal-warnings" +: modern + case 13 => modern } }, diff --git a/jvm/src/test/scala/org/scalacheck/CogenSpecification.scala b/jvm/src/test/scala/org/scalacheck/CogenSpecification.scala index b25a6488f..617184bfd 100644 --- a/jvm/src/test/scala/org/scalacheck/CogenSpecification.scala +++ b/jvm/src/test/scala/org/scalacheck/CogenSpecification.scala @@ -5,6 +5,8 @@ import org.scalacheck.Gen.listOfN import org.scalacheck.GenSpecification.arbSeed import org.scalacheck.Prop.forAll import org.scalacheck.rng.Seed +import ScalaVersionSpecific._ + import scala.util.Try import scala.concurrent.duration.{Duration, FiniteDuration} @@ -140,6 +142,7 @@ object CogenSpecification extends Properties("Cogen") { include(cogenLaws[String], "cogenString.") include(cogenLaws[List[Int]], "cogenList.") include(cogenLaws[Vector[Int]], "cogenVector.") + include(cogenLaws[Stream[Int]], "cogenStream.") include(cogenLaws[LazyList[Int]], "cogenLazyList.") include(cogenLaws[Set[Int]], "cogenSet.") include(cogenLaws[Map[Int, Int]], "cogenMap.") diff --git a/jvm/src/test/scala/org/scalacheck/GenSpecification.scala b/jvm/src/test/scala/org/scalacheck/GenSpecification.scala index 113898a5b..7b1f6dae3 100644 --- a/jvm/src/test/scala/org/scalacheck/GenSpecification.scala +++ b/jvm/src/test/scala/org/scalacheck/GenSpecification.scala @@ -18,7 +18,7 @@ import Shrink._ import java.util.Date import scala.util.{Try, Success, Failure} -object GenSpecification extends Properties("Gen") { +object GenSpecification extends Properties("Gen") with GenSpecificationVersionSpecific { implicit val arbSeed: Arbitrary[Seed] = Arbitrary( arbitrary[Long] flatMap Seed.apply @@ -179,6 +179,10 @@ object GenSpecification extends Properties("Gen") { l.length == 0 } + property("infiniteStream") = forAll(infiniteStream(arbitrary[Int]), arbitrary[Short]) { (s, n) => + s.drop(n & 0xffff).nonEmpty + } + property("infiniteLazyList") = forAll(infiniteLazyList(arbitrary[Int]), arbitrary[Short]) { (s, n) => s.drop(n & 0xffff).nonEmpty } diff --git a/project/plugin.sbt b/project/plugin.sbt index a637c556e..5dea6ce83 100644 --- a/project/plugin.sbt +++ b/project/plugin.sbt @@ -3,7 +3,7 @@ addSbtPlugin("com.typesafe" % "sbt-mima-plugin" % "0.2.0") addSbtPlugin("com.jsuereth" % "sbt-pgp" % "1.1.1") val scalaJSVersion = - Option(System.getenv("SCALAJS_VERSION")).getOrElse("0.6.22") + Option(System.getenv("SCALAJS_VERSION")).getOrElse("0.6.23") addSbtPlugin("org.scala-js" % "sbt-scalajs" % scalaJSVersion) diff --git a/src/main/scala-2.13+/org/scalacheck/ScalaVersionSpecific.scala b/src/main/scala-2.13+/org/scalacheck/ScalaVersionSpecific.scala new file mode 100644 index 000000000..7f614c7ec --- /dev/null +++ b/src/main/scala-2.13+/org/scalacheck/ScalaVersionSpecific.scala @@ -0,0 +1,63 @@ +package org.scalacheck + +import java.util.ArrayList + +import scala.collection.{BitSet, Factory} +import scala.collection.mutable.Builder +import rng.Seed + +private[scalacheck] object ScalaVersionSpecific { + def toLazyList[T](i: IterableOnce[T]) = i.to(LazyList) + + def listFactory[T]: Factory[T, List[T]] = + new Factory[T, List[T]] with Serializable { + def fromSpecific(source: IterableOnce[T]): List[T] = List.from(source) + def newBuilder: Builder[T, List[T]] = List.newBuilder[T] + } + + def bitsetFactory[T]: Factory[Int, BitSet] = + new Factory[Int, BitSet] with Serializable { + def fromSpecific(source: IterableOnce[Int]) = BitSet.fromSpecific(source) + def newBuilder: Builder[Int, BitSet] = BitSet.newBuilder + } + + def mapFactory[T, U]: Factory[(T, U), Map[T, U]] = + new Factory[(T, U), Map[T, U]] with Serializable { + def fromSpecific(source: IterableOnce[(T, U)]) = Map.from(source) + def newBuilder: Builder[(T, U), Map[T, U]] = Map.newBuilder[T, U] + } +} + +private[scalacheck] trait GenVersionSpecific { + + /** Generates an infinite lazy list. */ + def infiniteLazyList[T](g: => Gen[T]): Gen[LazyList[T]] = { + def unfold[A, S](z: S)(f: S => Option[(A, S)]): LazyList[A] = f(z) match { + case Some((h, s)) => h #:: unfold(s)(f) + case None => LazyList.empty + } + Gen.gen { (p, seed0) => + new Gen.R[LazyList[T]] { + val result: Option[LazyList[T]] = Some(unfold(seed0)(s => Some(g.pureApply(p, s) -> s.next))) + val seed: Seed = seed0.next + } + } + } +} + +private[scalacheck] trait GenSpecificationVersionSpecific + +private[scalacheck] trait CogenVersionSpecific { + implicit def cogenStream[A: Cogen]: Cogen[Stream[A]] = + Cogen.it(_.iterator) +} + +private[scalacheck] class ArrayListBuilder[T] extends Builder[T, ArrayList[T]] { + private val al = new ArrayList[T] + def addOne(x: T): this.type = { + al.add(x) + this + } + def clear(): Unit = al.clear() + def result(): ArrayList[T] = al +} diff --git a/src/main/scala-2.13-/org/scalacheck/ScalaVersionSpecific.scala b/src/main/scala-2.13-/org/scalacheck/ScalaVersionSpecific.scala new file mode 100644 index 000000000..bdd32cc27 --- /dev/null +++ b/src/main/scala-2.13-/org/scalacheck/ScalaVersionSpecific.scala @@ -0,0 +1,67 @@ +package org.scalacheck + +import java.util.ArrayList + +import scala.collection.generic.{CanBuildFrom, Sorted} +import scala.collection.immutable.Stream +import scala.collection.mutable.Builder +import scala.collection.{BitSet, TraversableOnce} + +private[scalacheck] object ScalaVersionSpecific { + def toLazyList[T](i: TraversableOnce[T]) = i.toStream + + type Factory[-A, +C] = CanBuildFrom[Nothing, A, C] + + def listFactory[T]: CanBuildFrom[List[T], T, List[T]] = + new CanBuildFrom[List[T], T, List[T]] with Serializable { + def apply(from: List[T]) = List.newBuilder[T] + def apply() = List.newBuilder[T] + } + + def bitsetFactory[T]: CanBuildFrom[BitSet, Int, BitSet] = + new CanBuildFrom[BitSet, Int, BitSet] with Serializable { + def apply(from: BitSet) = BitSet.newBuilder + def apply() = BitSet.newBuilder + } + + def mapFactory[T, U]: CanBuildFrom[Map[T, U], (T, U), Map[T, U]] = + new CanBuildFrom[Map[T, U], (T, U), Map[T, U]] with Serializable { + def apply(from: Map[T, U]) = Map.newBuilder[T, U] + def apply() = Map.newBuilder[T, U] + } + + implicit class CBFExt[-A, +C](val cbf: CanBuildFrom[Nothing, A, C]) extends AnyVal { + def newBuilder: Builder[A, C] = cbf() + } + + type LazyList[+A] = Stream[A] + val LazyList = Stream + + implicit class StreamExt[+A](val s: Stream[A]) extends AnyVal { + def lazyAppendedAll[B >: A](rest: => TraversableOnce[B]): Stream[B] = s.append(rest) + } + + implicit class SortedExt[K, T <: Sorted[K, T]](val s: Sorted[K, T]) extends AnyVal { + def rangeFrom(from: K): T = s.from(from) + def rangeTo(to: K): T = s.to(to) + def rangeUntil(until: K): T = s.until(until) + } +} + +private[scalacheck] trait GenVersionSpecific +private[scalacheck] trait CogenVersionSpecific + +// Used in tests +private[scalacheck] trait GenSpecificationVersionSpecific { + def infiniteLazyList[T](g: => Gen[T]): Gen[Stream[T]] = Gen.infiniteStream(g) +} + +private[scalacheck] class ArrayListBuilder[T] extends Builder[T, ArrayList[T]] { + private val al = new ArrayList[T] + def +=(x: T): this.type = { + al.add(x) + this + } + def clear(): Unit = al.clear() + def result(): ArrayList[T] = al +} diff --git a/src/main/scala/org/scalacheck/Cogen.scala b/src/main/scala/org/scalacheck/Cogen.scala index 6af873030..2275392e9 100644 --- a/src/main/scala/org/scalacheck/Cogen.scala +++ b/src/main/scala/org/scalacheck/Cogen.scala @@ -16,6 +16,7 @@ import scala.util.{Failure, Success, Try} import scala.concurrent.duration.{Duration, FiniteDuration} import java.math.BigInteger import rng.Seed +import ScalaVersionSpecific._ sealed trait Cogen[T] extends Serializable { @@ -28,7 +29,7 @@ sealed trait Cogen[T] extends Serializable { Cogen((seed: Seed, s: S) => perturb(seed, f(s))) } -object Cogen extends CogenArities with CogenLowPriority { +object Cogen extends CogenArities with CogenLowPriority with CogenVersionSpecific { // for binary compatibility private[scalacheck] def apply[T](ev: Cogen[T]): Cogen[T] = ev diff --git a/src/main/scala/org/scalacheck/Gen.scala b/src/main/scala/org/scalacheck/Gen.scala index 7d94188a9..e45679e7b 100644 --- a/src/main/scala/org/scalacheck/Gen.scala +++ b/src/main/scala/org/scalacheck/Gen.scala @@ -15,6 +15,7 @@ import language.implicitConversions import rng.Seed import util.Buildable import util.SerializableCanBuildFroms._ +import ScalaVersionSpecific._ import scala.annotation.tailrec import scala.collection.immutable.TreeMap @@ -200,7 +201,7 @@ sealed abstract class Gen[+T] extends Serializable { self => Gen.gen((p, seed) => doApply(p, f(seed))) } -object Gen extends GenArities{ +object Gen extends GenArities with GenVersionSpecific { //// Private interface //// @@ -656,14 +657,14 @@ object Gen extends GenArities{ def mapOfN[T,U](n: Int, g: Gen[(T,U)]) = buildableOfN[Map[T,U],(T,U)](n,g) /** Generates an infinite lazy list. */ - def infiniteLazyList[T](g: => Gen[T]): Gen[LazyList[T]] = { - def unfold[A, S](z: S)(f: S => Option[(A, S)]): LazyList[A] = f(z) match { + def infiniteStream[T](g: => Gen[T]): Gen[Stream[T]] = { + def unfold[A, S](z: S)(f: S => Option[(A, S)]): Stream[A] = f(z) match { case Some((h, s)) => h #:: unfold(s)(f) - case None => LazyList.empty + case None => Stream.empty } gen { (p, seed0) => - new R[LazyList[T]] { - val result: Option[LazyList[T]] = Some(unfold(seed0)(s => Some(g.pureApply(p, s) -> s.next))) + new R[Stream[T]] { + val result: Option[Stream[T]] = Some(unfold(seed0)(s => Some(g.pureApply(p, s) -> s.next))) val seed: Seed = seed0.next } } diff --git a/src/main/scala/org/scalacheck/Prop.scala b/src/main/scala/org/scalacheck/Prop.scala index 003bfb4c0..cc28a4e0f 100644 --- a/src/main/scala/org/scalacheck/Prop.scala +++ b/src/main/scala/org/scalacheck/Prop.scala @@ -15,6 +15,7 @@ import language.reflectiveCalls import rng.Seed import util.{Pretty, ConsoleReporter} import scala.annotation.tailrec +import ScalaVersionSpecific._ /** Helper class to satisfy ScalaJS compilation. Do not use this directly, * use `Prop.apply` instead. */ diff --git a/src/main/scala/org/scalacheck/Shrink.scala b/src/main/scala/org/scalacheck/Shrink.scala index d25b66c5c..8d397e86a 100644 --- a/src/main/scala/org/scalacheck/Shrink.scala +++ b/src/main/scala/org/scalacheck/Shrink.scala @@ -14,6 +14,7 @@ import language.higherKinds import util.Buildable import util.SerializableCanBuildFroms._ import scala.concurrent.duration.{Duration, FiniteDuration} +import ScalaVersionSpecific._ sealed abstract class Shrink[T] extends Serializable { def shrink(x: T): LazyList[T] @@ -53,7 +54,7 @@ object Shrink extends ShrinkLowPriority { b: Buildable[T,C[T]] ): Shrink[C[T]] = Shrink { xs: C[T] => val ys = v(xs) - val zs = ys.to(LazyList) + val zs = toLazyList(ys) removeChunks(ys.size,zs).lazyAppendedAll(shrinkOne(zs)).map(b.fromIterable) } @@ -62,7 +63,7 @@ object Shrink extends ShrinkLowPriority { b: Buildable[(T,U),C[T,U]] ): Shrink[C[T,U]] = Shrink { xs: C[T,U] => val ys = v(xs) - val zs = ys.to(LazyList) + val zs = toLazyList(ys) removeChunks(ys.size,zs).lazyAppendedAll(shrinkOne(zs)).map(b.fromIterable) } diff --git a/src/main/scala/org/scalacheck/commands/Commands.scala b/src/main/scala/org/scalacheck/commands/Commands.scala index 6d8985f72..daa2c05f3 100644 --- a/src/main/scala/org/scalacheck/commands/Commands.scala +++ b/src/main/scala/org/scalacheck/commands/Commands.scala @@ -11,6 +11,7 @@ package org.scalacheck.commands import org.scalacheck._ import scala.util.{Try, Success, Failure} +import ScalaVersionSpecific._ /** An API for stateful testing in ScalaCheck. * diff --git a/src/main/scala/org/scalacheck/util/ArrayListBuilder.scala b/src/main/scala/org/scalacheck/util/ArrayListBuilder.scala deleted file mode 100644 index f74b9ee63..000000000 --- a/src/main/scala/org/scalacheck/util/ArrayListBuilder.scala +++ /dev/null @@ -1,17 +0,0 @@ -package org.scalacheck.util - -import java.util -import java.util.ArrayList - -import scala.collection.mutable - -private[scalacheck] class ArrayListBuilder[T] - extends mutable.Builder[T, util.ArrayList[T]] { - val al = new ArrayList[T] - def addOne(x: T) = { - al.add(x) - this - } - def clear() = al.clear() - def result() = al -} diff --git a/src/main/scala/org/scalacheck/util/Buildable.scala b/src/main/scala/org/scalacheck/util/Buildable.scala index a9226ab67..fc1936e4b 100644 --- a/src/main/scala/org/scalacheck/util/Buildable.scala +++ b/src/main/scala/org/scalacheck/util/Buildable.scala @@ -10,6 +10,8 @@ package org.scalacheck.util import scala.collection.{mutable, Map => _, _} +import org.scalacheck.{ScalaVersionSpecific, ArrayListBuilder} +import ScalaVersionSpecific._ trait Buildable[T,C] extends Serializable { def builder: mutable.Builder[T,C] @@ -25,25 +27,9 @@ trait Buildable[T,C] extends Serializable { * serializable too. */ object SerializableCanBuildFroms { - - implicit def listFactory[T]: Factory[T, List[T]] = - new Factory[T, List[T]] with Serializable { - def fromSpecific(source: IterableOnce[T]): List[T] = List.from(source) - def newBuilder: mutable.Builder[T, List[T]] = List.newBuilder[T] - } - - implicit def bitsetFactory[T]: Factory[Int, BitSet] = - new Factory[Int, BitSet] with Serializable { - def fromSpecific(source: IterableOnce[Int]) = BitSet.fromSpecific(source) - def newBuilder: mutable.Builder[Int, BitSet] = BitSet.newBuilder - } - - implicit def mapFactory[T, U]: Factory[(T, U), Map[T, U]] = - new Factory[(T, U), Map[T, U]] with Serializable { - def fromSpecific(source: IterableOnce[(T, U)]) = Map.from(source) - def newBuilder: mutable.Builder[(T, U), Map[T, U]] = Map.newBuilder[T, U] - } - + implicit def listFactory[T]: Factory[T, List[T]] = ScalaVersionSpecific.listFactory + implicit def bitsetFactory[T]: Factory[Int, BitSet] = ScalaVersionSpecific.bitsetFactory + implicit def mapFactory[T, U]: Factory[(T, U), Map[T, U]] = ScalaVersionSpecific.mapFactory } object Buildable { diff --git a/src/main/scala/org/scalacheck/util/FreqMap.scala b/src/main/scala/org/scalacheck/util/FreqMap.scala index be6e2635d..7f653939d 100644 --- a/src/main/scala/org/scalacheck/util/FreqMap.scala +++ b/src/main/scala/org/scalacheck/util/FreqMap.scala @@ -9,6 +9,8 @@ package org.scalacheck.util +import org.scalacheck.ScalaVersionSpecific._ + sealed trait FreqMap[T] extends Serializable { protected val underlying: scala.collection.immutable.Map[T,Int] val total: Int @@ -32,7 +34,7 @@ sealed trait FreqMap[T] extends Serializable { def ++(fm: FreqMap[T]): FreqMap[T] = new FreqMap[T] { private val keys = FreqMap.this.underlying.keySet ++ fm.underlying.keySet - private val mappings = keys.to(LazyList).map { x => + private val mappings = toLazyList(keys).map { x => (x, fm.getCount(x).getOrElse(0) + FreqMap.this.getCount(x).getOrElse(0)) } val underlying = scala.collection.immutable.Map(mappings: _*) diff --git a/src/test/scala/org/scalacheck/ShrinkSpecification.scala b/src/test/scala/org/scalacheck/ShrinkSpecification.scala index e9a172e18..69dd74bd0 100644 --- a/src/test/scala/org/scalacheck/ShrinkSpecification.scala +++ b/src/test/scala/org/scalacheck/ShrinkSpecification.scala @@ -11,6 +11,7 @@ package org.scalacheck import Prop.{forAll, forAllNoShrink, BooleanOperators} import Shrink.shrink +import ScalaVersionSpecific._ import scala.concurrent.duration.{Duration, FiniteDuration} diff --git a/src/test/scala/org/scalacheck/util/BuildableSpecification.scala b/src/test/scala/org/scalacheck/util/BuildableSpecification.scala index cc89afa77..2830a10d5 100644 --- a/src/test/scala/org/scalacheck/util/BuildableSpecification.scala +++ b/src/test/scala/org/scalacheck/util/BuildableSpecification.scala @@ -10,9 +10,9 @@ package org.scalacheck package util -import language.higherKinds - -import collection._ +import scala.collection._ +import scala.language.higherKinds +import ScalaVersionSpecific._ object BuildableSpecification { def container[C[_]](implicit @@ -22,6 +22,8 @@ object BuildableSpecification { implicit val listGen: Gen[List[String]] = container[List] + implicit val streamGen: Gen[Stream[String]] = container[Stream] + implicit val lazyListGen: Gen[LazyList[String]] = container[LazyList] implicit val arrayGen: Gen[Array[String]] = container[Array] From 4b253fb89a5a6e69fbbd368dafdfe8c62688d7c3 Mon Sep 17 00:00:00 2001 From: Lukas Rytz Date: Fri, 18 May 2018 21:17:41 +0200 Subject: [PATCH 03/10] Changes to make MiMa happy --- .travis.yml | 2 +- doc/UserGuide.md | 8 ++++---- .../src/test/scala/CommandsLevelDB.scala | 4 ++-- .../commands-nix/src/test/scala/CommandsNix.scala | 4 ++-- .../src/test/scala/CommandsRedis.scala | 4 ++-- .../scalacheck/commands/CommandsSpecification.scala | 4 ++-- .../org/scalacheck/ScalaVersionSpecific.scala | 4 ++-- src/main/scala/org/scalacheck/Cogen.scala | 3 +-- src/main/scala/org/scalacheck/Gen.scala | 2 +- .../scala/org/scalacheck/commands/Commands.scala | 8 ++++---- src/main/scala/org/scalacheck/util/Buildable.scala | 13 +++++++------ 11 files changed, 28 insertions(+), 28 deletions(-) diff --git a/.travis.yml b/.travis.yml index 59a41fcbb..3cd273e68 100644 --- a/.travis.yml +++ b/.travis.yml @@ -17,7 +17,7 @@ scala: - 2.10.7 - 2.11.12 - 2.12.6 - - 2.13.0-M3 + - 2.13.0-M4 jdk: - oraclejdk8 env: diff --git a/doc/UserGuide.md b/doc/UserGuide.md index c16949876..a8e48a843 100644 --- a/doc/UserGuide.md +++ b/doc/UserGuide.md @@ -873,15 +873,15 @@ object CounterSpecification extends Commands { * (a singleton [[Sut]]), implement this method the following way: * * {{{ - * def canCreateNewSut(newState: State, initSuts: Iterable[State] - * runningSuts: Iterable[Sut] + * def canCreateNewSut(newState: State, initSuts: Traversable[State] + * runningSuts: Traversable[Sut] * ) = { * initSuts.isEmpty && runningSuts.isEmpty * } * }}} */ - def canCreateNewSut(newState: State, initSuts: Iterable[State], - runningSuts: Iterable[Sut]): Boolean = true + def canCreateNewSut(newState: State, initSuts: Traversable[State], + runningSuts: Traversable[Sut]): Boolean = true /** The precondition for the initial state, when no commands yet have * run. This is used by ScalaCheck when command sequences are shrinked diff --git a/examples/commands-leveldb/src/test/scala/CommandsLevelDB.scala b/examples/commands-leveldb/src/test/scala/CommandsLevelDB.scala index 2c7a9cd75..28212075e 100644 --- a/examples/commands-leveldb/src/test/scala/CommandsLevelDB.scala +++ b/examples/commands-leveldb/src/test/scala/CommandsLevelDB.scala @@ -30,8 +30,8 @@ object LevelDBSpec extends Commands { def path = s"db_$name" } - def canCreateNewSut(newState: State, initSuts: Iterable[State], - runningSuts: Iterable[Sut] + def canCreateNewSut(newState: State, initSuts: Traversable[State], + runningSuts: Traversable[Sut] ) = { !initSuts.exists(_.name == newState.name) && !runningSuts.exists(_.name == newState.name) diff --git a/examples/commands-nix/src/test/scala/CommandsNix.scala b/examples/commands-nix/src/test/scala/CommandsNix.scala index 9235dec8c..9a4916382 100644 --- a/examples/commands-nix/src/test/scala/CommandsNix.scala +++ b/examples/commands-nix/src/test/scala/CommandsNix.scala @@ -100,8 +100,8 @@ object MachineSpec extends Commands { type Sut = Map[String, org.libvirt.Domain] // TODO we should check for example total amount of memory used here - def canCreateNewSut(newState: State, initSuts: Iterable[State], - runningSuts: Iterable[Sut] + def canCreateNewSut(newState: State, initSuts: Traversable[State], + runningSuts: Traversable[Sut] ): Boolean = true def newSut(state: State): Sut = { diff --git a/examples/commands-redis/src/test/scala/CommandsRedis.scala b/examples/commands-redis/src/test/scala/CommandsRedis.scala index 5e285d77d..ce30b5554 100644 --- a/examples/commands-redis/src/test/scala/CommandsRedis.scala +++ b/examples/commands-redis/src/test/scala/CommandsRedis.scala @@ -26,8 +26,8 @@ object RedisSpec extends Commands { connected: Boolean ) - def canCreateNewSut(newState: State, initSuts: Iterable[State], - runningSuts: Iterable[Sut] + def canCreateNewSut(newState: State, initSuts: Traversable[State], + runningSuts: Traversable[Sut] ): Boolean = { initSuts.isEmpty && runningSuts.isEmpty } diff --git a/jvm/src/test/scala/org/scalacheck/commands/CommandsSpecification.scala b/jvm/src/test/scala/org/scalacheck/commands/CommandsSpecification.scala index b3757f932..c60e276d3 100644 --- a/jvm/src/test/scala/org/scalacheck/commands/CommandsSpecification.scala +++ b/jvm/src/test/scala/org/scalacheck/commands/CommandsSpecification.scala @@ -30,8 +30,8 @@ object CommandsSpecification extends Properties("Commands") { override def shrinkState: Shrink[Int] = implicitly - def canCreateNewSut(newState: State, initSuts: Iterable[State], - runningSuts: Iterable[Sut]) = true + def canCreateNewSut(newState: State, initSuts: Traversable[State], + runningSuts: Traversable[Sut]) = true def newSut(state: State): Sut = Counter(state) diff --git a/src/main/scala-2.13+/org/scalacheck/ScalaVersionSpecific.scala b/src/main/scala-2.13+/org/scalacheck/ScalaVersionSpecific.scala index 7f614c7ec..76b1eb4b2 100644 --- a/src/main/scala-2.13+/org/scalacheck/ScalaVersionSpecific.scala +++ b/src/main/scala-2.13+/org/scalacheck/ScalaVersionSpecific.scala @@ -7,7 +7,7 @@ import scala.collection.mutable.Builder import rng.Seed private[scalacheck] object ScalaVersionSpecific { - def toLazyList[T](i: IterableOnce[T]) = i.to(LazyList) + def toLazyList[T](i: IterableOnce[T]) = LazyList.from(i) def listFactory[T]: Factory[T, List[T]] = new Factory[T, List[T]] with Serializable { @@ -48,7 +48,7 @@ private[scalacheck] trait GenVersionSpecific { private[scalacheck] trait GenSpecificationVersionSpecific private[scalacheck] trait CogenVersionSpecific { - implicit def cogenStream[A: Cogen]: Cogen[Stream[A]] = + implicit def cogenLazyList[A: Cogen]: Cogen[LazyList[A]] = Cogen.it(_.iterator) } diff --git a/src/main/scala/org/scalacheck/Cogen.scala b/src/main/scala/org/scalacheck/Cogen.scala index 2275392e9..baf014155 100644 --- a/src/main/scala/org/scalacheck/Cogen.scala +++ b/src/main/scala/org/scalacheck/Cogen.scala @@ -16,7 +16,6 @@ import scala.util.{Failure, Success, Try} import scala.concurrent.duration.{Duration, FiniteDuration} import java.math.BigInteger import rng.Seed -import ScalaVersionSpecific._ sealed trait Cogen[T] extends Serializable { @@ -124,7 +123,7 @@ object Cogen extends CogenArities with CogenLowPriority with CogenVersionSpecifi implicit def cogenVector[A: Cogen]: Cogen[Vector[A]] = Cogen.it(_.iterator) - implicit def cogenLazyList[A: Cogen]: Cogen[LazyList[A]] = + implicit def cogenStream[A: Cogen]: Cogen[Stream[A]] = Cogen.it(_.iterator) implicit def cogenSet[A: Cogen: Ordering]: Cogen[Set[A]] = diff --git a/src/main/scala/org/scalacheck/Gen.scala b/src/main/scala/org/scalacheck/Gen.scala index e45679e7b..0e740c11c 100644 --- a/src/main/scala/org/scalacheck/Gen.scala +++ b/src/main/scala/org/scalacheck/Gen.scala @@ -450,7 +450,7 @@ object Gen extends GenArities with GenVersionSpecific { /** Sequences generators. If any of the given generators fails, the * resulting generator will also fail. */ - def sequence[C,T](gs: Iterable[Gen[T]])(implicit b: Buildable[T,C]): Gen[C] = { + def sequence[C,T](gs: Traversable[Gen[T]])(implicit b: Buildable[T,C]): Gen[C] = { val g = gen { (p, seed) => gs.foldLeft(r(Some(Vector.empty[T]), seed)) { case (rs,g) => diff --git a/src/main/scala/org/scalacheck/commands/Commands.scala b/src/main/scala/org/scalacheck/commands/Commands.scala index daa2c05f3..737f3cb29 100644 --- a/src/main/scala/org/scalacheck/commands/Commands.scala +++ b/src/main/scala/org/scalacheck/commands/Commands.scala @@ -56,15 +56,15 @@ trait Commands { * (a singleton [[Sut]]), implement this method the following way: * * {{{ - * def canCreateNewSut(newState: State, initSuts: Iterable[State] - * runningSuts: Iterable[Sut] + * def canCreateNewSut(newState: State, initSuts: Traversable[State] + * runningSuts: Traversable[Sut] * ) = { * initSuts.isEmpty && runningSuts.isEmpty * } * }}} */ - def canCreateNewSut(newState: State, initSuts: Iterable[State], - runningSuts: Iterable[Sut]): Boolean + def canCreateNewSut(newState: State, initSuts: Traversable[State], + runningSuts: Traversable[Sut]): Boolean /** Create a new [[Sut]] instance with an internal state that * corresponds to the provided abstract state instance. The provided state diff --git a/src/main/scala/org/scalacheck/util/Buildable.scala b/src/main/scala/org/scalacheck/util/Buildable.scala index fc1936e4b..d1fd5730d 100644 --- a/src/main/scala/org/scalacheck/util/Buildable.scala +++ b/src/main/scala/org/scalacheck/util/Buildable.scala @@ -15,7 +15,7 @@ import ScalaVersionSpecific._ trait Buildable[T,C] extends Serializable { def builder: mutable.Builder[T,C] - def fromIterable(it: Iterable[T]): C = { + def fromIterable(it: Traversable[T]): C = { val b = builder b ++= it b.result() @@ -27,14 +27,15 @@ trait Buildable[T,C] extends Serializable { * serializable too. */ object SerializableCanBuildFroms { - implicit def listFactory[T]: Factory[T, List[T]] = ScalaVersionSpecific.listFactory - implicit def bitsetFactory[T]: Factory[Int, BitSet] = ScalaVersionSpecific.bitsetFactory - implicit def mapFactory[T, U]: Factory[(T, U), Map[T, U]] = ScalaVersionSpecific.mapFactory + // Names are `..CanBuildFrom` for binary compatibility. Change to `..Factory` in a major release. + implicit def listCanBuildFrom[T]: Factory[T, List[T]] = ScalaVersionSpecific.listFactory + implicit def bitsetCanBuildFrom[T]: Factory[Int, BitSet] = ScalaVersionSpecific.bitsetFactory + implicit def mapCanBuildFrom[T, U]: Factory[(T, U), Map[T, U]] = ScalaVersionSpecific.mapFactory } object Buildable { - - implicit def buildableFactory[T,C](implicit f: Factory[T,C]) = + // Name is `..CanBuildFrom` for binary compatibility. Change to `..Factory` in a major release. + implicit def buildableCanBuildFrom[T,C](implicit f: Factory[T,C]) = new Buildable[T,C] { def builder = f.newBuilder } From fd6aa84137314d911b635f4b394025ee78547772 Mon Sep 17 00:00:00 2001 From: Lukas Rytz Date: Fri, 18 May 2018 23:33:18 +0200 Subject: [PATCH 04/10] Fix https://github.com/rickynils/scalacheck/issues/412 --- .travis.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.travis.yml b/.travis.yml index 3cd273e68..a1efeaf61 100644 --- a/.travis.yml +++ b/.travis.yml @@ -38,6 +38,9 @@ matrix: before_script: - curl https://raw.githubusercontent.com/scala-native/scala-native/master/scripts/travis_setup.sh | bash -x sudo: required + addons: + apt: + update: true # https://github.com/rickynils/scalacheck/issues/412 env: PLATFORM=native SBT_PARALLEL=true WORKERS=1 DEPLOY=true - env: EXAMPLES script: From 5ba8ddf19be1082d6edc1927baea5df00a360157 Mon Sep 17 00:00:00 2001 From: Lukas Rytz Date: Sat, 19 May 2018 07:20:09 +0200 Subject: [PATCH 05/10] Don't MiMa on 2.13 --- build.sbt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 54b59a6b4..c0df70f3b 100644 --- a/build.sbt +++ b/build.sbt @@ -91,7 +91,11 @@ lazy val sharedSettings = MimaSettings.settings ++ scalaVersionSettings ++ Seq( // don't use fatal warnings in tests scalacOptions in Test ~= (_ filterNot (_ == "-Xfatal-warnings")), - mimaPreviousArtifacts := Set("org.scalacheck" %% "scalacheck" % "1.14.0"), + mimaPreviousArtifacts := { + // TODO: re-enable MiMa for 2.13.0-M4 once there is a release out + if (scalaMajorVersion.value == 13) Set() + else Set("org.scalacheck" %% "scalacheck" % "1.14.0") + }, publishTo := { val nexus = "https://oss.sonatype.org/" From 1c791311c49688dcd154cf29a9bb4a1bb51a334d Mon Sep 17 00:00:00 2001 From: Lukas Rytz Date: Wed, 23 May 2018 16:10:47 +0200 Subject: [PATCH 06/10] Go back to using Traversable instead of Iterable This is a no-op for 2.13, as Traversable is a (deprecated) alias for Iterable. For 2.10-2.12, this ensures that the signatures don't change due to cross-building with 2.13. --- src/main/scala/org/scalacheck/Arbitrary.scala | 6 ++--- src/main/scala/org/scalacheck/Gen.scala | 22 +++++++++---------- src/main/scala/org/scalacheck/Shrink.scala | 8 +++---- .../scala/org/scalacheck/util/Buildable.scala | 4 ++-- .../org/scalacheck/ShrinkSpecification.scala | 2 +- .../util/BuildableSpecification.scala | 2 +- 6 files changed, 22 insertions(+), 22 deletions(-) diff --git a/src/main/scala/org/scalacheck/Arbitrary.scala b/src/main/scala/org/scalacheck/Arbitrary.scala index e6f057d6c..814a0ee71 100644 --- a/src/main/scala/org/scalacheck/Arbitrary.scala +++ b/src/main/scala/org/scalacheck/Arbitrary.scala @@ -357,17 +357,17 @@ private[scalacheck] sealed trait ArbitraryLowPriority { Arbitrary(Gen.oneOf(arbitrary[T].map(Success(_)), arbitrary[Throwable].map(Failure(_)))) /** Arbitrary instance of any [[org.scalacheck.util.Buildable]] container - * (such as lists, arrays, lazy lists, etc). The maximum size of the container + * (such as lists, arrays, streams / lazy lists, etc). The maximum size of the container * depends on the size generation parameter. */ implicit def arbContainer[C[_],T](implicit - a: Arbitrary[T], b: Buildable[T,C[T]], t: C[T] => Iterable[T] + a: Arbitrary[T], b: Buildable[T,C[T]], t: C[T] => Traversable[T] ): Arbitrary[C[T]] = Arbitrary(buildableOf[C[T],T](arbitrary[T])) /** Arbitrary instance of any [[org.scalacheck.util.Buildable]] container * (such as maps). The maximum size of the container depends on the size * generation parameter. */ implicit def arbContainer2[C[_,_],T,U](implicit - a: Arbitrary[(T,U)], b: Buildable[(T,U),C[T,U]], t: C[T,U] => Iterable[(T,U)] + a: Arbitrary[(T,U)], b: Buildable[(T,U),C[T,U]], t: C[T,U] => Traversable[(T,U)] ): Arbitrary[C[T,U]] = Arbitrary(buildableOf[C[T,U],(T,U)](arbitrary[(T,U)])) implicit def arbEnum[A <: java.lang.Enum[A]](implicit A: reflect.ClassTag[A]): Arbitrary[A] = { diff --git a/src/main/scala/org/scalacheck/Gen.scala b/src/main/scala/org/scalacheck/Gen.scala index 0e740c11c..3384e0f0c 100644 --- a/src/main/scala/org/scalacheck/Gen.scala +++ b/src/main/scala/org/scalacheck/Gen.scala @@ -577,7 +577,7 @@ object Gen extends GenArities with GenVersionSpecific { //// List Generators //// - /** Generates a container of any Iterable type for which there exists an + /** Generates a container of any Traversable type for which there exists an * implicit [[org.scalacheck.util.Buildable]] instance. The elements in the * container will be generated by the given generator. The size of the * generated container is limited by `n`. Depending on what kind of container @@ -585,47 +585,47 @@ object Gen extends GenArities with GenVersionSpecific { * `n`, but not more. If the given generator fails generating a value, the * complete container generator will also fail. */ def buildableOfN[C,T](n: Int, g: Gen[T])(implicit - evb: Buildable[T,C], evt: C => Iterable[T] + evb: Buildable[T,C], evt: C => Traversable[T] ): Gen[C] = - sequence[C,T](Iterable.fill(n)(g)) suchThat { c => + sequence[C,T](Traversable.fill(n)(g)) suchThat { c => // TODO: Can we guarantee c.size == n (See issue #89)? c.forall(g.sieveCopy) } - /** Generates a container of any Iterable type for which there exists an + /** Generates a container of any Traversable type for which there exists an * implicit [[org.scalacheck.util.Buildable]] instance. The elements in the * container will be generated by the given generator. The size of the * container is bounded by the size parameter used when generating values. */ def buildableOf[C,T](g: Gen[T])(implicit - evb: Buildable[T,C], evt: C => Iterable[T] + evb: Buildable[T,C], evt: C => Traversable[T] ): Gen[C] = sized(s => choose(0, s max 0).flatMap(buildableOfN[C,T](_,g))) suchThat { c => if (c == null) g.sieveCopy(null) else c.forall(g.sieveCopy) } - /** Generates a non-empty container of any Iterable type for which there + /** Generates a non-empty container of any Traversable type for which there * exists an implicit [[org.scalacheck.util.Buildable]] instance. The * elements in the container will be generated by the given generator. The * size of the container is bounded by the size parameter used when * generating values. */ def nonEmptyBuildableOf[C,T](g: Gen[T])(implicit - evb: Buildable[T,C], evt: C => Iterable[T] + evb: Buildable[T,C], evt: C => Traversable[T] ): Gen[C] = sized(s => choose(1, s max 1).flatMap(buildableOfN[C,T](_,g))) suchThat(_.size > 0) /** A convenience method for calling `buildableOfN[C[T],T](n,g)`. */ def containerOfN[C[_],T](n: Int, g: Gen[T])(implicit - evb: Buildable[T,C[T]], evt: C[T] => Iterable[T] + evb: Buildable[T,C[T]], evt: C[T] => Traversable[T] ): Gen[C[T]] = buildableOfN[C[T],T](n,g) /** A convenience method for calling `buildableOf[C[T],T](g)`. */ def containerOf[C[_],T](g: Gen[T])(implicit - evb: Buildable[T,C[T]], evt: C[T] => Iterable[T] + evb: Buildable[T,C[T]], evt: C[T] => Traversable[T] ): Gen[C[T]] = buildableOf[C[T],T](g) /** A convenience method for calling `nonEmptyBuildableOf[C[T],T](g)`. */ def nonEmptyContainerOf[C[_],T](g: Gen[T])(implicit - evb: Buildable[T,C[T]], evt: C[T] => Iterable[T] + evb: Buildable[T,C[T]], evt: C[T] => Traversable[T] ): Gen[C[T]] = nonEmptyBuildableOf[C[T],T](g) /** Generates a list of random length. The maximum length depends on the @@ -656,7 +656,7 @@ object Gen extends GenArities with GenVersionSpecific { * is equal to calling containerOfN[Map,T,U](n,g). */ def mapOfN[T,U](n: Int, g: Gen[(T,U)]) = buildableOfN[Map[T,U],(T,U)](n,g) - /** Generates an infinite lazy list. */ + /** Generates an infinite stream. */ def infiniteStream[T](g: => Gen[T]): Gen[Stream[T]] = { def unfold[A, S](z: S)(f: S => Option[(A, S)]): Stream[A] = f(z) match { case Some((h, s)) => h #:: unfold(s)(f) diff --git a/src/main/scala/org/scalacheck/Shrink.scala b/src/main/scala/org/scalacheck/Shrink.scala index 8d397e86a..423f85aff 100644 --- a/src/main/scala/org/scalacheck/Shrink.scala +++ b/src/main/scala/org/scalacheck/Shrink.scala @@ -30,7 +30,7 @@ object Shrink extends ShrinkLowPriority { import LazyList.{cons, empty} import scala.collection._ - /** Interleaves two lazy lists */ + /** Interleaves two streams / lazy lists */ private def interleave[T](xs: LazyList[T], ys: LazyList[T]): LazyList[T] = if(xs.isEmpty) ys else if(ys.isEmpty) xs @@ -45,12 +45,12 @@ object Shrink extends ShrinkLowPriority { def shrink[T](x: T)(implicit s: Shrink[T]): LazyList[T] = s.shrink(x) /** Shrink a value, but also return the original value as the first element in - * the resulting lazy list */ + * the resulting stream / lazy list */ def shrinkWithOrig[T](x: T)(implicit s: Shrink[T]): LazyList[T] = cons(x, s.shrink(x)) /** Shrink instance of container */ - implicit def shrinkContainer[C[_],T](implicit v: C[T] => Iterable[T], s: Shrink[T], + implicit def shrinkContainer[C[_],T](implicit v: C[T] => Traversable[T], s: Shrink[T], b: Buildable[T,C[T]] ): Shrink[C[T]] = Shrink { xs: C[T] => val ys = v(xs) @@ -59,7 +59,7 @@ object Shrink extends ShrinkLowPriority { } /** Shrink instance of container2 */ - implicit def shrinkContainer2[C[_,_],T,U](implicit v: C[T,U] => Iterable[(T,U)], s: Shrink[(T,U)], + implicit def shrinkContainer2[C[_,_],T,U](implicit v: C[T,U] => Traversable[(T,U)], s: Shrink[(T,U)], b: Buildable[(T,U),C[T,U]] ): Shrink[C[T,U]] = Shrink { xs: C[T,U] => val ys = v(xs) diff --git a/src/main/scala/org/scalacheck/util/Buildable.scala b/src/main/scala/org/scalacheck/util/Buildable.scala index d1fd5730d..d8ad2de3a 100644 --- a/src/main/scala/org/scalacheck/util/Buildable.scala +++ b/src/main/scala/org/scalacheck/util/Buildable.scala @@ -26,8 +26,8 @@ trait Buildable[T,C] extends Serializable { * Factory instances implementing Serializable, so that the objects capturing those can be * serializable too. */ +// Names are `..CanBuildFrom` for binary compatibility. Change to `..Factory` in a major release. object SerializableCanBuildFroms { - // Names are `..CanBuildFrom` for binary compatibility. Change to `..Factory` in a major release. implicit def listCanBuildFrom[T]: Factory[T, List[T]] = ScalaVersionSpecific.listFactory implicit def bitsetCanBuildFrom[T]: Factory[Int, BitSet] = ScalaVersionSpecific.bitsetFactory implicit def mapCanBuildFrom[T, U]: Factory[(T, U), Map[T, U]] = ScalaVersionSpecific.mapFactory @@ -41,7 +41,7 @@ object Buildable { } import java.util.ArrayList - implicit def buildableArrayList[T] = new Buildable[T,ArrayList[T]] { + implicit def buildableArrayList[T]: Buildable[T, ArrayList[T]] = new Buildable[T,ArrayList[T]] { def builder = new ArrayListBuilder[T] } diff --git a/src/test/scala/org/scalacheck/ShrinkSpecification.scala b/src/test/scala/org/scalacheck/ShrinkSpecification.scala index 69dd74bd0..930e00a4f 100644 --- a/src/test/scala/org/scalacheck/ShrinkSpecification.scala +++ b/src/test/scala/org/scalacheck/ShrinkSpecification.scala @@ -105,7 +105,7 @@ object ShrinkSpecification extends Properties("Shrink") { /* Ensure that shrink[T] terminates. (#244) * - * Let's say shrinking "terminates" when the lazy list of values + * Let's say shrinking "terminates" when the stream / lazy list of values * becomes empty. We can empirically determine the longest possible * sequence for a given type before termination. (Usually this * involves using the type's MinValue.) diff --git a/src/test/scala/org/scalacheck/util/BuildableSpecification.scala b/src/test/scala/org/scalacheck/util/BuildableSpecification.scala index 2830a10d5..4764f026d 100644 --- a/src/test/scala/org/scalacheck/util/BuildableSpecification.scala +++ b/src/test/scala/org/scalacheck/util/BuildableSpecification.scala @@ -17,7 +17,7 @@ import ScalaVersionSpecific._ object BuildableSpecification { def container[C[_]](implicit evb: Buildable[String, C[String]], - evt: C[String] => Iterable[String] + evt: C[String] => Traversable[String] ) = Gen.containerOf[C, String](Gen.alphaStr) implicit val listGen: Gen[List[String]] = container[List] From 543b4056bffdb684faec49e8afb09aee4c24eb2f Mon Sep 17 00:00:00 2001 From: Lukas Rytz Date: Wed, 23 May 2018 16:49:16 +0200 Subject: [PATCH 07/10] Remove Factory type alias, simplify version-dependent Buildable --- .../org/scalacheck/ScalaVersionSpecific.scala | 41 +++---------- .../util/BuildableVersionSpecific.scala | 59 +++++++++++++++++++ .../org/scalacheck/ScalaVersionSpecific.scala | 50 ++++------------ .../util/BuildableVersionSpecific.scala | 57 ++++++++++++++++++ .../scala/org/scalacheck/util/Buildable.scala | 23 +------- 5 files changed, 138 insertions(+), 92 deletions(-) create mode 100644 src/main/scala-2.13+/org/scalacheck/util/BuildableVersionSpecific.scala create mode 100644 src/main/scala-2.13-/org/scalacheck/util/BuildableVersionSpecific.scala diff --git a/src/main/scala-2.13+/org/scalacheck/ScalaVersionSpecific.scala b/src/main/scala-2.13+/org/scalacheck/ScalaVersionSpecific.scala index 76b1eb4b2..dc7ab3ce9 100644 --- a/src/main/scala-2.13+/org/scalacheck/ScalaVersionSpecific.scala +++ b/src/main/scala-2.13+/org/scalacheck/ScalaVersionSpecific.scala @@ -1,31 +1,18 @@ -package org.scalacheck +/*-------------------------------------------------------------------------*\ +** ScalaCheck ** +** Copyright (c) 2007-2018 Rickard Nilsson. All rights reserved. ** +** http://www.scalacheck.org ** +** ** +** This software is released under the terms of the Revised BSD License. ** +** There is NO WARRANTY. See the file LICENSE for the full text. ** +\*------------------------------------------------------------------------ */ -import java.util.ArrayList +package org.scalacheck -import scala.collection.{BitSet, Factory} -import scala.collection.mutable.Builder import rng.Seed private[scalacheck] object ScalaVersionSpecific { def toLazyList[T](i: IterableOnce[T]) = LazyList.from(i) - - def listFactory[T]: Factory[T, List[T]] = - new Factory[T, List[T]] with Serializable { - def fromSpecific(source: IterableOnce[T]): List[T] = List.from(source) - def newBuilder: Builder[T, List[T]] = List.newBuilder[T] - } - - def bitsetFactory[T]: Factory[Int, BitSet] = - new Factory[Int, BitSet] with Serializable { - def fromSpecific(source: IterableOnce[Int]) = BitSet.fromSpecific(source) - def newBuilder: Builder[Int, BitSet] = BitSet.newBuilder - } - - def mapFactory[T, U]: Factory[(T, U), Map[T, U]] = - new Factory[(T, U), Map[T, U]] with Serializable { - def fromSpecific(source: IterableOnce[(T, U)]) = Map.from(source) - def newBuilder: Builder[(T, U), Map[T, U]] = Map.newBuilder[T, U] - } } private[scalacheck] trait GenVersionSpecific { @@ -51,13 +38,3 @@ private[scalacheck] trait CogenVersionSpecific { implicit def cogenLazyList[A: Cogen]: Cogen[LazyList[A]] = Cogen.it(_.iterator) } - -private[scalacheck] class ArrayListBuilder[T] extends Builder[T, ArrayList[T]] { - private val al = new ArrayList[T] - def addOne(x: T): this.type = { - al.add(x) - this - } - def clear(): Unit = al.clear() - def result(): ArrayList[T] = al -} diff --git a/src/main/scala-2.13+/org/scalacheck/util/BuildableVersionSpecific.scala b/src/main/scala-2.13+/org/scalacheck/util/BuildableVersionSpecific.scala new file mode 100644 index 000000000..db60cc892 --- /dev/null +++ b/src/main/scala-2.13+/org/scalacheck/util/BuildableVersionSpecific.scala @@ -0,0 +1,59 @@ +/*-------------------------------------------------------------------------*\ +** ScalaCheck ** +** Copyright (c) 2007-2018 Rickard Nilsson. All rights reserved. ** +** http://www.scalacheck.org ** +** ** +** This software is released under the terms of the Revised BSD License. ** +** There is NO WARRANTY. See the file LICENSE for the full text. ** +\*------------------------------------------------------------------------ */ + +package org.scalacheck.util + +import java.util.ArrayList + +import collection.{Map => _, _} +import scala.collection.mutable.Builder + + +private[util] trait BuildableVersionSpecific { + implicit def buildableFactory[T,C](implicit f: Factory[T,C]) = + new Buildable[T,C] { + def builder = f.newBuilder + } +} + +private[util] class ArrayListBuilder[T] extends Builder[T, ArrayList[T]] { + private val al = new ArrayList[T] + def addOne(x: T): this.type = { + al.add(x) + this + } + def clear(): Unit = al.clear() + def result(): ArrayList[T] = al +} + +/** + * Factory instances implementing Serializable, so that the objects capturing those can be + * serializable too. + */ +// Named `...CanBuildFroms` for 2.12 source compatibility (`import SerializableCanBuildFroms._`) +// Can be renamed to `SerializableFactories` in a major release. +object SerializableCanBuildFroms { + implicit def listFactory[T]: Factory[T, List[T]] = + new Factory[T, List[T]] with Serializable { + def fromSpecific(source: IterableOnce[T]): List[T] = List.from(source) + def newBuilder: Builder[T, List[T]] = List.newBuilder[T] + } + + implicit def bitsetFactory[T]: Factory[Int, BitSet] = + new Factory[Int, BitSet] with Serializable { + def fromSpecific(source: IterableOnce[Int]) = BitSet.fromSpecific(source) + def newBuilder: Builder[Int, BitSet] = BitSet.newBuilder + } + + implicit def mapFactory[T, U]: Factory[(T, U), Map[T, U]] = + new Factory[(T, U), Map[T, U]] with Serializable { + def fromSpecific(source: IterableOnce[(T, U)]) = Map.from(source) + def newBuilder: Builder[(T, U), Map[T, U]] = Map.newBuilder[T, U] + } +} diff --git a/src/main/scala-2.13-/org/scalacheck/ScalaVersionSpecific.scala b/src/main/scala-2.13-/org/scalacheck/ScalaVersionSpecific.scala index bdd32cc27..38bc0bff3 100644 --- a/src/main/scala-2.13-/org/scalacheck/ScalaVersionSpecific.scala +++ b/src/main/scala-2.13-/org/scalacheck/ScalaVersionSpecific.scala @@ -1,39 +1,21 @@ -package org.scalacheck +/*-------------------------------------------------------------------------*\ +** ScalaCheck ** +** Copyright (c) 2007-2018 Rickard Nilsson. All rights reserved. ** +** http://www.scalacheck.org ** +** ** +** This software is released under the terms of the Revised BSD License. ** +** There is NO WARRANTY. See the file LICENSE for the full text. ** +\*------------------------------------------------------------------------ */ -import java.util.ArrayList +package org.scalacheck -import scala.collection.generic.{CanBuildFrom, Sorted} +import scala.collection.generic.Sorted import scala.collection.immutable.Stream -import scala.collection.mutable.Builder -import scala.collection.{BitSet, TraversableOnce} +import scala.collection.TraversableOnce private[scalacheck] object ScalaVersionSpecific { def toLazyList[T](i: TraversableOnce[T]) = i.toStream - type Factory[-A, +C] = CanBuildFrom[Nothing, A, C] - - def listFactory[T]: CanBuildFrom[List[T], T, List[T]] = - new CanBuildFrom[List[T], T, List[T]] with Serializable { - def apply(from: List[T]) = List.newBuilder[T] - def apply() = List.newBuilder[T] - } - - def bitsetFactory[T]: CanBuildFrom[BitSet, Int, BitSet] = - new CanBuildFrom[BitSet, Int, BitSet] with Serializable { - def apply(from: BitSet) = BitSet.newBuilder - def apply() = BitSet.newBuilder - } - - def mapFactory[T, U]: CanBuildFrom[Map[T, U], (T, U), Map[T, U]] = - new CanBuildFrom[Map[T, U], (T, U), Map[T, U]] with Serializable { - def apply(from: Map[T, U]) = Map.newBuilder[T, U] - def apply() = Map.newBuilder[T, U] - } - - implicit class CBFExt[-A, +C](val cbf: CanBuildFrom[Nothing, A, C]) extends AnyVal { - def newBuilder: Builder[A, C] = cbf() - } - type LazyList[+A] = Stream[A] val LazyList = Stream @@ -55,13 +37,3 @@ private[scalacheck] trait CogenVersionSpecific private[scalacheck] trait GenSpecificationVersionSpecific { def infiniteLazyList[T](g: => Gen[T]): Gen[Stream[T]] = Gen.infiniteStream(g) } - -private[scalacheck] class ArrayListBuilder[T] extends Builder[T, ArrayList[T]] { - private val al = new ArrayList[T] - def +=(x: T): this.type = { - al.add(x) - this - } - def clear(): Unit = al.clear() - def result(): ArrayList[T] = al -} diff --git a/src/main/scala-2.13-/org/scalacheck/util/BuildableVersionSpecific.scala b/src/main/scala-2.13-/org/scalacheck/util/BuildableVersionSpecific.scala new file mode 100644 index 000000000..ebf7e2f65 --- /dev/null +++ b/src/main/scala-2.13-/org/scalacheck/util/BuildableVersionSpecific.scala @@ -0,0 +1,57 @@ +/*-------------------------------------------------------------------------*\ +** ScalaCheck ** +** Copyright (c) 2007-2018 Rickard Nilsson. All rights reserved. ** +** http://www.scalacheck.org ** +** ** +** This software is released under the terms of the Revised BSD License. ** +** There is NO WARRANTY. See the file LICENSE for the full text. ** +\*------------------------------------------------------------------------ */ + +package org.scalacheck.util + +import java.util.ArrayList + +import collection.{Map => _, _} +import generic.CanBuildFrom +import scala.collection.mutable.Builder + +private[util] trait BuildableVersionSpecific { + implicit def buildableCanBuildFrom[T,F,C](implicit c: CanBuildFrom[F,T,C]) = + new Buildable[T,C] { + def builder = c.apply + } +} + +private[util] class ArrayListBuilder[T] extends Builder[T, ArrayList[T]] { + private val al = new ArrayList[T] + def +=(x: T): this.type = { + al.add(x) + this + } + def clear(): Unit = al.clear() + def result(): ArrayList[T] = al +} + +/** + * CanBuildFrom instances implementing Serializable, so that the objects capturing those can be + * serializable too. + */ +object SerializableCanBuildFroms { + implicit def listCanBuildFrom[T]: CanBuildFrom[List[T], T, List[T]] = + new CanBuildFrom[List[T], T, List[T]] with Serializable { + def apply(from: List[T]) = List.newBuilder[T] + def apply() = List.newBuilder[T] + } + + implicit def bitsetCanBuildFrom[T]: CanBuildFrom[BitSet, Int, BitSet] = + new CanBuildFrom[BitSet, Int, BitSet] with Serializable { + def apply(from: BitSet) = BitSet.newBuilder + def apply() = BitSet.newBuilder + } + + implicit def mapCanBuildFrom[T, U]: CanBuildFrom[Map[T, U], (T, U), Map[T, U]] = + new CanBuildFrom[Map[T, U], (T, U), Map[T, U]] with Serializable { + def apply(from: Map[T, U]) = Map.newBuilder[T, U] + def apply() = Map.newBuilder[T, U] + } +} diff --git a/src/main/scala/org/scalacheck/util/Buildable.scala b/src/main/scala/org/scalacheck/util/Buildable.scala index d8ad2de3a..2d8eab3bf 100644 --- a/src/main/scala/org/scalacheck/util/Buildable.scala +++ b/src/main/scala/org/scalacheck/util/Buildable.scala @@ -10,8 +10,6 @@ package org.scalacheck.util import scala.collection.{mutable, Map => _, _} -import org.scalacheck.{ScalaVersionSpecific, ArrayListBuilder} -import ScalaVersionSpecific._ trait Buildable[T,C] extends Serializable { def builder: mutable.Builder[T,C] @@ -22,30 +20,13 @@ trait Buildable[T,C] extends Serializable { } } -/** - * Factory instances implementing Serializable, so that the objects capturing those can be - * serializable too. - */ -// Names are `..CanBuildFrom` for binary compatibility. Change to `..Factory` in a major release. -object SerializableCanBuildFroms { - implicit def listCanBuildFrom[T]: Factory[T, List[T]] = ScalaVersionSpecific.listFactory - implicit def bitsetCanBuildFrom[T]: Factory[Int, BitSet] = ScalaVersionSpecific.bitsetFactory - implicit def mapCanBuildFrom[T, U]: Factory[(T, U), Map[T, U]] = ScalaVersionSpecific.mapFactory -} - -object Buildable { - // Name is `..CanBuildFrom` for binary compatibility. Change to `..Factory` in a major release. - implicit def buildableCanBuildFrom[T,C](implicit f: Factory[T,C]) = - new Buildable[T,C] { - def builder = f.newBuilder - } - +object Buildable extends BuildableVersionSpecific { import java.util.ArrayList implicit def buildableArrayList[T]: Buildable[T, ArrayList[T]] = new Buildable[T,ArrayList[T]] { def builder = new ArrayListBuilder[T] } - } + /* object Buildable2 { From f7d6cf8faf9f5d58cf333e9e20548360de4b4248 Mon Sep 17 00:00:00 2001 From: "Aaron S. Hawley" Date: Wed, 6 Jun 2018 09:16:31 -0400 Subject: [PATCH 08/10] Revert LazyList back to Stream for Shrink --- src/main/scala/org/scalacheck/Prop.scala | 7 +- src/main/scala/org/scalacheck/Shrink.scala | 127 +++++++++--------- .../org/scalacheck/commands/Commands.scala | 5 +- .../org/scalacheck/ShrinkSpecification.scala | 6 +- 4 files changed, 71 insertions(+), 74 deletions(-) diff --git a/src/main/scala/org/scalacheck/Prop.scala b/src/main/scala/org/scalacheck/Prop.scala index cc28a4e0f..beddcf662 100644 --- a/src/main/scala/org/scalacheck/Prop.scala +++ b/src/main/scala/org/scalacheck/Prop.scala @@ -15,7 +15,6 @@ import language.reflectiveCalls import rng.Seed import util.{Pretty, ConsoleReporter} import scala.annotation.tailrec -import ScalaVersionSpecific._ /** Helper class to satisfy ScalaJS compilation. Do not use this directly, * use `Prop.apply` instead. */ @@ -750,7 +749,7 @@ object Prop { /** Universal quantifier for an explicit generator. Shrinks failed arguments * with the given shrink function */ def forAllShrink[T, P](g: Gen[T], - shrink: T => LazyList[T])(f: T => P + shrink: T => Stream[T])(f: T => P )(implicit pv: P => Prop, pp: T => Pretty ): Prop = Prop { prms0 => @@ -766,8 +765,8 @@ object Prop { /* * Returns the first failed result in Left or success in Right. */ - def getFirstFailure(xs: LazyList[T]): Either[(T,Result),(T,Result)] = { - assert(!xs.isEmpty, "LazyList cannot be empty") + def getFirstFailure(xs: Stream[T]): Either[(T,Result),(T,Result)] = { + assert(!xs.isEmpty, "Stream cannot be empty") val results = xs.map(x => (x, result(x))) results.dropWhile(!_._2.failure).headOption match { case None => Right(results.head) diff --git a/src/main/scala/org/scalacheck/Shrink.scala b/src/main/scala/org/scalacheck/Shrink.scala index 423f85aff..4547a7d75 100644 --- a/src/main/scala/org/scalacheck/Shrink.scala +++ b/src/main/scala/org/scalacheck/Shrink.scala @@ -14,39 +14,38 @@ import language.higherKinds import util.Buildable import util.SerializableCanBuildFroms._ import scala.concurrent.duration.{Duration, FiniteDuration} -import ScalaVersionSpecific._ sealed abstract class Shrink[T] extends Serializable { - def shrink(x: T): LazyList[T] + def shrink(x: T): Stream[T] } trait ShrinkLowPriority { /** Default shrink instance */ - implicit def shrinkAny[T]: Shrink[T] = Shrink(_ => LazyList.empty) + implicit def shrinkAny[T]: Shrink[T] = Shrink(_ => Stream.empty) } object Shrink extends ShrinkLowPriority { - import LazyList.{cons, empty} + import Stream.{cons, empty} import scala.collection._ - /** Interleaves two streams / lazy lists */ - private def interleave[T](xs: LazyList[T], ys: LazyList[T]): LazyList[T] = + /** Interleaves two streams */ + private def interleave[T](xs: Stream[T], ys: Stream[T]): Stream[T] = if(xs.isEmpty) ys else if(ys.isEmpty) xs else cons(xs.head, cons(ys.head, interleave(xs.tail, ys.tail))) /** Shrink instance factory */ - def apply[T](s: T => LazyList[T]): Shrink[T] = new Shrink[T] { + def apply[T](s: T => Stream[T]): Shrink[T] = new Shrink[T] { override def shrink(x: T) = s(x) } /** Shrink a value */ - def shrink[T](x: T)(implicit s: Shrink[T]): LazyList[T] = s.shrink(x) + def shrink[T](x: T)(implicit s: Shrink[T]): Stream[T] = s.shrink(x) /** Shrink a value, but also return the original value as the first element in - * the resulting stream / lazy list */ - def shrinkWithOrig[T](x: T)(implicit s: Shrink[T]): LazyList[T] = + * the resulting stream */ + def shrinkWithOrig[T](x: T)(implicit s: Shrink[T]): Stream[T] = cons(x, s.shrink(x)) /** Shrink instance of container */ @@ -54,8 +53,8 @@ object Shrink extends ShrinkLowPriority { b: Buildable[T,C[T]] ): Shrink[C[T]] = Shrink { xs: C[T] => val ys = v(xs) - val zs = toLazyList(ys) - removeChunks(ys.size,zs).lazyAppendedAll(shrinkOne(zs)).map(b.fromIterable) + val zs = ys.toStream + removeChunks(ys.size,zs).append(shrinkOne(zs)).map(b.fromIterable) } /** Shrink instance of container2 */ @@ -63,11 +62,11 @@ object Shrink extends ShrinkLowPriority { b: Buildable[(T,U),C[T,U]] ): Shrink[C[T,U]] = Shrink { xs: C[T,U] => val ys = v(xs) - val zs = toLazyList(ys) - removeChunks(ys.size,zs).lazyAppendedAll(shrinkOne(zs)).map(b.fromIterable) + val zs = ys.toStream + removeChunks(ys.size,zs).append(shrinkOne(zs)).map(b.fromIterable) } - private def removeChunks[T](n: Int, xs: LazyList[T]): LazyList[LazyList[T]] = + private def removeChunks[T](n: Int, xs: Stream[T]): Stream[Stream[T]] = if (xs.isEmpty) empty else if (xs.tail.isEmpty) cons(empty, empty) else { @@ -76,19 +75,19 @@ object Shrink extends ShrinkLowPriority { lazy val xs1 = xs.take(n1) lazy val xs2 = xs.drop(n1) lazy val xs3 = - for (ys1 <- removeChunks(n1, xs1) if !ys1.isEmpty) yield ys1 lazyAppendedAll xs2 + for (ys1 <- removeChunks(n1, xs1) if !ys1.isEmpty) yield ys1 append xs2 lazy val xs4 = - for (ys2 <- removeChunks(n2, xs2) if !ys2.isEmpty) yield xs1 lazyAppendedAll ys2 + for (ys2 <- removeChunks(n2, xs2) if !ys2.isEmpty) yield xs1 append ys2 cons(xs1, cons(xs2, interleave(xs3, xs4))) } - private def shrinkOne[T : Shrink](zs: LazyList[T]): LazyList[LazyList[T]] = + private def shrinkOne[T : Shrink](zs: Stream[T]): Stream[Stream[T]] = if (zs.isEmpty) empty else { val x = zs.head val xs = zs.tail - shrink(x).map(cons(_,xs)).lazyAppendedAll(shrinkOne(xs).map(cons(x,_))) + shrink(x).map(cons(_,xs)).append(shrinkOne(xs).map(cons(x,_))) } /** Shrink instances for numeric data types */ @@ -115,7 +114,7 @@ object Shrink extends ShrinkLowPriority { T1:Shrink, T2:Shrink ]: Shrink[(T1,T2)] = Shrink { case (t1,t2) => - shrink(t1).map((_,t2)) lazyAppendedAll + shrink(t1).map((_,t2)) append shrink(t2).map((t1,_)) } @@ -124,8 +123,8 @@ object Shrink extends ShrinkLowPriority { T1:Shrink, T2:Shrink, T3:Shrink ]: Shrink[(T1,T2,T3)] = Shrink { case (t1,t2,t3) => - shrink(t1).map((_, t2, t3)) lazyAppendedAll - shrink(t2).map((t1, _, t3)) lazyAppendedAll + shrink(t1).map((_, t2, t3)) append + shrink(t2).map((t1, _, t3)) append shrink(t3).map((t1, t2, _)) } @@ -134,9 +133,9 @@ object Shrink extends ShrinkLowPriority { T1:Shrink, T2:Shrink, T3:Shrink, T4:Shrink ]: Shrink[(T1,T2,T3,T4)] = Shrink { case (t1,t2,t3,t4) => - shrink(t1).map((_, t2, t3, t4)) lazyAppendedAll - shrink(t2).map((t1, _, t3, t4)) lazyAppendedAll - shrink(t3).map((t1, t2, _, t4)) lazyAppendedAll + shrink(t1).map((_, t2, t3, t4)) append + shrink(t2).map((t1, _, t3, t4)) append + shrink(t3).map((t1, t2, _, t4)) append shrink(t4).map((t1, t2, t3, _)) } @@ -145,10 +144,10 @@ object Shrink extends ShrinkLowPriority { T1:Shrink, T2:Shrink, T3:Shrink, T4:Shrink, T5:Shrink ]: Shrink[(T1,T2,T3,T4,T5)] = Shrink { case (t1,t2,t3,t4,t5) => - shrink(t1).map((_, t2, t3, t4, t5)) lazyAppendedAll - shrink(t2).map((t1, _, t3, t4, t5)) lazyAppendedAll - shrink(t3).map((t1, t2, _, t4, t5)) lazyAppendedAll - shrink(t4).map((t1, t2, t3, _, t5)) lazyAppendedAll + shrink(t1).map((_, t2, t3, t4, t5)) append + shrink(t2).map((t1, _, t3, t4, t5)) append + shrink(t3).map((t1, t2, _, t4, t5)) append + shrink(t4).map((t1, t2, t3, _, t5)) append shrink(t5).map((t1, t2, t3, t4, _)) } @@ -157,11 +156,11 @@ object Shrink extends ShrinkLowPriority { T1:Shrink, T2:Shrink, T3:Shrink, T4:Shrink, T5:Shrink, T6:Shrink ]: Shrink[(T1,T2,T3,T4,T5,T6)] = Shrink { case (t1,t2,t3,t4,t5,t6) => - shrink(t1).map((_, t2, t3, t4, t5, t6)) lazyAppendedAll - shrink(t2).map((t1, _, t3, t4, t5, t6)) lazyAppendedAll - shrink(t3).map((t1, t2, _, t4, t5, t6)) lazyAppendedAll - shrink(t4).map((t1, t2, t3, _, t5, t6)) lazyAppendedAll - shrink(t5).map((t1, t2, t3, t4, _, t6)) lazyAppendedAll + shrink(t1).map((_, t2, t3, t4, t5, t6)) append + shrink(t2).map((t1, _, t3, t4, t5, t6)) append + shrink(t3).map((t1, t2, _, t4, t5, t6)) append + shrink(t4).map((t1, t2, t3, _, t5, t6)) append + shrink(t5).map((t1, t2, t3, t4, _, t6)) append shrink(t6).map((t1, t2, t3, t4, t5, _)) } @@ -170,12 +169,12 @@ object Shrink extends ShrinkLowPriority { T1:Shrink, T2:Shrink, T3:Shrink, T4:Shrink, T5:Shrink, T6:Shrink, T7:Shrink ]: Shrink[(T1,T2,T3,T4,T5,T6,T7)] = Shrink { case (t1,t2,t3,t4,t5,t6,t7) => - shrink(t1).map((_, t2, t3, t4, t5, t6, t7)) lazyAppendedAll - shrink(t2).map((t1, _, t3, t4, t5, t6, t7)) lazyAppendedAll - shrink(t3).map((t1, t2, _, t4, t5, t6, t7)) lazyAppendedAll - shrink(t4).map((t1, t2, t3, _, t5, t6, t7)) lazyAppendedAll - shrink(t5).map((t1, t2, t3, t4, _, t6, t7)) lazyAppendedAll - shrink(t6).map((t1, t2, t3, t4, t5, _, t7)) lazyAppendedAll + shrink(t1).map((_, t2, t3, t4, t5, t6, t7)) append + shrink(t2).map((t1, _, t3, t4, t5, t6, t7)) append + shrink(t3).map((t1, t2, _, t4, t5, t6, t7)) append + shrink(t4).map((t1, t2, t3, _, t5, t6, t7)) append + shrink(t5).map((t1, t2, t3, t4, _, t6, t7)) append + shrink(t6).map((t1, t2, t3, t4, t5, _, t7)) append shrink(t7).map((t1, t2, t3, t4, t5, t6, _)) } @@ -185,13 +184,13 @@ object Shrink extends ShrinkLowPriority { T7:Shrink, T8:Shrink ]: Shrink[(T1,T2,T3,T4,T5,T6,T7,T8)] = Shrink { case (t1,t2,t3,t4,t5,t6,t7,t8) => - shrink(t1).map((_, t2, t3, t4, t5, t6, t7, t8)) lazyAppendedAll - shrink(t2).map((t1, _, t3, t4, t5, t6, t7, t8)) lazyAppendedAll - shrink(t3).map((t1, t2, _, t4, t5, t6, t7, t8)) lazyAppendedAll - shrink(t4).map((t1, t2, t3, _, t5, t6, t7, t8)) lazyAppendedAll - shrink(t5).map((t1, t2, t3, t4, _, t6, t7, t8)) lazyAppendedAll - shrink(t6).map((t1, t2, t3, t4, t5, _, t7, t8)) lazyAppendedAll - shrink(t7).map((t1, t2, t3, t4, t5, t6, _, t8)) lazyAppendedAll + shrink(t1).map((_, t2, t3, t4, t5, t6, t7, t8)) append + shrink(t2).map((t1, _, t3, t4, t5, t6, t7, t8)) append + shrink(t3).map((t1, t2, _, t4, t5, t6, t7, t8)) append + shrink(t4).map((t1, t2, t3, _, t5, t6, t7, t8)) append + shrink(t5).map((t1, t2, t3, t4, _, t6, t7, t8)) append + shrink(t6).map((t1, t2, t3, t4, t5, _, t7, t8)) append + shrink(t7).map((t1, t2, t3, t4, t5, t6, _, t8)) append shrink(t8).map((t1, t2, t3, t4, t5, t6, t7, _)) } @@ -201,14 +200,14 @@ object Shrink extends ShrinkLowPriority { T7:Shrink, T8:Shrink, T9:Shrink ]: Shrink[(T1,T2,T3,T4,T5,T6,T7,T8,T9)] = Shrink { case (t1,t2,t3,t4,t5,t6,t7,t8,t9) => - shrink(t1).map((_, t2, t3, t4, t5, t6, t7, t8, t9)) lazyAppendedAll - shrink(t2).map((t1, _, t3, t4, t5, t6, t7, t8, t9)) lazyAppendedAll - shrink(t3).map((t1, t2, _, t4, t5, t6, t7, t8, t9)) lazyAppendedAll - shrink(t4).map((t1, t2, t3, _, t5, t6, t7, t8, t9)) lazyAppendedAll - shrink(t5).map((t1, t2, t3, t4, _, t6, t7, t8, t9)) lazyAppendedAll - shrink(t6).map((t1, t2, t3, t4, t5, _, t7, t8, t9)) lazyAppendedAll - shrink(t7).map((t1, t2, t3, t4, t5, t6, _, t8, t9)) lazyAppendedAll - shrink(t8).map((t1, t2, t3, t4, t5, t6, t7, _, t9)) lazyAppendedAll + shrink(t1).map((_, t2, t3, t4, t5, t6, t7, t8, t9)) append + shrink(t2).map((t1, _, t3, t4, t5, t6, t7, t8, t9)) append + shrink(t3).map((t1, t2, _, t4, t5, t6, t7, t8, t9)) append + shrink(t4).map((t1, t2, t3, _, t5, t6, t7, t8, t9)) append + shrink(t5).map((t1, t2, t3, t4, _, t6, t7, t8, t9)) append + shrink(t6).map((t1, t2, t3, t4, t5, _, t7, t8, t9)) append + shrink(t7).map((t1, t2, t3, t4, t5, t6, _, t8, t9)) append + shrink(t8).map((t1, t2, t3, t4, t5, t6, t7, _, t9)) append shrink(t9).map((t1, t2, t3, t4, t5, t6, t7, t8, _)) } @@ -222,7 +221,7 @@ object Shrink extends ShrinkLowPriority { implicit val shrinkDuration: Shrink[Duration] = Shrink { case d: FiniteDuration => shrinkFiniteDuration.shrink(d) - case _ => LazyList.empty + case _ => Stream.empty } /** Transform a Shrink[T] to a Shrink[U] where T and U are two isomorphic types @@ -245,15 +244,15 @@ final class ShrinkIntegral[T](implicit ev: Integral[T]) extends Shrink[T] { val skipNegation = gteq(negate(one), one) // assumes x is non-zero. - private def halves(x: T): LazyList[T] = { + private def halves(x: T): Stream[T] = { val q = quot(x, two) - if (equiv(q, zero)) LazyList(zero) + if (equiv(q, zero)) Stream(zero) else if (skipNegation) q #:: halves(q) else q #:: negate(q) #:: halves(q) } - def shrink(x: T): LazyList[T] = - if (equiv(x, zero)) LazyList.empty[T] else halves(x) + def shrink(x: T): Stream[T] = + if (equiv(x, zero)) Stream.empty[T] else halves(x) } final class ShrinkFractional[T](implicit ev: Fractional[T]) extends Shrink[T] { @@ -268,9 +267,9 @@ final class ShrinkFractional[T](implicit ev: Fractional[T]) extends Shrink[T] { def closeToZero(x: T): Boolean = lteq(abs(x), small) // assumes x is not close to zero - private def halves(x: T): LazyList[T] = { + private def halves(x: T): Stream[T] = { val q = div(x, two) - if (closeToZero(q)) LazyList(zero) + if (closeToZero(q)) Stream(zero) else q #:: negate(q) #:: halves(q) } @@ -283,7 +282,7 @@ final class ShrinkFractional[T](implicit ev: Fractional[T]) extends Shrink[T] { !lt(div(x, two), x) } - def shrink(x: T): LazyList[T] = - if (closeToZero(x) || isUnusual(x)) LazyList.empty[T] + def shrink(x: T): Stream[T] = + if (closeToZero(x) || isUnusual(x)) Stream.empty[T] else halves(x) } diff --git a/src/main/scala/org/scalacheck/commands/Commands.scala b/src/main/scala/org/scalacheck/commands/Commands.scala index 737f3cb29..1cf097c9a 100644 --- a/src/main/scala/org/scalacheck/commands/Commands.scala +++ b/src/main/scala/org/scalacheck/commands/Commands.scala @@ -11,7 +11,6 @@ package org.scalacheck.commands import org.scalacheck._ import scala.util.{Try, Success, Failure} -import ScalaVersionSpecific._ /** An API for stateful testing in ScalaCheck. * @@ -271,8 +270,8 @@ trait Commands { ) private implicit val shrinkActions = Shrink[Actions] { as => - val shrinkedCmds: LazyList[Actions] = - Shrink.shrink(as.seqCmds).map(cs => as.copy(seqCmds = cs)) lazyAppendedAll + val shrinkedCmds: Stream[Actions] = + Shrink.shrink(as.seqCmds).map(cs => as.copy(seqCmds = cs)) append Shrink.shrink(as.parCmds).map(cs => as.copy(parCmds = cs)) Shrink.shrinkWithOrig[State](as.s)(shrinkState) flatMap { state => diff --git a/src/test/scala/org/scalacheck/ShrinkSpecification.scala b/src/test/scala/org/scalacheck/ShrinkSpecification.scala index 930e00a4f..83bc726cc 100644 --- a/src/test/scala/org/scalacheck/ShrinkSpecification.scala +++ b/src/test/scala/org/scalacheck/ShrinkSpecification.scala @@ -17,10 +17,10 @@ import scala.concurrent.duration.{Duration, FiniteDuration} object ShrinkSpecification extends Properties("Shrink") { - def shrinkClosure[T : Shrink](x: T): LazyList[T] = { + def shrinkClosure[T : Shrink](x: T): Stream[T] = { val xs = shrink[T](x) if(xs.isEmpty) xs - else xs.lazyAppendedAll(xs.take(1).map(shrinkClosure[T]).flatten) + else xs.append(xs.take(1).map(shrinkClosure[T]).flatten) } property("byte") = forAll { n: Byte => @@ -105,7 +105,7 @@ object ShrinkSpecification extends Properties("Shrink") { /* Ensure that shrink[T] terminates. (#244) * - * Let's say shrinking "terminates" when the stream / lazy list of values + * Let's say shrinking "terminates" when the stream of values * becomes empty. We can empirically determine the longest possible * sequence for a given type before termination. (Usually this * involves using the type's MinValue.) From 12c8a66c051c90c5e99b0a6d73968bc21e92557a Mon Sep 17 00:00:00 2001 From: Lukas Rytz Date: Wed, 6 Jun 2018 22:13:32 +0200 Subject: [PATCH 09/10] Small user guide update --- doc/UserGuide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/UserGuide.md b/doc/UserGuide.md index a8e48a843..ae9a348a9 100644 --- a/doc/UserGuide.md +++ b/doc/UserGuide.md @@ -778,7 +778,7 @@ can also define default shrinking methods. This is done by defining an implicit method that returns a `Shrink[T]` instance. This is done by using the `Shrink(...)` factory method, which as its only parameter takes a function and returns an instance of `Shrink[T]`. In turn, the function should take a value -of the given type `T`, and return a `Stream` (`LazyList` on Scala 2.13) of shrank +of the given type `T`, and return a `Stream` of shrank variants of the given value. As an example, look at the implicit `Shrink` instance for a tuple as it is defined in ScalaCheck: From 4848ee862b3bac2228b5d2fe07178cc4f4d2480b Mon Sep 17 00:00:00 2001 From: Lukas Rytz Date: Thu, 7 Jun 2018 10:30:26 +0200 Subject: [PATCH 10/10] Fix "Gen.frequency 3" test With `n == 0` the test effectively calls `Gen.frequency()`, which throws `IllegalArgumentException: no items with positive weights`. --- jvm/src/test/scala/org/scalacheck/GenSpecification.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jvm/src/test/scala/org/scalacheck/GenSpecification.scala b/jvm/src/test/scala/org/scalacheck/GenSpecification.scala index 7b1f6dae3..cfd478691 100644 --- a/jvm/src/test/scala/org/scalacheck/GenSpecification.scala +++ b/jvm/src/test/scala/org/scalacheck/GenSpecification.scala @@ -54,7 +54,7 @@ object GenSpecification extends Properties("Gen") with GenSpecificationVersionSp forAll(g) { n => true } } - property("frequency 3") = forAll(choose(0,100000)) { n => + property("frequency 3") = forAll(choose(1,100000)) { n => forAll(frequency(List.fill(n)((1,const(0))): _*)) { _ == 0 } }