From 41402a87b5cddd8745a6136e8b924eb8bd34a71d Mon Sep 17 00:00:00 2001 From: "Kai(luo) Wang" Date: Thu, 10 Aug 2017 22:29:16 -0400 Subject: [PATCH] workaround for a possible scala bug in show for value class. (#1804) * workaround for a possible scala bug * renamed to cshow * hand rolling type class boilerplate * minor * move tests to scala 2.11+ to avoid 6260 in 2.10 --- build.sbt | 9 ++++++- core/src/main/scala/cats/Show.scala | 27 ++++++++++++++----- .../cats/tests/RegressionTests.scala | 25 +++++++++++++++++ .../scala/cats/tests/RegressionTests.scala | 2 +- 4 files changed, 55 insertions(+), 8 deletions(-) create mode 100644 tests/src/test/scala-2.11+/cats/tests/RegressionTests.scala diff --git a/build.sbt b/build.sbt index 57aa1c56b9..b3d1d9470e 100644 --- a/build.sbt +++ b/build.sbt @@ -54,7 +54,14 @@ lazy val commonSettings = Seq( // workaround for https://github.com/scalastyle/scalastyle-sbt-plugin/issues/47 scalastyleSources in Compile ++= (unmanagedSourceDirectories in Compile).value, ivyConfigurations += config("compile-time").hide, - unmanagedClasspath in Compile ++= update.value.select(configurationFilter("compile-time")) + unmanagedClasspath in Compile ++= update.value.select(configurationFilter("compile-time")), + unmanagedSourceDirectories in Test ++= { + val bd = baseDirectory.value + if (CrossVersion.partialVersion(scalaVersion.value) exists (_._2 >= 11)) + CrossType.Pure.sharedSrcDir(bd, "test").toList map (f => file(f.getPath + "-2.11+")) + else + Nil + } ) ++ warnUnusedImport ++ update2_12 ++ xlint diff --git a/core/src/main/scala/cats/Show.scala b/core/src/main/scala/cats/Show.scala index 590a49f836..4b090651c1 100644 --- a/core/src/main/scala/cats/Show.scala +++ b/core/src/main/scala/cats/Show.scala @@ -1,6 +1,5 @@ package cats -import simulacrum.typeclass import cats.functor.Contravariant /** @@ -10,16 +9,32 @@ import cats.functor.Contravariant * made a toString method, a Show instance will only exist if someone * explicitly provided one. */ -@typeclass trait Show[T] extends Show.ContravariantShow[T] { - // duplicated so simulacrum knows it requires an instance of this trait - def show(t: T): String -} +trait Show[T] extends Show.ContravariantShow[T] +/** + * Hand rolling the type class boilerplate due to scala/bug#6260 and scala/bug#10458 + */ object Show { - trait ContravariantShow[-T] { + + def apply[A](implicit instance: Show[A]): Show[A] = instance + + trait ContravariantShow[-T] extends Serializable { def show(t: T): String } + trait Ops[A] { + def typeClassInstance: Show[A] + def self: A + def show: String = typeClassInstance.show(self) + } + + trait ToShowOps { + implicit def toShow[A](target: A)(implicit tc: Show[A]): Ops[A] = new Ops[A] { + val self = target + val typeClassInstance = tc + } + } + /** creates an instance of [[Show]] using the provided function */ def show[A](f: A => String): Show[A] = new Show[A] { def show(a: A): String = f(a) diff --git a/tests/src/test/scala-2.11+/cats/tests/RegressionTests.scala b/tests/src/test/scala-2.11+/cats/tests/RegressionTests.scala new file mode 100644 index 0000000000..86e06bee16 --- /dev/null +++ b/tests/src/test/scala-2.11+/cats/tests/RegressionTests.scala @@ -0,0 +1,25 @@ +package cats +package tests + + +import ExtraRegressionTests._ + +class ExtraRegressionTests extends CatsSuite { + /** + * Placed here to work around scala/bug#6260 on scala 2.10 + */ + test("#1802 duplicated method name") { + Show[First[String]] + } +} + + +object ExtraRegressionTests { + final case class First[A](getFirst: A) extends AnyVal + object First { + implicit def showInstance[A](implicit ev: Show[A]): Show[First[A]] = new Show[First[A]] { + override def show(f: First[A]): String = s"First(${ev.show(f.getFirst)})" + } + } + +} diff --git a/tests/src/test/scala/cats/tests/RegressionTests.scala b/tests/src/test/scala/cats/tests/RegressionTests.scala index d5418217c5..be197e087b 100644 --- a/tests/src/test/scala/cats/tests/RegressionTests.scala +++ b/tests/src/test/scala/cats/tests/RegressionTests.scala @@ -4,7 +4,6 @@ package tests import cats.data.{Const, NonEmptyList} import scala.collection.mutable - class RegressionTests extends CatsSuite { // toy state class @@ -123,4 +122,5 @@ class RegressionTests extends CatsSuite { NonEmptyList.of(6,7,8).traverse_(validate) should === (Either.left("6 is greater than 5")) checkAndResetCount(1) } + }