diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b0e1a03e16..f47727d16a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -104,7 +104,7 @@ jobs: run: sbt ++${{ matrix.scala }} buildJVM bench/test - name: Binary compatibility ${{ matrix.scala }} - if: matrix.platform == 'jvm' && (matrix.scala != '3.0.2') + if: matrix.platform == 'jvm' run: sbt ++${{ matrix.scala }} clean validateBC scalafix: diff --git a/binCompatTest/src/main/scala/catsBC/MimaExceptions.scala b/binCompatTest/src/main/scala/catsBC/MimaExceptions.scala index 03ac4d7045..c4972d3132 100644 --- a/binCompatTest/src/main/scala/catsBC/MimaExceptions.scala +++ b/binCompatTest/src/main/scala/catsBC/MimaExceptions.scala @@ -19,7 +19,7 @@ object MimaExceptions { cats.data.Kleisli.catsDataCommutativeFlatMapForKleisli[Option, Int], cats.data.IRWST.catsDataStrongForIRWST[List, Int, Int, Int], cats.data.OptionT.catsDataMonadErrorMonadForOptionT[List], - FunctionK.lift(headOption), + // FunctionK.lift(headOption), // Doesn't work in Scala 3 cats.data.OptionT.catsDataMonadErrorForOptionT[Either[String, *], String], cats.data.OptionT[Either[String, *], Int](Right(Some(17))).ensure("error")(_ => true), "blah".leftNec[Int], diff --git a/build.sbt b/build.sbt index d80d5d083d..cb750bd2ef 100644 --- a/build.sbt +++ b/build.sbt @@ -91,7 +91,7 @@ ThisBuild / githubWorkflowBuild := Seq( WorkflowStep.Sbt( List("clean", "validateBC"), // cleaning here to avoid issues with codecov name = Some("Binary compatibility ${{ matrix.scala }}"), - cond = Some(JvmCond + " && " + Scala2Cond) + cond = Some(JvmCond) ) ) @@ -339,18 +339,21 @@ def mimaPrevious(moduleName: String, scalaVer: String, ver: String, includeCats1 Version(ver) match { case Some(Version(major, Seq(minor, patch), _)) => semverBinCompatVersions(major, minor, patch) - .map { case (maj, min, pat) => s"$maj.$min.$pat" } + .collect { case (maj, min, pat) if !scalaVer.startsWith("3.") || (maj >= 2 && min >= 7) => s"$maj.$min.$pat" } case _ => List.empty[String] } } // Safety Net For Exclusions - lazy val excludedVersions: List[String] = List() + lazy val excludedVersions: List[String] = List("2.7.0") // cursed bincompat on Scala 3 // Safety Net for Inclusions - lazy val extraVersions: List[String] = List("1.0.1", "1.1.0", "1.2.0", "1.3.1", "1.4.0", "1.5.0", "1.6.1") + lazy val extraCats1Versions: List[String] = List("1.0.1", "1.1.0", "1.2.0", "1.3.1", "1.4.0", "1.5.0", "1.6.1") - (mimaVersions ++ (if (priorTo2_13(scalaVer) && includeCats1) extraVersions else Nil)) + // Safety Net, starting with Scala 3 introduction in 2.6.1 + lazy val extraVersions: List[String] = List("2.6.1") + + (mimaVersions ++ extraVersions ++ (if (priorTo2_13(scalaVer) && includeCats1) extraCats1Versions else Nil)) .filterNot(excludedVersions.contains(_)) .map(v => "org.typelevel" %% moduleName % v) } @@ -521,7 +524,13 @@ def mimaSettings(moduleName: String, includeCats1: Boolean = true) = exclude[DirectAbstractMethodProblem]("cats.free.ContravariantCoyoneda.k"), exclude[ReversedAbstractMethodProblem]("cats.free.ContravariantCoyoneda.k"), exclude[DirectAbstractMethodProblem]("cats.free.Coyoneda.k"), - exclude[ReversedAbstractMethodProblem]("cats.free.Coyoneda.k") + exclude[ReversedAbstractMethodProblem]("cats.free.Coyoneda.k"), + exclude[DirectMissingMethodProblem]("cats.free.ContravariantCoyoneda.unsafeApply"), + exclude[DirectMissingMethodProblem]("cats.free.ContravariantCoyoneda.ks"), + exclude[DirectMissingMethodProblem]("cats.free.ContravariantCoyoneda.unsafeApply"), + exclude[DirectMissingMethodProblem]("cats.free.Coyoneda.unsafeApply"), + exclude[DirectMissingMethodProblem]("cats.free.Coyoneda.ks"), + exclude[DirectMissingMethodProblem]("cats.free.Coyoneda.unsafeApply") ) } ) @@ -876,9 +885,16 @@ lazy val binCompatTest = project // see https://github.com/typelevel/cats/pull/3079#discussion_r327181584 // see https://github.com/typelevel/cats/pull/3026#discussion_r321984342 useCoursier := false, - addCompilerPlugin(("org.typelevel" %% "kind-projector" % kindProjectorVersion).cross(CrossVersion.full)), + libraryDependencies ++= { + if (isDotty.value) Nil + else + Seq( + compilerPlugin(("org.typelevel" %% "kind-projector" % kindProjectorVersion).cross(CrossVersion.full)) + ) + }, libraryDependencies += mimaPrevious("cats-core", scalaVersion.value, version.value).last % Provided, - scalacOptions ++= (if (priorTo2_13(scalaVersion.value)) Seq("-Ypartial-unification") else Nil) + scalacOptions ++= (if (priorTo2_13(scalaVersion.value)) Seq("-Ypartial-unification") else Nil), + scalacOptions ++= (if (isDotty.value) Seq("-Ykind-projector") else Nil) ) .settings(testingDependencies) .dependsOn(core.jvm % Test) diff --git a/core/src/main/scala/cats/Invariant.scala b/core/src/main/scala/cats/Invariant.scala index 4ec85f0931..546d7a82e2 100644 --- a/core/src/main/scala/cats/Invariant.scala +++ b/core/src/main/scala/cats/Invariant.scala @@ -102,9 +102,10 @@ import scala.util.control.TailCalls.TailRec @suppressUnusedImportWarningForScalaVersionSpecific object Invariant extends ScalaVersionSpecificInvariantInstances with InvariantInstances0 { - implicit def catsInstancesForId + private[cats] def catsInstancesForId: Distributive[Id] with Comonad[Id] = catsInstancesForIdBinCompat1 + implicit def catsInstancesForIdBinCompat1 : Distributive[Id] with Bimonad[Id] with CommutativeMonad[Id] with NonEmptyTraverse[Id] = - cats.catsInstancesForId + cats.catsInstancesForIdBinCompat1 implicit def catsMonadErrorForEither[A]: MonadError[Either[A, *], A] = cats.instances.either.catsStdInstancesForEither[A] implicit def catsInstancesForOption diff --git a/core/src/main/scala/cats/Semigroupal.scala b/core/src/main/scala/cats/Semigroupal.scala index e93d711b20..4b05de6a39 100644 --- a/core/src/main/scala/cats/Semigroupal.scala +++ b/core/src/main/scala/cats/Semigroupal.scala @@ -47,7 +47,7 @@ import simulacrum.typeclass } object Semigroupal extends ScalaVersionSpecificSemigroupalInstances with SemigroupalArityFunctions { - implicit def catsSemigroupalForId: Semigroupal[Id] = catsInstancesForId + implicit def catsSemigroupalForId: Semigroupal[Id] = catsInstancesForIdBinCompat1 implicit def catsSemigroupalForOption: Semigroupal[Option] = cats.instances.option.catsStdInstancesForOption implicit def catsSemigroupalForTry: Semigroupal[Try] = cats.instances.try_.catsStdInstancesForTry implicit def catsSemigroupalForFuture(implicit ec: ExecutionContext): Semigroupal[Future] = diff --git a/core/src/main/scala/cats/UnorderedFoldable.scala b/core/src/main/scala/cats/UnorderedFoldable.scala index 668ecf928c..c1817ac165 100644 --- a/core/src/main/scala/cats/UnorderedFoldable.scala +++ b/core/src/main/scala/cats/UnorderedFoldable.scala @@ -96,7 +96,7 @@ object UnorderedFoldable } } - implicit def catsNonEmptyTraverseForId: NonEmptyTraverse[Id] = catsInstancesForId + implicit def catsNonEmptyTraverseForId: NonEmptyTraverse[Id] = catsInstancesForIdBinCompat1 implicit def catsTraverseForOption: Traverse[Option] = cats.instances.option.catsStdInstancesForOption implicit def catsTraverseForList: Traverse[List] = cats.instances.list.catsStdInstancesForList implicit def catsTraverseForSeq: Traverse[Seq] = cats.instances.seq.catsStdInstancesForSeq diff --git a/core/src/main/scala/cats/package.scala b/core/src/main/scala/cats/package.scala index 79c5c07101..4a2f026ed3 100644 --- a/core/src/main/scala/cats/package.scala +++ b/core/src/main/scala/cats/package.scala @@ -70,7 +70,12 @@ package object cats { type Endo[A] = A => A - val catsInstancesForId: Bimonad[Id] with CommutativeMonad[Id] with NonEmptyTraverse[Id] with Distributive[Id] = + @deprecated("retained for binary compatibility", "2.7.1") + private[cats] def catsInstancesForId + : Bimonad[Id] with CommutativeMonad[Id] with Comonad[Id] with NonEmptyTraverse[Id] with Distributive[Id] = + catsInstancesForIdBinCompat1 + val catsInstancesForIdBinCompat1 + : Bimonad[Id] with CommutativeMonad[Id] with NonEmptyTraverse[Id] with Distributive[Id] = new Bimonad[Id] with CommutativeMonad[Id] with NonEmptyTraverse[Id] with Distributive[Id] { def pure[A](a: A): A = a def extract[A](a: A): A = a