From fc9d748668ae2dcc26b7651dac25fc57b2261e93 Mon Sep 17 00:00:00 2001 From: Yoshimura Yuu Date: Sun, 27 Mar 2022 18:33:48 +0900 Subject: [PATCH] Fix partially #30 (only Scala 3) --- .../main/scala-3/izumi/reflect/TagMacro.scala | 21 +++++++++++++++---- .../scala-3/izumi/reflect/test/TagTest.scala | 9 ++++++++ 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/izumi-reflect/izumi-reflect/src/main/scala-3/izumi/reflect/TagMacro.scala b/izumi-reflect/izumi-reflect/src/main/scala-3/izumi/reflect/TagMacro.scala index 5ca7a0a1..352b2124 100644 --- a/izumi-reflect/izumi-reflect/src/main/scala-3/izumi/reflect/TagMacro.scala +++ b/izumi-reflect/izumi-reflect/src/main/scala-3/izumi/reflect/TagMacro.scala @@ -42,8 +42,6 @@ final class TagMacro(using override val qctx: Quotes) extends InspectorBase { private def summonCombinedTag[T <: AnyKind: Type](typeRepr: TypeRepr): Expr[Tag[T]] = typeRepr.dealias match { - case x if x.typeSymbol.isTypeParam => summonTag(x) - case AppliedType(ctor, args) => val ctorTag = createTagExpr(ctor.asType) val argsTags = Expr.ofList(args.map(mkLtt)) @@ -64,27 +62,42 @@ final class TagMacro(using override val qctx: Quotes) extends InspectorBase { val ltts: Expr[List[LightTypeTag]] = Expr.ofList(ltts0) '{ Tag.unionTag[T](classOf[Any], $ltts) } + case x if x.typeSymbol.isTypeParam => summonTag(x) + case _ => throw new Exception(s"Unsupported type: $typeRepr") } private def summonTag[any <: AnyKind](typeRepr: TypeRepr): Expr[Tag[any]] = + summonTagEither(typeRepr) match { + case Right(tag) => tag.asInstanceOf[Expr[Tag[any]]] + case Left(message) => report.errorAndAbort(message) + } + + private def summonTagEither[any <: AnyKind](typeRepr: TypeRepr): Either[String, Expr[Tag[any]]] = typeRepr.asType match { case given Type[a] => val message = s"Cannot find implicit Tag[${Type.show[a]}]" - Expr.summon[Tag[a]].getOrElse(report.errorAndAbort(message)).asInstanceOf[Expr[Tag[any]]] + Expr.summon[Tag[a]] match { + case Some(tag) => Right(tag.asInstanceOf[Expr[Tag[any]]]) + case None => Left(message) + } } + private def summonable[any <: AnyKind](typeRepr: TypeRepr): Boolean = + summonTagEither(typeRepr).isRight + /** * Returns true if the given type contains no type parameters * (this means the type is not "weak" https://stackoverflow.com/questions/29435985/weaktypetag-v-typetag) */ private def allPartsStrong(typeRepr: TypeRepr): Boolean = typeRepr.dealias match { - case x if x.typeSymbol.isTypeParam => false + case x if x.typeSymbol.isTypeParam && summonable(x) => false case AppliedType(tpe, args) => allPartsStrong(tpe) && args.forall(allPartsStrong) case AndType(lhs, rhs) => allPartsStrong(lhs) && allPartsStrong(rhs) case OrType(lhs, rhs) => allPartsStrong(lhs) && allPartsStrong(rhs) + case x if x.typeSymbol.isTypeParam => false case TypeRef(tpe, name) => allPartsStrong(tpe) case TermRef(tpe, name) => allPartsStrong(tpe) case ThisType(tpe) => allPartsStrong(tpe) diff --git a/izumi-reflect/izumi-reflect/src/test/scala-3/izumi/reflect/test/TagTest.scala b/izumi-reflect/izumi-reflect/src/test/scala-3/izumi/reflect/test/TagTest.scala index 411c124f..b8b05329 100644 --- a/izumi-reflect/izumi-reflect/src/test/scala-3/izumi/reflect/test/TagTest.scala +++ b/izumi-reflect/izumi-reflect/src/test/scala-3/izumi/reflect/test/TagTest.scala @@ -23,6 +23,15 @@ class TagTest extends SharedTagTest with TagAssertions { assertNotChild(Tag[Animal | String].tag, Tag[Dog | String].tag) } + "Support HKTag for unapplied type lambdas with type bounds" in { + trait X + trait XAble[A <: X] + class Y extends X + + def getTag[F[_ <: X]: Tag.auto.T] = Tag[F[Y]] + + assertSame(getTag[XAble].tag, Tag[XAble[Y]].tag) + } } }