quotes.reflect.memberType can return ClassInfo
See original GitHub issueDiscussed in https://github.com/lampepfl/dotty/discussions/15157
in the example below, memberType
returns a ClassInfo
, which is not exposed in the quotes api, and seems unexpected when pattern matching on a type. It seems that memberType
should escape this?
Originally posted by adamw May 10, 2022 I’m trying to summon a typeclass instance for each child class of a sealed trait. So far I’ve got the following code (here simplified):
import scala.quoted.*
object TestMacro:
inline def test[T]: Unit = ${ testImpl[T] }
def testImpl[T: Type](using Quotes): Expr[Unit] =
import quotes.reflect.*
val tpe = TypeRepr.of[T]
tpe.typeSymbol.children.map { childSymbol =>
val childTpe = tpe.memberType(childSymbol)
println("Child TypeRepr: " + childTpe)
childTpe.asType match
case '[c] =>
println("Got Type!")
}
'{ () }
The childTpe: TypeRepr
is correct, however I get an exception when converting it to a Type
and trying to get a handle to the type parameter c
(so that later I can do Expr.summon[MyTypeClass[c]]
). Using the following invocation:
sealed trait A
case class X(i: Int) extends A
object Test extends App {
TestMacro.test[A]
}
The output is:
Child type: ClassInfo(ThisType(TypeRef(NoPrefix,module class newschema)), class X, List(TypeRef(ThisType(TypeRef(NoPrefix,module class lang)),class Object), TypeRef(ThisType(TypeRef(NoPrefix,module class newschema)),trait A), TypeRef(TermRef(TermRef(NoPrefix,object _root_),object scala),trait Product), TypeRef(ThisType(TypeRef(NoPrefix,module class io)),trait Serializable)))
[info] assertion failure for class X in package sttp.tapir.newschema <:< c, frozen = false
[error] -- Error: Test.scala:33:16
[error] 33 | TestMacro.test[A]
[error] | ^^^^^^^^^^^^^^^^^
[error] |Exception occurred while executing macro expansion.
[error] |java.lang.AssertionError: assertion failed: ClassInfo(ThisType(TypeRef(NoPrefix,module class newschema)), class X, List(TypeRef(ThisType(TypeRef(NoPrefix,module class lang)),class Object), TypeRef(ThisType(TypeRef(NoPrefix,module class newschema)),trait A), TypeRef(TermRef(TermRef(NoPrefix,object _root_),object scala),trait Product), TypeRef(ThisType(TypeRef(NoPrefix,module class io)),trait Serializable)))
[error] | at scala.runtime.Scala3RunTime$.assertFailed(Scala3RunTime.scala:8)
[error] | at dotty.tools.dotc.core.Types$TypeBounds.<init>(Types.scala:5038)
[error] | at dotty.tools.dotc.core.Types$RealTypeBounds.<init>(Types.scala:5114)
[error] | at dotty.tools.dotc.core.Types$TypeBounds$.apply(Types.scala:5158)
[error] | at dotty.tools.dotc.core.Types$TypeBounds.derivedTypeBounds(Types.scala:5046)
[error] | at dotty.tools.dotc.core.ConstraintHandling.addOneBound(ConstraintHandling.scala:262)
[error] | at dotty.tools.dotc.core.ConstraintHandling.addOneBound$(ConstraintHandling.scala:29)
[error] | at dotty.tools.dotc.core.ProperGadtConstraint.addOneBound(GadtConstraint.scala:61)
[error] | at dotty.tools.dotc.core.ConstraintHandling.addBoundTransitively(ConstraintHandling.scala:316)
[error] | at dotty.tools.dotc.core.ConstraintHandling.addBoundTransitively$(ConstraintHandling.scala:29)
[error] | at dotty.tools.dotc.core.ProperGadtConstraint.addBoundTransitively(GadtConstraint.scala:61)
[error] | at dotty.tools.dotc.core.ProperGadtConstraint.addBound(GadtConstraint.scala:168)
[error] | at dotty.tools.dotc.core.TypeComparer.gadtAddLowerBound(TypeComparer.scala:116)
[error] | at dotty.tools.dotc.core.TypeComparer.narrowGADTBounds(TypeComparer.scala:1893)
[error] | at dotty.tools.dotc.core.TypeComparer.compareGADT$1(TypeComparer.scala:509)
[error] | at dotty.tools.dotc.core.TypeComparer.thirdTryNamed$1(TypeComparer.scala:512)
[error] | at dotty.tools.dotc.core.TypeComparer.thirdTry$1(TypeComparer.scala:561)
[error] | at dotty.tools.dotc.core.TypeComparer.secondTry$1(TypeComparer.scala:492)
[error] | at dotty.tools.dotc.core.TypeComparer.compareNamed$1(TypeComparer.scala:301)
[error] | at dotty.tools.dotc.core.TypeComparer.firstTry$1(TypeComparer.scala:307)
[error] | at dotty.tools.dotc.core.TypeComparer.recur(TypeComparer.scala:1309)
[error] | at dotty.tools.dotc.core.TypeComparer.isSubType(TypeComparer.scala:189)
[error] | at dotty.tools.dotc.core.TypeComparer.isSubType(TypeComparer.scala:199)
[error] | at dotty.tools.dotc.core.TypeComparer.topLevelSubType(TypeComparer.scala:126)
[error] | at dotty.tools.dotc.core.TypeComparer$.topLevelSubType(TypeComparer.scala:2709)
[error] | at dotty.tools.dotc.core.Types$Type.$less$colon$less(Types.scala:1040)
[error] | at scala.quoted.runtime.impl.QuoteMatcher$.$eq$qmark$eq(QuoteMatcher.scala:336)
[error] | at scala.quoted.runtime.impl.QuoteMatcher$.treeMatch(QuoteMatcher.scala:129)
[error] | at scala.quoted.runtime.impl.QuotesImpl.scala$quoted$runtime$impl$QuotesImpl$$treeMatch(QuotesImpl.scala:3051)
[error] | at scala.quoted.runtime.impl.QuotesImpl$TypeMatch$.unapply(QuotesImpl.scala:3021)
Is there a better (and working 😃 ) way to achieve the above goal?</div>
Issue Analytics
- State:
- Created a year ago
- Comments:12 (11 by maintainers)
Top Results From Across the Web
scala - Is it possible to match a quoted type of a sum type?
A.memberType(childSymbol).asType match { case '[f] => Expr.summon[BarOf[f]] }. Complete Functional Code : package bar import scala.quoted.
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
@nicolasstucki does this mean that
.memberType
shouldn’t be used when trying to get theTypeRepr
of a symbol obtained viaSymbol.children
? If it shouldn’t, what’s the correct way to do this?My use-case is trying to get the types of implementations of a
sealed trait
in order to summon typeclass instances for them.Thank you, @nicolasstucki, for the pointer to that page! With the help of that example I was able to replace the complicated @jsoniter snippet with a much cleaner and simpler implementation, that does exactly what I need:
No need for a call to
tpe.typeSymbol.children
anymore. 👍