From f9fd03db46098cf6bbc3c9c12c22812fd0a616f8 Mon Sep 17 00:00:00 2001 From: Nabil Abdel-Hafeez <7283535+987Nabil@users.noreply.github.com> Date: Sat, 21 Oct 2023 20:21:12 +0200 Subject: [PATCH] Find implicits first, before deriving any kind of schema in Scala 3 (#611) * Find implicits first, before deriving any kind of schema in Scala 3 Also fixes #580 * Find implicits first, before deriving any kind of schema in Scala 3 --- .../scala-3/zio/schema/DeriveSchema.scala | 109 +++++++++--------- 1 file changed, 57 insertions(+), 52 deletions(-) diff --git a/zio-schema-derivation/shared/src/main/scala-3/zio/schema/DeriveSchema.scala b/zio-schema-derivation/shared/src/main/scala-3/zio/schema/DeriveSchema.scala index 359ab429b..722a23223 100644 --- a/zio-schema-derivation/shared/src/main/scala-3/zio/schema/DeriveSchema.scala +++ b/zio-schema-derivation/shared/src/main/scala-3/zio/schema/DeriveSchema.scala @@ -50,59 +50,64 @@ private case class DeriveSchema()(using val ctx: Quotes) extends ReflectionUtils val result = stack.find(typeRepr) match { case Some(ref) => '{ Schema.defer(${ref.asExprOf[Schema[T]]}) } - case None => - typeRepr.asType match { - case '[List[a]] => - val schema = deriveSchema[a](stack) - '{ Schema.list(Schema.defer(${schema})) }.asExprOf[Schema[T]] - case '[scala.util.Either[a, b]] => - val schemaA = deriveSchema[a](stack) - val schemaB = deriveSchema[b](stack) - '{ Schema.either(Schema.defer(${schemaA}), Schema.defer(${schemaB})) }.asExprOf[Schema[T]] - case '[Option[a]] => - val schema = deriveSchema[a](stack) - // throw new Error(s"OPITOS ${schema.show}") - '{ Schema.option(Schema.defer($schema)) }.asExprOf[Schema[T]] - case '[scala.collection.Set[a]] => - val schema = deriveSchema[a](stack) - '{ Schema.set(Schema.defer(${schema})) }.asExprOf[Schema[T]] - case '[Vector[a]] => - val schema = deriveSchema[a](stack) - '{ Schema.vector(Schema.defer(${schema})) }.asExprOf[Schema[T]] - case '[scala.collection.Map[a, b]] => - val schemaA = deriveSchema[a](stack) - val schemaB = deriveSchema[b](stack) - '{ Schema.map(Schema.defer(${schemaA}), Schema.defer(${schemaB})) }.asExprOf[Schema[T]] - case '[zio.Chunk[a]] => - val schema = deriveSchema[a](stack) - '{ Schema.chunk(Schema.defer(${schema})) }.asExprOf[Schema[T]] - case _ => - val summoned = if (!top) Expr.summon[Schema[T]] else None - summoned match { - case Some(schema) => - // println(s"FOR TYPE ${typeRepr.show}") - // println(s"STACK ${stack.find(typeRepr)}") - // println(s"Found schema ${schema.show}") - schema - case _ => - Mirror(typeRepr) match { - case Some(mirror) => - mirror.mirrorType match { - case MirrorType.Sum => - deriveEnum[T](mirror, stack) - case MirrorType.Product => - deriveCaseClass[T](mirror, stack, top) - } - case None => - val sym = typeRepr.typeSymbol - if (sym.isClassDef && sym.flags.is(Flags.Module)) { - deriveCaseObject[T](stack, top) - } - else { - report.errorAndAbort(s"Deriving schema for ${typeRepr.show} is not supported") - } + case None => + val summoned = Expr.summon[Schema[T]] + if (!top && summoned.isDefined) { + '{ Schema.defer(${summoned.get}) }.asExprOf[Schema[T]] + } else { + typeRepr.asType match { + case '[List[a]] => + val schema = deriveSchema[a](stack) + '{ Schema.list(Schema.defer(${schema})) }.asExprOf[Schema[T]] + case '[scala.util.Either[a, b]] => + val schemaA = deriveSchema[a](stack) + val schemaB = deriveSchema[b](stack) + '{ Schema.either(Schema.defer(${schemaA}), Schema.defer(${schemaB})) }.asExprOf[Schema[T]] + case '[Option[a]] => + val schema = deriveSchema[a](stack) + // throw new Error(s"OPITOS ${schema.show}") + '{ Schema.option(Schema.defer($schema)) }.asExprOf[Schema[T]] + case '[scala.collection.Set[a]] => + val schema = deriveSchema[a](stack) + '{ Schema.set(Schema.defer(${schema})) }.asExprOf[Schema[T]] + case '[Vector[a]] => + val schema = deriveSchema[a](stack) + '{ Schema.vector(Schema.defer(${schema})) }.asExprOf[Schema[T]] + case '[scala.collection.Map[a, b]] => + val schemaA = deriveSchema[a](stack) + val schemaB = deriveSchema[b](stack) + '{ Schema.map(Schema.defer(${schemaA}), Schema.defer(${schemaB})) }.asExprOf[Schema[T]] + case '[zio.Chunk[a]] => + val schema = deriveSchema[a](stack) + '{ Schema.chunk(Schema.defer(${schema})) }.asExprOf[Schema[T]] + case _ => + val summoned = if (!top) Expr.summon[Schema[T]] else None + summoned match { + case Some(schema) => + // println(s"FOR TYPE ${typeRepr.show}") + // println(s"STACK ${stack.find(typeRepr)}") + // println(s"Found schema ${schema.show}") + schema + case _ => + Mirror(typeRepr) match { + case Some(mirror) => + mirror.mirrorType match { + case MirrorType.Sum => + deriveEnum[T](mirror, stack) + case MirrorType.Product => + deriveCaseClass[T](mirror, stack, top) + } + case None => + val sym = typeRepr.typeSymbol + if (sym.isClassDef && sym.flags.is(Flags.Module)) { + deriveCaseObject[T](stack, top) + } + else { + report.errorAndAbort(s"Deriving schema for ${typeRepr.show} is not supported") + } + } } - } + } } }