Skip to content

Reflection's path dependent TypeRepr loses information about the prefix when converting to symbol  #19933

Open
@jchyb

Description

@jchyb

Compiler version

If you're not sure what version you're using, run print scalaVersion from sbt
(if you're running scalac manually, use scalac -version instead).

Minimized code

Macro.scala:

import scala.quoted._

inline def pdTypeMacro[T]: Unit = ${ pdTypeMacroImpl[T] }

def pdTypeMacroImpl[T](using quotes: Quotes, tpe: Type[T]): Expr[Unit] =
  import quotes.reflect.*
  val sym = TypeRepr.of[T].classSymbol.get
  println(sym.typeRef) // TypeRef(ThisType(TypeRef(ThisType(TypeRef(NoPrefix,module class <empty>)),class Outer)),class Inner)
  val mod = Ref(sym.companionModule)
  '{
    ${mod.asExpr}
    ???
  }

Main.scala:

class Outer:
  case class Inner(a: String = "test", b: Int = 23)

object Test:
  def main(args: Array[String]): Unit =
    val outer = Outer()
    pdTypeMacro[outer.Inner]

Output

WIth -Xcheck-macros

-- Error: main.scala:7:15 ------------------------------------------------------
7 |    pdTypeMacro[outer.Inner]
  |    ^^^^^^^^^^^^^^^^^^^^^^^^
  |Malformed tree was found while expanding macro with -Xcheck-macros.
  |The tree does not conform to the compiler's tree invariants.
  |
  |Macro was:
  |scala.quoted.runtime.Expr.splice[scala.Unit](((contextual$1: scala.quoted.Quotes) ?=> macro$package.pdTypeMacroImpl[outer.Inner](contextual$1, scala.quoted.Type.of[outer.Inner](contextual$1))))
  |
  |The macro returned:
  |{
  |  Outer.this.Inner
  |  scala.Predef.???
  |}
  |
  |Error:
  |assertion failed: error while typing Outer.this, method main is not contained in class Outer
  |
  |stacktrace available when compiling with `-Ydebug`
  |-----------------------------------------------------------------------------
  |Inline stack trace
  |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  |This location contains code that was inlined from macro.scala:3
3 |inline def pdTypeMacro[T]: Unit = ${ pdTypeMacroImpl[T] }
  |                                  ^^^^^^^^^^^^^^^^^^^^^^^
   -----------------------------------------------------------------------------

Without:

  exception while retyping Outer.this of class This # -1

  An unhandled exception was thrown in the compiler.
  Please file a crash report here:
  https://github.com/scala/scala3/issues/new/choose
  For non-enriched exceptions, compile with -Yno-enrich-error-messages.

     while compiling: main.scala
        during phase: MegaPhase{elimErasedValueType, pureStats, vcElideAllocations, etaReduce, arrayApply, elimPolyFunction, tailrec, completeJavaEnums, mixin, lazyVals, memoize, nonLocalReturns, capturedVars}
                mode: Mode(ImplicitsEnabled)
     library version: version 2.13.12
    compiler version: version 3.4.2-RC1-bin-SNAPSHOT-nonbootstrapped-git-3694d95
            settings: -classpath /Users/jchyb/Library/Caches/Coursier/v1/https/repo1.maven.org/maven2/org/scala-lang/scala-library/2.13.12/scala-library-2.13.12.jar:/Users/jchyb/Documents/workspace/dotty/library/../out/bootstrap/scala3-library-bootstrapped/scala-3.4.2-RC1-bin-SNAPSHOT-nonbootstrapped/scala3-library_3-3.4.2-RC1-bin-SNAPSHOT.jar
Exception in thread "main" 
  Exception while compiling macro.scala, main.scala

  An unhandled exception was thrown in the compiler.
  Please file a crash report here:
  https://github.com/scala/scala3/issues/new/choose
  For non-enriched exceptions, compile with -Yno-enrich-error-messages.

     while compiling: <no file>
        during phase: parser
                mode: Mode()
     library version: version 2.13.12
    compiler version: version 3.4.2-RC1-bin-SNAPSHOT-nonbootstrapped-git-3694d95
            settings: -classpath /Users/jchyb/Library/Caches/Coursier/v1/https/repo1.maven.org/maven2/org/scala-lang/scala-library/2.13.12/scala-library-2.13.12.jar:/Users/jchyb/Documents/workspace/dotty/library/../out/bootstrap/scala3-library-bootstrapped/scala-3.4.2-RC1-bin-SNAPSHOT-nonbootstrapped/scala3-library_3-3.4.2-RC1-bin-SNAPSHOT.jar
java.lang.AssertionError: assertion failed: missing outer accessor in object Test
        at scala.runtime.Scala3RunTime$.assertFailed(Scala3RunTime.scala:8)
        at dotty.tools.dotc.transform.ExplicitOuter$.dotty$tools$dotc$transform$ExplicitOuter$$$outerParamAccessor(ExplicitOuter.scala:237)
        at dotty.tools.dotc.transform.ExplicitOuter$OuterOps$.loop$1(ExplicitOuter.scala:474)
        at dotty.tools.dotc.transform.ExplicitOuter$OuterOps$.path$extension(ExplicitOuter.scala:483)
        at dotty.tools.dotc.transform.Erasure$Typer.typedThis(Erasure.scala:804)
        at dotty.tools.dotc.typer.Typer.typedUnnamed$1(Typer.scala:3124)
        at dotty.tools.dotc.typer.Typer.typedUnadapted(Typer.scala:3207)
        at dotty.tools.dotc.typer.ReTyper.typedUnadapted(ReTyper.scala:174)
        at dotty.tools.dotc.typer.Typer.typed(Typer.scala:3284)
        at dotty.tools.dotc.typer.Typer.typed(Typer.scala:3281)
        at dotty.tools.dotc.typer.Typer.typed(Typer.scala:3288)
        at dotty.tools.dotc.transform.Erasure$Typer.typedSelect(Erasure.scala:671)
        at dotty.tools.dotc.typer.Typer.typedNamed$1(Typer.scala:3098)
        at dotty.tools.dotc.typer.Typer.typedUnadapted(Typer.scala:3206)
        at dotty.tools.dotc.typer.ReTyper.typedUnadapted(ReTyper.scala:174)
        at dotty.tools.dotc.typer.Typer.typed(Typer.scala:3284)
        at dotty.tools.dotc.typer.Typer.typed(Typer.scala:3288)
        at dotty.tools.dotc.typer.ReTyper.typedInlined(ReTyper.scala:100)
        at dotty.tools.dotc.transform.Erasure$Typer.typedInlined(Erasure.scala:904)
        at dotty.tools.dotc.typer.Typer.typedUnnamed$1(Typer.scala:3146)
        at dotty.tools.dotc.typer.Typer.typedUnadapted(Typer.scala:3207)
        at dotty.tools.dotc.typer.ReTyper.typedUnadapted(ReTyper.scala:174)
        at dotty.tools.dotc.typer.Typer.typed(Typer.scala:3284)
        at dotty.tools.dotc.typer.Typer.typed(Typer.scala:3288)
        at dotty.tools.dotc.typer.Typer.traverse$1(Typer.scala:3337)
        at dotty.tools.dotc.typer.Typer.typedStats(Typer.scala:3356)
        at dotty.tools.dotc.transform.Erasure$Typer.typedStats(Erasure.scala:1073)
        at dotty.tools.dotc.typer.Typer.typedBlockStats(Typer.scala:1197)
        at dotty.tools.dotc.typer.Typer.typedBlock(Typer.scala:1201)
        at dotty.tools.dotc.typer.Typer.typedUnnamed$1(Typer.scala:3131)
        at dotty.tools.dotc.typer.Typer.typedUnadapted(Typer.scala:3207)
        at dotty.tools.dotc.typer.ReTyper.typedUnadapted(ReTyper.scala:174)
        at dotty.tools.dotc.typer.Typer.typed(Typer.scala:3284)
        at dotty.tools.dotc.typer.Typer.typed(Typer.scala:3288)
        at dotty.tools.dotc.typer.ReTyper.typedInlined(ReTyper.scala:100)
        at dotty.tools.dotc.transform.Erasure$Typer.typedInlined(Erasure.scala:904)
        at dotty.tools.dotc.typer.Typer.typedUnnamed$1(Typer.scala:3146)
        at dotty.tools.dotc.typer.Typer.typedUnadapted(Typer.scala:3207)
        at dotty.tools.dotc.typer.ReTyper.typedUnadapted(ReTyper.scala:174)
        at dotty.tools.dotc.typer.Typer.typed(Typer.scala:3284)
        at dotty.tools.dotc.typer.Typer.typed(Typer.scala:3288)
        at dotty.tools.dotc.transform.Erasure$Typer.typedTyped(Erasure.scala:627)
        at dotty.tools.dotc.typer.Typer.typedUnnamed$1(Typer.scala:3128)
        at dotty.tools.dotc.typer.Typer.typedUnadapted(Typer.scala:3207)
        at dotty.tools.dotc.typer.ReTyper.typedUnadapted(ReTyper.scala:174)
        at dotty.tools.dotc.typer.Typer.typed(Typer.scala:3284)
        at dotty.tools.dotc.typer.Typer.typed(Typer.scala:3281)
        at dotty.tools.dotc.typer.Typer.typed(Typer.scala:3288)
        at dotty.tools.dotc.typer.ReTyper.typedInlined(ReTyper.scala:100)
        at dotty.tools.dotc.transform.Erasure$Typer.typedInlined(Erasure.scala:904)
        at dotty.tools.dotc.typer.Typer.typedUnnamed$1(Typer.scala:3146)
        at dotty.tools.dotc.typer.Typer.typedUnadapted(Typer.scala:3207)
        at dotty.tools.dotc.typer.ReTyper.typedUnadapted(ReTyper.scala:174)
        at dotty.tools.dotc.typer.Typer.typed(Typer.scala:3284)
        at dotty.tools.dotc.typer.Typer.typed(Typer.scala:3288)
        at dotty.tools.dotc.typer.Typer.typedExpr(Typer.scala:3399)
        at dotty.tools.dotc.typer.Typer.typedBlock(Typer.scala:1204)
        at dotty.tools.dotc.typer.Typer.typedUnnamed$1(Typer.scala:3131)
        at dotty.tools.dotc.typer.Typer.typedUnadapted(Typer.scala:3207)
        at dotty.tools.dotc.typer.ReTyper.typedUnadapted(ReTyper.scala:174)
        at dotty.tools.dotc.typer.Typer.typed(Typer.scala:3284)
        at dotty.tools.dotc.typer.Typer.typed(Typer.scala:3288)
        at dotty.tools.dotc.typer.Typer.typedExpr(Typer.scala:3399)
        at dotty.tools.dotc.typer.Typer.$anonfun$63(Typer.scala:2613)
        at dotty.tools.dotc.inlines.PrepareInlineable$.dropInlineIfError(PrepareInlineable.scala:256)
        at dotty.tools.dotc.typer.Typer.typedDefDef(Typer.scala:2613)
        at dotty.tools.dotc.transform.Erasure$Typer.typedDefDef(Erasure.scala:960)
        at dotty.tools.dotc.typer.Typer.typedNamed$1(Typer.scala:3105)
        at dotty.tools.dotc.typer.Typer.typedUnadapted(Typer.scala:3206)
        at dotty.tools.dotc.typer.ReTyper.typedUnadapted(ReTyper.scala:174)
        at dotty.tools.dotc.typer.Typer.typed(Typer.scala:3284)
        at dotty.tools.dotc.typer.Typer.typed(Typer.scala:3288)
        at dotty.tools.dotc.typer.Typer.traverse$1(Typer.scala:3310)
        at dotty.tools.dotc.typer.Typer.typedStats(Typer.scala:3356)
        at dotty.tools.dotc.transform.Erasure$Typer.typedStats(Erasure.scala:1073)
        at dotty.tools.dotc.typer.Typer.typedClassDef(Typer.scala:2800)
        at dotty.tools.dotc.transform.Erasure$Typer.typedClassDef(Erasure.scala:1049)
        at dotty.tools.dotc.typer.Typer.typedTypeOrClassDef$1(Typer.scala:3111)
        at dotty.tools.dotc.typer.Typer.typedNamed$1(Typer.scala:3115)
        at dotty.tools.dotc.typer.Typer.typedUnadapted(Typer.scala:3206)
        at dotty.tools.dotc.typer.ReTyper.typedUnadapted(ReTyper.scala:174)
        at dotty.tools.dotc.typer.Typer.typed(Typer.scala:3284)
        at dotty.tools.dotc.typer.Typer.typed(Typer.scala:3288)
        at dotty.tools.dotc.typer.Typer.traverse$1(Typer.scala:3310)
        at dotty.tools.dotc.typer.Typer.typedStats(Typer.scala:3356)
        at dotty.tools.dotc.transform.Erasure$Typer.typedStats(Erasure.scala:1073)
        at dotty.tools.dotc.typer.Typer.typedPackageDef(Typer.scala:2933)
        at dotty.tools.dotc.typer.Typer.typedUnnamed$1(Typer.scala:3157)
        at dotty.tools.dotc.typer.Typer.typedUnadapted(Typer.scala:3207)
        at dotty.tools.dotc.typer.ReTyper.typedUnadapted(ReTyper.scala:174)
        at dotty.tools.dotc.typer.Typer.typed(Typer.scala:3284)
        at dotty.tools.dotc.typer.Typer.typed(Typer.scala:3288)
        at dotty.tools.dotc.typer.Typer.typedExpr(Typer.scala:3399)
        at dotty.tools.dotc.transform.Erasure.run(Erasure.scala:144)
        at dotty.tools.dotc.core.Phases$Phase.runOn$$anonfun$1(Phases.scala:354)
        at scala.runtime.function.JProcedure1.apply(JProcedure1.java:15)
        at scala.runtime.function.JProcedure1.apply(JProcedure1.java:10)
        at scala.collection.immutable.List.foreach(List.scala:333)
        at dotty.tools.dotc.core.Phases$Phase.runOn(Phases.scala:360)
        at dotty.tools.dotc.Run.runPhases$1$$anonfun$1(Run.scala:315)
        at scala.runtime.function.JProcedure1.apply(JProcedure1.java:15)
        at scala.runtime.function.JProcedure1.apply(JProcedure1.java:10)
        at scala.collection.ArrayOps$.foreach$extension(ArrayOps.scala:1323)
        at dotty.tools.dotc.Run.runPhases$1(Run.scala:337)
        at dotty.tools.dotc.Run.compileUnits$$anonfun$1(Run.scala:350)
        at dotty.tools.dotc.Run.compileUnits$$anonfun$adapted$1(Run.scala:360)
        at dotty.tools.dotc.util.Stats$.maybeMonitored(Stats.scala:69)
        at dotty.tools.dotc.Run.compileUnits(Run.scala:360)
        at dotty.tools.dotc.Run.compileUnits(Run.scala:267)
        at dotty.tools.dotc.Run.compileSuspendedUnits(Run.scala:371)
        at dotty.tools.dotc.Driver.finish(Driver.scala:57)
        at dotty.tools.dotc.Driver.doCompile(Driver.scala:38)
        at dotty.tools.dotc.Driver.process(Driver.scala:196)
        at dotty.tools.dotc.Driver.process(Driver.scala:164)
        at dotty.tools.dotc.Driver.process(Driver.scala:176)
        at dotty.tools.dotc.Driver.main(Driver.scala:206)
        at dotty.tools.dotc.Main.main(Main.scala)
## Expectation This is not a high priority, as this is caught by `-Xcheck-macros` after all, but I would expect Symbols to represent more correct information about the types. As it is now, any path dependent types like `outer.Inner` effectively become Outer.this.Inner, which is incorrect.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions