scala3 icon indicating copy to clipboard operation
scala3 copied to clipboard

summonAll after importing givens from a function parameter causes compiler crash

Open KuceraMartin opened this issue 1 year ago • 5 comments

Compiler version

3.4.0-RC2

Minimized code

import compiletime.summonAll
import deriving.Mirror

type Sc[X] = X
case class Row[T[_]](name: T[String])

class DialectTypeMappers:
  given String = ???

inline def metadata(dialect: DialectTypeMappers)(using m: Mirror.Of[Row[Sc]]): m.MirroredElemTypes =
  import dialect.given
  summonAll[m.MirroredElemTypes]

def f = metadata(???)

Output (click arrow to expand)

  unhandled exception while running MegaPhase{lambdaLift, elimStaticThis, countOuterAccesses} on /Users/martin/development/macro-test/main.scala

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

     while compiling: /Users/martin/development/macro-test/main.scala
        during phase: MegaPhase{lambdaLift, elimStaticThis, countOuterAccesses}
                mode: Mode(ImplicitsEnabled)
     library version: version 2.13.12
    compiler version: version 3.4.0-RC2
            settings: -classpath /Users/martin/Library/Caches/Coursier/v1/https/repo1.maven.org/maven2/org/scala-lang/scala3-library_3/3.4.0-RC2/scala3-library_3-3.4.0-RC2.jar:/Users/martin/Library/Caches/Coursier/v1/https/repo1.maven.org/maven2/org/scala-lang/scala-library/2.13.12/scala-library-2.13.12.jar -d /Users/martin/development/macro-test/.scala-build/macro-test_3200b05eac-d141fe35e1/classes/main -java-output-version 17 -sourceroot /Users/martin/development/macro-test

Exception in thread "main" java.lang.IllegalArgumentException: Could not find proxy for dialect: DialectTypeMappers in [parameter dialect, method metadata, the top-level definitions in package <empty>, package <empty>, package <root>], encl = method f, owners = method f, the top-level definitions in package <empty>, package <empty>, package <root>; enclosures = method f, the top-level definitions in package <empty>, package <empty>, package <root>
	at dotty.tools.dotc.transform.LambdaLift$Lifter.searchIn$1(LambdaLift.scala:137)
	at dotty.tools.dotc.transform.LambdaLift$Lifter.proxy(LambdaLift.scala:150)
	at dotty.tools.dotc.transform.LambdaLift$Lifter.proxyRef(LambdaLift.scala:168)
	at dotty.tools.dotc.transform.LambdaLift.transformIdent(LambdaLift.scala:287)
	at dotty.tools.dotc.transform.MegaPhase.goIdent(MegaPhase.scala:617)
	at dotty.tools.dotc.transform.MegaPhase.transformNamed$1(MegaPhase.scala:236)
	at dotty.tools.dotc.transform.MegaPhase.transformTree(MegaPhase.scala:448)
	at dotty.tools.dotc.transform.MegaPhase.transformNamed$1(MegaPhase.scala:240)
	at dotty.tools.dotc.transform.MegaPhase.transformTree(MegaPhase.scala:448)
	at dotty.tools.dotc.transform.MegaPhase.transformUnnamed$1(MegaPhase.scala:291)
	at dotty.tools.dotc.transform.MegaPhase.transformTree(MegaPhase.scala:450)
	at dotty.tools.dotc.transform.MegaPhase.loop$3(MegaPhase.scala:482)
	at dotty.tools.dotc.transform.MegaPhase.transformTrees(MegaPhase.scala:482)
	at dotty.tools.dotc.transform.MegaPhase.transformUnnamed$1(MegaPhase.scala:292)
	at dotty.tools.dotc.transform.MegaPhase.transformTree(MegaPhase.scala:450)
	at dotty.tools.dotc.transform.MegaPhase.transformUnnamed$1(MegaPhase.scala:333)
	at dotty.tools.dotc.transform.MegaPhase.transformTree(MegaPhase.scala:450)
	at dotty.tools.dotc.transform.MegaPhase.loop$2$$anonfun$1(MegaPhase.scala:470)
	at dotty.tools.dotc.transform.MegaPhase.loop$2(MegaPhase.scala:472)
	at dotty.tools.dotc.transform.MegaPhase.transformBlock(MegaPhase.scala:472)
	at dotty.tools.dotc.transform.MegaPhase.transformUnnamed$1(MegaPhase.scala:311)
	at dotty.tools.dotc.transform.MegaPhase.transformTree(MegaPhase.scala:450)
	at dotty.tools.dotc.transform.MegaPhase.transformUnnamed$1(MegaPhase.scala:333)
	at dotty.tools.dotc.transform.MegaPhase.transformTree(MegaPhase.scala:450)
	at dotty.tools.dotc.transform.MegaPhase.loop$2$$anonfun$1(MegaPhase.scala:470)
	at dotty.tools.dotc.transform.MegaPhase.loop$2(MegaPhase.scala:472)
	at dotty.tools.dotc.transform.MegaPhase.transformBlock(MegaPhase.scala:472)
	at dotty.tools.dotc.transform.MegaPhase.transformUnnamed$1(MegaPhase.scala:311)
	at dotty.tools.dotc.transform.MegaPhase.transformTree(MegaPhase.scala:450)
	at dotty.tools.dotc.transform.MegaPhase.mapDefDef$1(MegaPhase.scala:261)
	at dotty.tools.dotc.transform.MegaPhase.transformNamed$1(MegaPhase.scala:264)
	at dotty.tools.dotc.transform.MegaPhase.transformTree(MegaPhase.scala:448)
	at dotty.tools.dotc.transform.MegaPhase.loop$1(MegaPhase.scala:461)
	at dotty.tools.dotc.transform.MegaPhase.transformStats(MegaPhase.scala:461)
	at dotty.tools.dotc.transform.MegaPhase.transformUnnamed$1(MegaPhase.scala:372)
	at dotty.tools.dotc.transform.MegaPhase.transformTree(MegaPhase.scala:450)
	at dotty.tools.dotc.transform.MegaPhase.transformNamed$1(MegaPhase.scala:268)
	at dotty.tools.dotc.transform.MegaPhase.transformTree(MegaPhase.scala:448)
	at dotty.tools.dotc.transform.MegaPhase.loop$1(MegaPhase.scala:461)
	at dotty.tools.dotc.transform.MegaPhase.transformStats(MegaPhase.scala:461)
	at dotty.tools.dotc.transform.MegaPhase.mapPackage$1(MegaPhase.scala:392)
	at dotty.tools.dotc.transform.MegaPhase.transformUnnamed$1(MegaPhase.scala:395)
	at dotty.tools.dotc.transform.MegaPhase.transformTree(MegaPhase.scala:450)
	at dotty.tools.dotc.transform.MegaPhase.transformUnit(MegaPhase.scala:477)
	at dotty.tools.dotc.transform.MegaPhase.run(MegaPhase.scala:489)
	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:348)
	at dotty.tools.dotc.Run.compileUnits$$anonfun$adapted$1(Run.scala:357)
	at dotty.tools.dotc.util.Stats$.maybeMonitored(Stats.scala:71)
	at dotty.tools.dotc.Run.compileUnits(Run.scala:357)
	at dotty.tools.dotc.Run.compileSources(Run.scala:261)
	at dotty.tools.dotc.Run.compile(Run.scala:246)
	at dotty.tools.dotc.Driver.doCompile(Driver.scala:37)
	at dotty.tools.dotc.Driver.process(Driver.scala:197)
	at dotty.tools.dotc.Driver.process(Driver.scala:165)
	at dotty.tools.dotc.Driver.process(Driver.scala:177)
	at dotty.tools.dotc.Driver.main(Driver.scala:207)
	at dotty.tools.dotc.Main.main(Main.scala)
Compilation failed

note: could be related to https://github.com/lampepfl/dotty/issues/19436

KuceraMartin avatar Jan 19 '24 18:01 KuceraMartin

Miminized
import compiletime.{summonInline, summonAll}

class DialectTypeMappers:
  given aString: String = ???

inline def metadata(dialect: DialectTypeMappers): Unit =
  import dialect.given
  summonInline[String]
  // summonAll[Tuple1[String]]

def f =
  metadata((??? : DialectTypeMappers))

scalac -Xprint:inlining shows

def f: Unit =
      {
        val dialect$proxy1: DialectTypeMappers = ??? :DialectTypeMappers
        {
          import dialect$proxy1.given
          {
            dialect.aString
            ()
          }
        }:Unit
      }

where dialect.aString should have been dialect$proxy1.aString

nicolasstucki avatar Jan 22 '24 08:01 nicolasstucki

summon works correctly, therefore I assume that the context is properly updated with the correct import before expanding summonInline.

My best guess so far we are using the wrong context here https://github.com/lampepfl/dotty/blob/main/compiler/src/dotty/tools/dotc/inlines/Inlines.scala#L427-L437

nicolasstucki avatar Jan 22 '24 09:01 nicolasstucki

This issue was picked for the Issue Spree of Februrary 27th, 2024. @natsukagami, @KuceraMartin and @jan-pieter will be working on it. If you have any insight into the issue or guidance on how to fix it, please leave it here.

mbovel avatar Feb 25 '24 12:02 mbovel

Some more context:

Looking at InlinerMap, it seems that Import trees have their qualifiers renamed, but the underlying denotation is not changed. This is later used by Typer to infer the imported givens into the context (through importContext). That's how the dialect got through.

natsukagami avatar Feb 27 '24 19:02 natsukagami

@EugeneFlesselle, do you plan to work on this?

mbovel avatar Apr 08 '24 14:04 mbovel