diff --git a/build.sbt b/build.sbt index 9b2faa85f..176b396d2 100644 --- a/build.sbt +++ b/build.sbt @@ -33,7 +33,7 @@ lazy val weaverVersion = "0.8.4" ThisBuild / tlBaseVersion := "1.0" ThisBuild / tlCiReleaseBranches := Seq("main") // publish snapshots on `main` ThisBuild / tlCiScalafmtCheck := true -//ThisBuild / scalaVersion := scala212Version +//ThisBuild / scalaVersion := scala213Version ThisBuild / scalaVersion := scala3Version ThisBuild / crossScalaVersions := Seq(scala212Version, scala213Version, scala3Version) ThisBuild / developers += tlGitHubDev("tpolecat", "Rob Norris") @@ -98,9 +98,12 @@ lazy val compilerFlags = Seq( Compile / doc / scalacOptions --= Seq( "-Xfatal-warnings" ), -// Test / scalacOptions --= Seq( -// "-Xfatal-warnings" -// ), + // Disable warning when @nowarn annotation isn't suppressing a warning + // to simplify cross-building + // because 2.12 @nowarn doesn't actually do anything.. https://github.com/scala/bug/issues/12313 + scalacOptions ++= Seq( + "-Wconf:cat=unused-nowarn:s" + ), scalacOptions ++= (if (tlIsScala3.value) // Handle irrefutable patterns in for comprehensions Seq("-source:future", "-language:adhocExtensions") diff --git a/modules/core/src/main/scala-3/doobie/util/MkReadPlatform.scala b/modules/core/src/main/scala-3/doobie/util/MkReadPlatform.scala index 6eced2967..e77390817 100644 --- a/modules/core/src/main/scala-3/doobie/util/MkReadPlatform.scala +++ b/modules/core/src/main/scala-3/doobie/util/MkReadPlatform.scala @@ -6,6 +6,7 @@ package doobie.util import scala.deriving.Mirror import doobie.util.shapeless.OrElse +import scala.util.NotGiven trait MkReadPlatform: @@ -14,8 +15,10 @@ trait MkReadPlatform: implicit m: Mirror.ProductOf[P], i: A =:= m.MirroredElemTypes, - r: Read[A] `OrElse` Derived[MkRead[A]] + r: Read[A] `OrElse` Derived[MkRead[A]], + isNotCaseObj: NotGiven[m.MirroredElemTypes =:= EmptyTuple] ): Derived[MkRead[P]] = { + val _ = isNotCaseObj val read = r.fold(identity, _.instance).map(a => m.fromProduct(i(a))) new Derived(new MkRead(read)) } diff --git a/modules/core/src/main/scala-3/doobie/util/MkWritePlatform.scala b/modules/core/src/main/scala-3/doobie/util/MkWritePlatform.scala index a6172333e..91f393017 100644 --- a/modules/core/src/main/scala-3/doobie/util/MkWritePlatform.scala +++ b/modules/core/src/main/scala-3/doobie/util/MkWritePlatform.scala @@ -6,6 +6,7 @@ package doobie.util import scala.deriving.Mirror import doobie.util.shapeless.OrElse +import scala.util.NotGiven trait MkWritePlatform: @@ -14,8 +15,10 @@ trait MkWritePlatform: implicit m: Mirror.ProductOf[P], i: m.MirroredElemTypes =:= A, - w: Write[A] `OrElse` Derived[MkWrite[A]] + w: Write[A] `OrElse` Derived[MkWrite[A]], + isNotCaseObj: NotGiven[m.MirroredElemTypes =:= EmptyTuple] ): Derived[MkWrite[P]] = + val _ = isNotCaseObj val write: Write[P] = w.fold(identity, _.instance).contramap(p => i(Tuple.fromProductTyped(p))) new Derived( new MkWrite(write) diff --git a/modules/core/src/main/scala/doobie/util/read.scala b/modules/core/src/main/scala/doobie/util/read.scala index 831432248..0cbf29a26 100644 --- a/modules/core/src/main/scala/doobie/util/read.scala +++ b/modules/core/src/main/scala/doobie/util/read.scala @@ -63,7 +63,11 @@ object Read extends LowerPriorityRead { def apply[A](implicit ev: Read[A]): Read[A] = ev - def derived[A](implicit ev: Derived[MkRead[A]]): Read[A] = ev.instance.underlying + def derived[A](implicit + @implicitNotFound( + "Cannot derive Read instance. Please check that each field in the case class has a Read instance or can derive one") + ev: Derived[MkRead[A]] + ): Read[A] = ev.instance.underlying trait Auto extends MkReadInstances diff --git a/modules/core/src/main/scala/doobie/util/write.scala b/modules/core/src/main/scala/doobie/util/write.scala index 910a786d4..bd465572d 100644 --- a/modules/core/src/main/scala/doobie/util/write.scala +++ b/modules/core/src/main/scala/doobie/util/write.scala @@ -76,7 +76,11 @@ sealed trait Write[A] { object Write extends LowerPriorityWrite { def apply[A](implicit A: Write[A]): Write[A] = A - def derived[A](implicit ev: Derived[MkWrite[A]]): Write[A] = ev.instance + def derived[A](implicit + @implicitNotFound( + "Cannot derive Write instance. Please check that each field in the case class has a Write instance or can derive one") + ev: Derived[MkWrite[A]] + ): Write[A] = ev.instance trait Auto extends MkWriteInstances diff --git a/modules/core/src/test/scala/doobie/util/ReadSuite.scala b/modules/core/src/test/scala/doobie/util/ReadSuite.scala index 206d9be10..1e570c0df 100644 --- a/modules/core/src/test/scala/doobie/util/ReadSuite.scala +++ b/modules/core/src/test/scala/doobie/util/ReadSuite.scala @@ -11,6 +11,7 @@ import doobie.testutils.VoidExtensions import doobie.syntax.all.* import doobie.Query import munit.Location +import scala.annotation.nowarn class ReadSuite extends munit.FunSuite with ReadSuitePlatform { @@ -107,11 +108,18 @@ class ReadSuite extends munit.FunSuite with ReadSuitePlatform { } test("Read should not be derivable for case objects") { + val expectedDeriveError = + if (util.Properties.versionString.startsWith("version 2.12")) + "could not find implicit" + else + "Cannot derive" + assert(compileErrors("Read.derived[CaseObj.type]").contains(expectedDeriveError)) + assert(compileErrors("Read.derived[Option[CaseObj.type]]").contains(expectedDeriveError)) + + import doobie.implicits.* assert(compileErrors("Read[CaseObj.type]").contains("not find or construct")) - assert(compileErrors("Read.derived[CaseObj.type]").contains("not find or construct")) assert(compileErrors("Read[Option[CaseObj.type]]").contains("not find or construct")) - assert(compileErrors("Read.derived[Option[CaseObj.type]]").contains("not find or construct")) - } + }: @nowarn("msg=.*(u|U)nused import.*") test("Read should exist for Unit/Option[Unit]") { assertEquals(Read[Unit].length, 0) diff --git a/modules/core/src/test/scala/doobie/util/WriteSuite.scala b/modules/core/src/test/scala/doobie/util/WriteSuite.scala index a892973f1..57cc83c67 100644 --- a/modules/core/src/test/scala/doobie/util/WriteSuite.scala +++ b/modules/core/src/test/scala/doobie/util/WriteSuite.scala @@ -11,6 +11,7 @@ import cats.effect.unsafe.implicits.global import doobie.testutils.VoidExtensions import doobie.syntax.all.* import munit.Location +import scala.annotation.nowarn class WriteSuite extends munit.FunSuite with WriteSuitePlatform { @@ -105,11 +106,18 @@ class WriteSuite extends munit.FunSuite with WriteSuitePlatform { } test("Write should not be derivable for case objects") { - assert(compileErrors("Write[CaseObj.type]").contains("not find or construct")) - assert(compileErrors("Write.derived[CaseObj.type]").contains("not find or construct")) + val expectedDeriveError = + if (util.Properties.versionString.startsWith("version 2.12")) + "could not find implicit" + else + "Cannot derive" + assert(compileErrors("Write.derived[CaseObj.type]").contains(expectedDeriveError)) + assert(compileErrors("Write.derived[Option[CaseObj.type]]").contains(expectedDeriveError)) + + import doobie.implicits.* assert(compileErrors("Write[Option[CaseObj.type]]").contains("not find or construct")) - assert(compileErrors("Write.derived[Option[CaseObj.type]]").contains("not find or construct")) - } + assert(compileErrors("Write[CaseObj.type]").contains("not find or construct")) + }: @nowarn("msg=.*(u|U)nused import.*") test("Write should exist for Unit/Option[Unit]") { assertEquals(Write[Unit].length, 0)