diff --git a/upickle/implicits/src-2/upickle/implicits/internal/Macros.scala b/upickle/implicits/src-2/upickle/implicits/internal/Macros.scala index 4db982416..7285c0ad7 100644 --- a/upickle/implicits/src-2/upickle/implicits/internal/Macros.scala +++ b/upickle/implicits/src-2/upickle/implicits/internal/Macros.scala @@ -170,14 +170,14 @@ object Macros { def func(t: Type) = { - if (argSyms.length == 0) t + if (argSyms.isEmpty) t else { val concrete = tpe.normalize.asInstanceOf[TypeRef].args if (t.typeSymbol != definitions.RepeatedParamClass) { t.substituteTypes(typeParams, concrete) } else { - val TypeRef(pref, sym, args) = typeOf[Seq[Int]] + val TypeRef(pref, sym, _) = typeOf[Seq[Int]] import compat._ TypeRef(pref, sym, t.asInstanceOf[TypeRef].args) } @@ -301,6 +301,7 @@ object Macros { val localReaders = for (i <- rawArgs.indices) yield TermName("localReader" + i) val aggregates = for (i <- rawArgs.indices) yield TermName("aggregated" + i) + val typeTreeOfClass: c.Tree = c.universe.TypeTree(targetType) q""" ..${ for (i <- rawArgs.indices) @@ -355,7 +356,7 @@ object Macros { }){ this.errorMissingKeys(${rawArgs.length}, ${mappedArgs.toArray}) } - $companion.apply( + new $typeTreeOfClass( ..${ for(i <- rawArgs.indices) yield diff --git a/upickle/implicits/src-3/upickle/implicits/macros.scala b/upickle/implicits/src-3/upickle/implicits/macros.scala index 50d50ee9d..248d8b9ec 100644 --- a/upickle/implicits/src-3/upickle/implicits/macros.scala +++ b/upickle/implicits/src-3/upickle/implicits/macros.scala @@ -224,9 +224,8 @@ def tagKeyImpl[T](using Quotes, Type[T])(thisOuter: Expr[upickle.core.Types with inline def applyConstructor[T](params: Array[Any]): T = ${ applyConstructorImpl[T]('params) } def applyConstructorImpl[T](using quotes: Quotes, t0: Type[T])(params: Expr[Array[Any]]): Expr[T] = import quotes.reflect._ - def apply(typeApply: Option[List[TypeRepr]]) = { + def apply(appliedTypeOpt: Option[AppliedType]) = { val tpe = TypeRepr.of[T] - val companion: Symbol = tpe.classSymbol.get.companionModule val constructorSym = tpe.typeSymbol.primaryConstructor val constructorParamSymss = constructorSym.paramSymss @@ -238,8 +237,8 @@ def applyConstructorImpl[T](using quotes: Quotes, t0: Type[T])(params: Expr[Arra val lhs = '{$params(${ Expr(i) })} val tpe0 = constructorTpe.memberType(sym0) - typeApply.map(tps => tpe0.substituteTypes(tparams0, tps)).getOrElse(tpe0) match { - case AnnotatedType(AppliedType(base, Seq(arg)), x) + appliedTypeOpt.map(appliedType => tpe0.substituteTypes(tparams0, appliedType.args)).getOrElse(tpe0) match { + case AnnotatedType(AppliedType(_, Seq(arg)), x) if x.tpe =:= defn.RepeatedAnnot.typeRef => arg.asType match { case '[t] => @@ -253,18 +252,18 @@ def applyConstructorImpl[T](using quotes: Quotes, t0: Type[T])(params: Expr[Arra case '[t] => '{ $lhs.asInstanceOf[t] }.asTerm } } - } - typeApply match{ - case None => Select.overloaded(Ref(companion), "apply", Nil, rhs).asExprOf[T] - case Some(args) => - Select.overloaded(Ref(companion), "apply", args, rhs).asExprOf[T] + val constructorTree = appliedTypeOpt match { + case Some(AppliedType(tycon, args)) => New(Inferred(tycon)).select(constructorSym).appliedToTypes(args) + case None => New(TypeTree.of[T]).select(constructorSym) } + + constructorTree.appliedToArgs(rhs).asExprOf[T] } TypeRepr.of[T] match{ - case t: AppliedType => apply(Some(t.args)) + case t: AppliedType => apply(Some(t)) case t: TypeRef => apply(None) case t: TermRef => '{${Ref(t.classSymbol.get.companionModule).asExprOf[Any]}.asInstanceOf[T]} } diff --git a/upickle/test/src/upickle/MacroTests.scala b/upickle/test/src/upickle/MacroTests.scala index c135073ec..10fb3bf19 100644 --- a/upickle/test/src/upickle/MacroTests.scala +++ b/upickle/test/src/upickle/MacroTests.scala @@ -144,6 +144,23 @@ object TagName{ implicit val quxRw: TagNamePickler.ReadWriter[Qux] = TagNamePickler.macroRW implicit val fooRw: TagNamePickler.ReadWriter[Foo] = TagNamePickler.macroRW } + + +// Defined for compilation test +sealed trait Term + +case class Var(name: String) extends Term +object Var { + def apply(name: String): Term = new Var(name) + implicit val rw: RW[Var] = upickle.default.macroRW +} + +case class Constant(value: Int) extends Term +object Constant { + def apply(value: Int): Term = new Constant(value) + implicit val rw: RW[Constant] = upickle.default.macroRW +} + object MacroTests extends TestSuite { // Doesn't work :(