[Bug] configured derivation withDefaults fails on class with type parameters and defaults
kailuowang opened this issue · comments
The following code fails
given Configuration = Configuration.default.withDefaults
case class FooWithDefaultSeq[A](a: Seq[A] = Nil)
object FooWithDefaultSeq:
given Codec[FooWithDefaultSeq[Int]] = Codec.AsObject.derivedConfigured
Error
[error] 237 | given Codec[FooWithDefaultSeq[Int]] = Codec.AsObject.derivedConfigured
[error] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
[error] |Exception occurred while executing macro expansion.
[error] |java.lang.Exception: Expected an expression. This is a partially applied Term. Try eta-expanding the term first.
[error] | at scala.quoted.runtime.impl.QuotesImpl$reflect$TreeMethods$.asExpr(QuotesImpl.scala:110)
[error] | at scala.quoted.runtime.impl.QuotesImpl$reflect$TreeMethods$.asExpr(QuotesImpl.scala:106)
[error] | at io.circe.derivation.Default$.$anonfun$1$$anonfun$1(Default.scala:43)
[error] | at io.circe.derivation.Default$.$anonfun$1$$anonfun$adapted$1(Default.scala:43)
[error] | at dotty.tools.dotc.quoted.PickledQuotes$$anon$1.transform(PickledQuotes.scala:109)
[error] | at dotty.tools.dotc.ast.Trees$Instance$TreeMap.transform(Trees.scala:1446)
[error] | at dotty.tools.dotc.quoted.PickledQuotes$$anon$1.transform(PickledQuotes.scala:134)
[error] | at dotty.tools.dotc.ast.Trees$Instance$TreeMap.transform$$anonfun$1(Trees.scala:1507)
[error] | at scala.collection.immutable.List.mapConserve(List.scala:472)
[error] | at dotty.tools.dotc.ast.Trees$Instance$TreeMap.transform(Trees.scala:1507)
[error] | at dotty.tools.dotc.ast.Trees$Instance$TreeMap.transform(Trees.scala:1412)
[error] | at dotty.tools.dotc.quoted.PickledQuotes$$anon$1.transform(PickledQuotes.scala:134)
[error] | at dotty.tools.dotc.quoted.PickledQuotes$.spliceTerms(PickledQuotes.scala:151)
[error] | at dotty.tools.dotc.quoted.PickledQuotes$.unpickleTerm(PickledQuotes.scala:87)
[error] | at scala.quoted.runtime.impl.QuotesImpl.unpickleExprV2(QuotesImpl.scala:3044)
[error] | at io.circe.derivation.Default$.$anonfun$1(Default.scala:43)
[error] | at io.circe.derivation.Default$.$anonfun$adapted$1(Default.scala:43)
[error] | at scala.collection.StrictOptimizedSeqFactory.tabulate(Factory.scala:341)
[error] | at scala.collection.StrictOptimizedSeqFactory.tabulate$(Factory.scala:336)
[error] | at scala.collection.immutable.List$.tabulate(List.scala:681)
[error] | at io.circe.derivation.Default$.getDefaultsImpl(Default.scala:43)
The code compiles if you remove the default value for the parameter, i.e.
case class FooWithDefaultSeq[A](a: Seq[A])
Sorry I am not familiar with scala 3 derivation enough to help debug this error.
cc @Lasering
Configuration.withDefaults
uses a macro to fetch the defaults of the class. The error is coming from the macro. Here is a more detailed explanation of the problem https://stackoverflow.com/questions/73024281/how-to-get-the-list-of-default-fields-values-for-typed-case-class
I'm looking into a solution, but I'm really not good with macros, if someone with more experience can lend a hand it would be greatly appreciated.
Some more context: lampepfl/dotty-feature-requests#162
When the class is generic this line:
companion.declaredMethod(s"$$lessinit$$greater$$default$$${i + 1}").headOption.map(Select(Ref(companion), _))
should be
companion.declaredMethod(s"$$lessinit$$greater$$default$$${i + 1}").headOption.map(s => Ref(companion).select(s).appliedToTypes(TypeRepr.of[T].typeArgs))
I just need to find a way to distinguish between a generic class and a non generic class.