Skip to content

ClassInfo can appear as result of memberType in macros #13319

Open
@scf37

Description

@scf37

Compiler version

3.0.1

Minimized code

import scala.quoted._
object Macro:
  inline def apply[A]: Unit = ${impl[A]}

  private def impl[A: Type](using Quotes): Expr[String] =
    import quotes.reflect._
    val t = TypeRepr.of[A]
    Expr.ofList(t.baseClasses.drop(1).filter(_.flags.is(Flags.Trait)).map { baseSymbol =>
        t.memberType(baseSymbol).asType  match { case '[t] => 42}
        Expr("")
    })
    Expr("")
Macro[Option[String]]

Output (click arrow to expand)

[info] compiling 2 Scala sources to /tmp/1/target/scala-3.0.1/classes ...
[info] assertion failure for trait Serializable in package java.io <:< t, frozen = false
[error] -- Error: /tmp/1/Main.scala:6:9 ------------------------------------------------
[error] 6 |    Macro[Option[String]]
[error]   |    ^^^^^^^^^^^^^^^^^^^^^
[error]   |Exception occurred while executing macro expansion.
[error]   |java.lang.AssertionError: assertion failed: ClassInfo(ThisType(TypeRef(NoPrefix,module class io)), trait Serializable, List(TypeRef(ThisType(TypeRef(NoPrefix,module class scala)),class Any)))
[error]   |	at scala.runtime.Scala3RunTime$.assertFailed(Scala3RunTime.scala:8)
[error]   |	at dotty.tools.dotc.core.Types$TypeBounds.<init>(Types.scala:4791)
[error]   |	at dotty.tools.dotc.core.Types$RealTypeBounds.<init>(Types.scala:4852)
[error]   |	at dotty.tools.dotc.core.Types$TypeBounds$.apply(Types.scala:4896)
[error]   |	at dotty.tools.dotc.core.Types$TypeBounds.derivedTypeBounds(Types.scala:4799)
[error]   |	at dotty.tools.dotc.core.ConstraintHandling.addOneBound(ConstraintHandling.scala:108)
[error]   |	at dotty.tools.dotc.core.ConstraintHandling.addOneBound$(ConstraintHandling.scala:26)
[error]   |	at dotty.tools.dotc.core.ProperGadtConstraint.addOneBound(GadtConstraint.scala:60)
[error]   |	at dotty.tools.dotc.core.ConstraintHandling.addBoundTransitively(ConstraintHandling.scala:162)
[error]   |	at dotty.tools.dotc.core.ConstraintHandling.addBoundTransitively$(ConstraintHandling.scala:26)
[error]   |	at dotty.tools.dotc.core.ProperGadtConstraint.addBoundTransitively(GadtConstraint.scala:60)
[error]   |	at dotty.tools.dotc.core.ProperGadtConstraint.addBound(GadtConstraint.scala:159)
[error]   |	at dotty.tools.dotc.core.TypeComparer.gadtAddLowerBound(TypeComparer.scala:118)
[error]   |	at dotty.tools.dotc.core.TypeComparer.narrowGADTBounds(TypeComparer.scala:1870)
[error]   |	at dotty.tools.dotc.core.TypeComparer.compareGADT$1(TypeComparer.scala:505)
[error]   |	at dotty.tools.dotc.core.TypeComparer.thirdTryNamed$1(TypeComparer.scala:508)
[error]   |	at dotty.tools.dotc.core.TypeComparer.thirdTry$1(TypeComparer.scala:557)
[error]   |	at dotty.tools.dotc.core.TypeComparer.secondTry$1(TypeComparer.scala:488)
[error]   |	at dotty.tools.dotc.core.TypeComparer.compareNamed$1(TypeComparer.scala:297)
[error]   |	at dotty.tools.dotc.core.TypeComparer.firstTry$1(TypeComparer.scala:303)
[error]   |	at dotty.tools.dotc.core.TypeComparer.recur(TypeComparer.scala:1282)
[error]   |	at dotty.tools.dotc.core.TypeComparer.isSubType(TypeComparer.scala:185)
[error]   |	at dotty.tools.dotc.core.TypeComparer.isSubType(TypeComparer.scala:195)
[error]   |	at dotty.tools.dotc.core.TypeComparer.topLevelSubType(TypeComparer.scala:128)
[error]   |	at dotty.tools.dotc.core.TypeComparer$.topLevelSubType(TypeComparer.scala:2673)
[error]   |	at dotty.tools.dotc.core.Types$Type.$less$colon$less(Types.scala:1032)
[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:2961)
[error]   |	at scala.quoted.runtime.impl.QuotesImpl$TypeMatch$.unapply(QuotesImpl.scala:2931)
[error]   |	at Macro$.impl$$anonfun$2(Macro.scala:9)
[error]   |	at scala.collection.immutable.List.map(List.scala:246)
[error]   |	at Macro$.impl(Macro.scala:10)
[error]   |	at Macro$.inline$impl(Macro.scala:5)
[error]   |
[error]   | This location contains code that was inlined from Main.scala:6
[error] one error found
[error] one error found

Activity

scf37

scf37 commented on Aug 17, 2021

@scf37
Author

It seems to fail on non-Scala interfaces as well:
assertion failed: ClassInfo(ThisType(TypeRef(NoPrefix,module class io)), trait Serializable, List(TypeRef(ThisType(TypeRef(NoPrefix,module class scala)),class Any)))

dwijnand

dwijnand commented on Aug 17, 2021

@dwijnand
Member

It seems to fail on non-Scala interfaces as well:
assertion failed: ClassInfo(ThisType(TypeRef(NoPrefix,module class io)), trait Serializable, List(TypeRef(ThisType(TypeRef(NoPrefix,module class scala)),class Any)))

That's the same as in the original report. Did you see another one too?

scf37

scf37 commented on Aug 18, 2021

@scf37
Author

@dwijnand I was confident I saw it for scala.Matchable as well

scf37

scf37 commented on Aug 18, 2021

@scf37
Author

t.memberType(baseSymbol).show throws MatchError.
Is this a bug or some kind of "wrong type"? Because I need to process superclass and traits of given type.

[error]   |Exception occurred while executing macro expansion.
[error]   |scala.MatchError: ClassInfo(ThisType(TypeRef(NoPrefix,module class io)), trait Serializable, List(TypeRef(ThisType(TypeRef(NoPrefix,module class scala)),class Any))) (of class dotty.tools.dotc.core.Types$CachedClassInfo)
[error]   |	at scala.quoted.runtime.impl.printers.Extractors$ExtractorsPrinter.visitType(Extractors.scala:233)
[error]   |	at scala.quoted.runtime.impl.printers.Extractors$.showType(Extractors.scala:12)
[error]   |	at scala.quoted.runtime.impl.QuotesImpl$$anon$17.show(QuotesImpl.scala:2898)
[error]   |	at scala.quoted.runtime.impl.QuotesImpl$$anon$17.show(QuotesImpl.scala:2897)
[error]   |	at scala.quoted.runtime.impl.QuotesImpl$reflect$TypeReprMethods$.show(QuotesImpl.scala:1660)
[error]   |	at scala.quoted.runtime.impl.QuotesImpl$reflect$TypeReprMethods$.show(QuotesImpl.scala:1660)
[error]   |	at scala.quoted.runtime.impl.printers.SourceCode$SourceCodePrinter.printType(SourceCode.scala:1228)
[error]   |	at scala.quoted.runtime.impl.printers.SourceCode$.showType(SourceCode.scala:13)
[error]   |	at scala.quoted.runtime.impl.QuotesImpl$$anon$14.show(QuotesImpl.scala:2886)
[error]   |	at scala.quoted.runtime.impl.QuotesImpl$$anon$14.show(QuotesImpl.scala:2885)
[error]   |	at scala.quoted.runtime.impl.QuotesImpl$reflect$TypeReprMethods$.show(QuotesImpl.scala:1660)
[error]   |	at scala.quoted.runtime.impl.QuotesImpl$reflect$TypeReprMethods$.show(QuotesImpl.scala:1660)
[error]   |	at Macro$.impl$$anonfun$2(Macro.scala:11)
[error]   |	at scala.collection.immutable.List.map(List.scala:246)
[error]   |	at Macro$.impl(Macro.scala:13)
[error]   |	at Macro$.inline$impl(Macro.scala:5)
changed the title [-]AssertionError on matching TypeRepr.baseClasses(1).asType[/-] [+]ClassInfo can appear as result of `memberType` in macros[/+] on Dec 21, 2021
bishabosha

bishabosha commented on Dec 21, 2021

@bishabosha
Member

I came across a similar issue with matching on the result of memberType when answering #14154:

package mcr

import scala.quoted.*

trait CaseClass[Companion <: AnyRef]:
  type CC <: Product

object CaseClass:
  transparent inline given mkCaseClass[Comp <: AnyRef]: CaseClass[Comp] = ${
    macroImpl[Comp]
  }
  def macroImpl[Comp <: AnyRef](using Quotes, Type[Comp]): Expr[CaseClass[Comp]] =
    import quotes.reflect.*

    val compObjTpe = TypeRepr.of[Comp]
    val clsSym = compObjTpe.typeSymbol.companionClass
    if !clsSym.paramSymss.forall(_.headOption.forall(_.isTerm)) then
      report.throwError("Case class with type parameters are not supported")

    val compPrefix = compObjTpe match
      case TermRef(pre, _) => pre
      case _ => report.throwError("Case class companion must be a term ref")
    val clsTpe = compPrefix.memberType(clsSym) // memberType returns ClassInfo here
    report.info(s"Case class type: ${clsTpe}")
    // clsTpe.asType match // uncomment causes match error when calling macro
      // case '[t] =>
        '{
          new CaseClass[Comp]:
            type CC = Nothing
        }
end CaseClass

1 remaining item

Loading
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Development

      Participants

      @dwijnand@scf37@nicolasstucki@bishabosha

      Issue actions

        ClassInfo can appear as result of `memberType` in macros · Issue #13319 · scala/scala3