diff --git a/.mill-version b/.mill-version index d225a9b31..ecd2d5d92 100644 --- a/.mill-version +++ b/.mill-version @@ -1,2 +1,2 @@ -0.11.2 +0.11.6 diff --git a/upickle/implicits/src-3/upickle/implicits/macros.scala b/upickle/implicits/src-3/upickle/implicits/macros.scala index fbcd90830..5711baec2 100644 --- a/upickle/implicits/src-3/upickle/implicits/macros.scala +++ b/upickle/implicits/src-3/upickle/implicits/macros.scala @@ -7,7 +7,8 @@ type IsInt[A <: Int] = A def getDefaultParamsImpl0[T](using Quotes, Type[T]): Map[String, Expr[AnyRef]] = import quotes.reflect._ - val sym = TypeTree.of[T].symbol + val unwrapped = TypeRepr.of[T] match{case AppliedType(p, v) => p case t => t} + val sym = unwrapped.typeSymbol if (!sym.isClassDef) Map.empty else @@ -23,14 +24,16 @@ def getDefaultParamsImpl0[T](using Quotes, Type[T]): Map[String, Expr[AnyRef]] = val body = comp.tree.asInstanceOf[ClassDef].body - val idents: List[Ref] = + val idents: List[Term] = for case deff @ DefDef(name, _, _, _) <- body if name.startsWith("$lessinit$greater$default") - yield Ref(deff.symbol) + yield TypeRepr.of[T] match{ // Fix copied from https://github.com/circe/circe/issues/2093 + case AppliedType(p, v) => Ref(deff.symbol).appliedToTypes(TypeRepr.of[T].typeArgs) + case t => Ref(deff.symbol) + } names.zip(idents.map(_.asExpr).map(e => '{$e.asInstanceOf[AnyRef]})).toMap - def extractKey[A](using Quotes)(sym: quotes.reflect.Symbol): Option[String] = import quotes.reflect._ sym diff --git a/upickle/test/src/upickle/MacroTests.scala b/upickle/test/src/upickle/MacroTests.scala index e06a3b14b..9735fe0e8 100644 --- a/upickle/test/src/upickle/MacroTests.scala +++ b/upickle/test/src/upickle/MacroTests.scala @@ -68,6 +68,16 @@ object SpecialChars{ implicit def rw: RW[SpecialChars] = default.macroRW } +object GenericIssue545{ + case class Person(id: Int, name: String = "test") + + implicit val personRw: upickle.default.ReadWriter[Person] = upickle.default.macroRW[Person] + + case class ApiResult[T](data: Option[T] = None, @upickle.implicits.key("total_count") totalCount: Int) + + implicit def apiResultRw[T: upickle.default.ReadWriter]: upickle.default.ReadWriter[ApiResult[T]] = upickle.default.macroRW[ApiResult[T]] +} + object MacroTests extends TestSuite { // Doesn't work :( @@ -564,5 +574,17 @@ object MacroTests extends TestSuite { rw(SpecialChars.`-1`(), """{"$type": "upickle.SpecialChars.-1"}""") rw(SpecialChars.`-1`(1), """{"$type": "upickle.SpecialChars.-1", "-1": 1}""") } + + test("genericIssue545"){ + // Make sure case class default values are properly picked up for + // generic case classes in Scala 3 + import upickle.implicits.key + + upickle.default.read[GenericIssue545.Person]("{\"id\":1}") ==> + GenericIssue545.Person(1) + + upickle.default.read[GenericIssue545.ApiResult[GenericIssue545.Person]]("{\"total_count\": 10}") ==> + GenericIssue545.ApiResult[GenericIssue545.Person](None, 10) + } } }