From af467c7ddd2f93f9d6e35486b03a7b3e4d6cd455 Mon Sep 17 00:00:00 2001 From: Julien Richard-Foy Date: Thu, 29 Mar 2018 11:34:13 +0200 Subject: [PATCH 1/5] Use immutable.Seq and Iterable Preparation for the new collections library. Cherry-picked from work on trying to: Add support for Scala 2.13-M4 --- doc/UserGuide.md | 8 +++---- .../org/scalacheck/GenSpecification.scala | 1 + .../commands/CommandsSpecification.scala | 4 ++-- src/main/scala/org/scalacheck/Arbitrary.scala | 4 ++-- src/main/scala/org/scalacheck/Cogen.scala | 2 +- src/main/scala/org/scalacheck/Gen.scala | 23 ++++++++++--------- .../scala/org/scalacheck/Properties.scala | 2 +- .../org/scalacheck/ScalaCheckFramework.scala | 2 +- src/main/scala/org/scalacheck/Shrink.scala | 4 ++-- src/main/scala/org/scalacheck/Test.scala | 2 ++ .../org/scalacheck/commands/Commands.scala | 8 +++---- .../scala/org/scalacheck/util/Buildable.scala | 2 +- .../util/BuildableSpecification.scala | 2 +- 13 files changed, 34 insertions(+), 30 deletions(-) diff --git a/doc/UserGuide.md b/doc/UserGuide.md index 522b04aea..ce1a13e71 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: 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/jvm/src/test/scala/org/scalacheck/GenSpecification.scala b/jvm/src/test/scala/org/scalacheck/GenSpecification.scala index 59c2b9647..0774e2599 100644 --- a/jvm/src/test/scala/org/scalacheck/GenSpecification.scala +++ b/jvm/src/test/scala/org/scalacheck/GenSpecification.scala @@ -17,6 +17,7 @@ import Arbitrary._ import Shrink._ import java.util.Date import scala.util.{Try, Success, Failure} +import scala.collection.immutable.Seq object GenSpecification extends Properties("Gen") { 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..8cd0c5118 100644 --- a/src/main/scala/org/scalacheck/Arbitrary.scala +++ b/src/main/scala/org/scalacheck/Arbitrary.scala @@ -360,14 +360,14 @@ private[scalacheck] sealed trait ArbitraryLowPriority { * (such as lists, arrays, streams, 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] = { diff --git a/src/main/scala/org/scalacheck/Cogen.scala b/src/main/scala/org/scalacheck/Cogen.scala index c8585d9c9..16a757a0c 100644 --- a/src/main/scala/org/scalacheck/Cogen.scala +++ b/src/main/scala/org/scalacheck/Cogen.scala @@ -118,7 +118,7 @@ object Cogen extends CogenArities with CogenLowPriority { Cogen[String].contramap(_.name) implicit def cogenList[A: Cogen]: Cogen[List[A]] = - Cogen.it(_.iterator) + Cogen.it(_.iterator()) implicit def cogenVector[A: Cogen]: Cogen[Vector[A]] = Cogen.it(_.iterator) diff --git a/src/main/scala/org/scalacheck/Gen.scala b/src/main/scala/org/scalacheck/Gen.scala index 638995d71..182fd5961 100644 --- a/src/main/scala/org/scalacheck/Gen.scala +++ b/src/main/scala/org/scalacheck/Gen.scala @@ -17,6 +17,7 @@ import util.Buildable import util.SerializableCanBuildFroms._ import scala.annotation.tailrec +import scala.collection.immutable.Seq import scala.collection.immutable.TreeMap import scala.collection.mutable.ArrayBuffer import scala.concurrent.duration.{Duration, FiniteDuration} @@ -449,7 +450,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) => @@ -576,7 +577,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 +585,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 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..6004585cf 100644 --- a/src/main/scala/org/scalacheck/Shrink.scala +++ b/src/main/scala/org/scalacheck/Shrink.scala @@ -49,7 +49,7 @@ object Shrink extends ShrinkLowPriority { 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) @@ -58,7 +58,7 @@ object Shrink extends ShrinkLowPriority { } /** 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) diff --git a/src/main/scala/org/scalacheck/Test.scala b/src/main/scala/org/scalacheck/Test.scala index 67ec6cf46..c8778a09f 100644 --- a/src/main/scala/org/scalacheck/Test.scala +++ b/src/main/scala/org/scalacheck/Test.scala @@ -11,6 +11,8 @@ package org.scalacheck import Prop.Arg +import scala.collection.immutable.Seq + object Test { import util.{FreqMap, CmdLineParser, ConsoleReporter} diff --git a/src/main/scala/org/scalacheck/commands/Commands.scala b/src/main/scala/org/scalacheck/commands/Commands.scala index 1cf097c9a..7e578d420 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 diff --git a/src/main/scala/org/scalacheck/util/Buildable.scala b/src/main/scala/org/scalacheck/util/Buildable.scala index 2e8d5fd80..647b7e66f 100644 --- a/src/main/scala/org/scalacheck/util/Buildable.scala +++ b/src/main/scala/org/scalacheck/util/Buildable.scala @@ -14,7 +14,7 @@ import generic.CanBuildFrom 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() diff --git a/src/test/scala/org/scalacheck/util/BuildableSpecification.scala b/src/test/scala/org/scalacheck/util/BuildableSpecification.scala index 2311a8a65..adb9354ea 100644 --- a/src/test/scala/org/scalacheck/util/BuildableSpecification.scala +++ b/src/test/scala/org/scalacheck/util/BuildableSpecification.scala @@ -17,7 +17,7 @@ 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] From ed05010bcce31e0da7708a0f3361ee411bd7d553 Mon Sep 17 00:00:00 2001 From: "Aaron S. Hawley" Date: Wed, 4 Apr 2018 17:52:03 -0400 Subject: [PATCH 2/5] Iterator[A] does not take parameters Fix by removing parens. --- src/main/scala/org/scalacheck/Cogen.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/scala/org/scalacheck/Cogen.scala b/src/main/scala/org/scalacheck/Cogen.scala index 16a757a0c..c8585d9c9 100644 --- a/src/main/scala/org/scalacheck/Cogen.scala +++ b/src/main/scala/org/scalacheck/Cogen.scala @@ -118,7 +118,7 @@ object Cogen extends CogenArities with CogenLowPriority { Cogen[String].contramap(_.name) implicit def cogenList[A: Cogen]: Cogen[List[A]] = - Cogen.it(_.iterator()) + Cogen.it(_.iterator) implicit def cogenVector[A: Cogen]: Cogen[Vector[A]] = Cogen.it(_.iterator) From 88c291d49cd1109fa4f9266caca30080ebfd3edc Mon Sep 17 00:00:00 2001 From: "Aaron S. Hawley" Date: Wed, 4 Apr 2018 18:02:18 -0400 Subject: [PATCH 3/5] Explicitly convert Array to immutable.Seq The collections library doesn't do this automatically. Seemingly, this is because org.scalacheck.util.SerializableCanBuildFroms has implicits that interfere. --- src/main/scala/org/scalacheck/Arbitrary.scala | 2 +- src/main/scala/org/scalacheck/Gen.scala | 4 ++-- src/main/scala/org/scalacheck/Properties.scala | 3 ++- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/main/scala/org/scalacheck/Arbitrary.scala b/src/main/scala/org/scalacheck/Arbitrary.scala index 8cd0c5118..628e724c3 100644 --- a/src/main/scala/org/scalacheck/Arbitrary.scala +++ b/src/main/scala/org/scalacheck/Arbitrary.scala @@ -372,7 +372,7 @@ private[scalacheck] sealed trait ArbitraryLowPriority { 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.to[Vector])) } implicit def arbPartialFunction[A: Cogen, B: Arbitrary]: Arbitrary[PartialFunction[A, B]] = diff --git a/src/main/scala/org/scalacheck/Gen.scala b/src/main/scala/org/scalacheck/Gen.scala index 182fd5961..9176efb78 100644 --- a/src/main/scala/org/scalacheck/Gen.scala +++ b/src/main/scala/org/scalacheck/Gen.scala @@ -531,7 +531,7 @@ object Gen extends GenArities{ } /** Picks a random value from a list */ - def oneOf[T](t0: T, t1: T, tn: T*): Gen[T] = oneOf(t0 +: t1 +: tn) + def oneOf[T](t0: T, t1: T, tn: T*): Gen[T] = oneOf((t0 +: t1 +: tn).to[Vector]) /** Picks a random generator from a list */ def oneOf[T](g0: Gen[T], g1: Gen[T], gn: Gen[T]*): Gen[T] = { @@ -708,7 +708,7 @@ object Gen extends GenArities{ seed = s } } - r(Some(buf), seed) + r(Some(buf.to[Vector]), seed) } } diff --git a/src/main/scala/org/scalacheck/Properties.scala b/src/main/scala/org/scalacheck/Properties.scala index f726791ce..c7f013c28 100644 --- a/src/main/scala/org/scalacheck/Properties.scala +++ b/src/main/scala/org/scalacheck/Properties.scala @@ -12,6 +12,7 @@ package org.scalacheck import org.scalacheck.rng.Seed import language.reflectiveCalls +import collection.immutable.Seq import util.ConsoleReporter @@ -41,7 +42,7 @@ class Properties(val name: String) { /** Returns all properties of this collection in a list of name/property * pairs. */ - def properties: collection.Seq[(String,Prop)] = props + def properties: Seq[(String,Prop)] = props.to[Seq] /** Convenience method that checks the properties with the given parameters * (or default parameters, if not specified) From a68e80e7ea375a60fda51a349944555a50a43cad Mon Sep 17 00:00:00 2001 From: "Aaron S. Hawley" Date: Thu, 3 May 2018 09:14:43 -0400 Subject: [PATCH 4/5] Fix 2.12+ MiMa errors - method oneOf(Seq)Gen in object Gen's type is different in current version, where it is (immutable.Seq)Gen instead of (Seq)Gen - method sequence(Traversable,util.Buildable)Gen in object Gen's type is different in current version, where it is (Iterable,util.Buildable)Gen instead of (Traversable,util.Buildable)Gen - method properties()Seq in class Properties has a different result type in current version, where it is immutable.Seq rather than Seq - method checkProperties(Test#Parameters,Properties)Seq in object Test has a different result type in current version, where it is immutable.Seq rather than Seq - method canCreateNewSut(java.lang.Object,Traversable,Traversable)Boolean in interface commands.Commands's type is different in current version, where it is (java.lang.Object,Iterable,Iterable)Boolean instead of (java.lang.Object,Traversable,Traversable)Boolean - abstract method canCreateNewSut(java.lang.Object,Iterable,Iterable)Boolean in interface commands.Commands is present only in current version - method fromIterable(Traversable)java.lang.Object in interface util.Buildable's type is different in current version, where it is (Iterable)java.lang.Object instead of (Traversable)java.lang.Object --- project/MimaSettings.scala | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/project/MimaSettings.scala b/project/MimaSettings.scala index e13e3c4e9..7b9088681 100644 --- a/project/MimaSettings.scala +++ b/project/MimaSettings.scala @@ -12,10 +12,13 @@ object MimaSettings { removedPrivateMethods.map(exclude[DirectMissingMethodProblem](_)) ++ newMethods.map(exclude[ReversedMissingMethodProblem](_)) ++ removedPrivateClasses.map(exclude[MissingClassProblem](_)) ++ + methodTypeChanges.map(exclude[IncompatibleMethTypeProblem](_)) ++ + returnTypeChanges.map(exclude[IncompatibleResultTypeProblem](_)) ++ otherProblems ) private def newMethods = Seq( + "org.scalacheck.commands.Commands.canCreateNewSut" ) private def removedPrivateMethods = Seq( @@ -25,6 +28,18 @@ object MimaSettings { "org.scalacheck.Platform$EnableReflectiveInstantiation" ) + private def methodTypeChanges = Seq( + "org.scalacheck.Gen.oneOf", + "org.scalacheck.Gen.sequence", + "org.scalacheck.commands.Commands.canCreateNewSut", + "org.scalacheck.util.Buildable.fromIterable" + ) + + private def returnTypeChanges = Seq( + "org.scalacheck.Properties.properties", + "org.scalacheck.Test.checkProperties" + ) + private def otherProblems = Seq( ) From 7ff0a74ca11ff75f790bf7df515fe5715f69ad75 Mon Sep 17 00:00:00 2001 From: "Aaron S. Hawley" Date: Thu, 3 May 2018 09:21:19 -0400 Subject: [PATCH 5/5] Fix 2.11 MiMa errors - method fromIterable(Traversable)java.lang.Object in trait util.Buildable does not have a correspondent in current version - method fromIterable(Iterable)java.lang.Object in trait util.Buildable is present only in current version --- project/MimaSettings.scala | 2 ++ 1 file changed, 2 insertions(+) diff --git a/project/MimaSettings.scala b/project/MimaSettings.scala index 7b9088681..9ceb5fe9d 100644 --- a/project/MimaSettings.scala +++ b/project/MimaSettings.scala @@ -18,10 +18,12 @@ object MimaSettings { ) private def newMethods = Seq( + "org.scalacheck.util.Buildable.fromIterable", "org.scalacheck.commands.Commands.canCreateNewSut" ) private def removedPrivateMethods = Seq( + "org.scalacheck.util.Buildable.fromIterable" ) private def removedPrivateClasses = Seq(