Skip to content

Commit

Permalink
Disable derivation for case object
Browse files Browse the repository at this point in the history
  • Loading branch information
jatcwang committed Nov 3, 2024
1 parent 8273448 commit c49cd4c
Show file tree
Hide file tree
Showing 7 changed files with 48 additions and 15 deletions.
11 changes: 7 additions & 4 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand Down Expand Up @@ -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")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ package doobie.util

import scala.deriving.Mirror
import doobie.util.shapeless.OrElse
import scala.util.NotGiven

trait MkReadPlatform:

Expand All @@ -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))
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ package doobie.util

import scala.deriving.Mirror
import doobie.util.shapeless.OrElse
import scala.util.NotGiven

trait MkWritePlatform:

Expand All @@ -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)
Expand Down
6 changes: 5 additions & 1 deletion modules/core/src/main/scala/doobie/util/read.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
6 changes: 5 additions & 1 deletion modules/core/src/main/scala/doobie/util/write.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
14 changes: 11 additions & 3 deletions modules/core/src/test/scala/doobie/util/ReadSuite.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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 {

Expand Down Expand Up @@ -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)
Expand Down
16 changes: 12 additions & 4 deletions modules/core/src/test/scala/doobie/util/WriteSuite.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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 {

Expand Down Expand Up @@ -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)
Expand Down

0 comments on commit c49cd4c

Please sign in to comment.