-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Description
Compiler version
3.3.1
Minimized code
import scala.quoted.*
given staging.Compiler = staging.Compiler.make(getClass.getClassLoader)
class A(i: Int)
def f(i: Expr[Int])(using Quotes): Expr[A] = { '{ new A($i) } }
val g: Int => A = staging.run { '{ (i: Int) => ${ f('{i}) } } }
Output
scala> g
dotty.tools.dotc.reporting.UnhandledError: undefined: new A # -1: TermRef(TypeRef(ThisType(TypeRef(ThisType(TypeRef(NoPrefix,module class )),module class )),A),) at quotedFrontend
at dotty.tools.dotc.reporting.ThrowingReporter.doReport(ThrowingReporter.scala:14)
at dotty.tools.dotc.reporting.Reporter.issueUnconfigured(Reporter.scala:158)
at dotty.tools.dotc.reporting.Reporter.go$1(Reporter.scala:181)
at dotty.tools.dotc.reporting.Reporter.issueIfNotSuppressed(Reporter.scala:200)
at dotty.tools.dotc.reporting.Reporter.report(Reporter.scala:203)
at dotty.tools.dotc.report$.error(report.scala:68)
at dotty.tools.dotc.typer.ErrorReporting$.errorType(ErrorReporting.scala:31)
at dotty.tools.dotc.typer.TypeAssigner.assignType(TypeAssigner.scala:298)
at dotty.tools.dotc.typer.TypeAssigner.assignType$(TypeAssigner.scala:16)
at dotty.tools.dotc.typer.Typer.assignType(Typer.scala:116)
at dotty.tools.dotc.ast.tpd$.Apply(tpd.scala:49)
at dotty.tools.dotc.core.tasty.TreeUnpickler$TreeReader.readLengthTree$1(TreeUnpickler.scala:1304)
at dotty.tools.dotc.core.tasty.TreeUnpickler$TreeReader.readTree(TreeUnpickler.scala:1468)
at dotty.tools.dotc.core.tasty.TreeUnpickler$TreeReader.readLengthTree$1(TreeUnpickler.scala:1333)
at dotty.tools.dotc.core.tasty.TreeUnpickler$TreeReader.readTree(TreeUnpickler.scala:1468)
at dotty.tools.dotc.core.tasty.TreeUnpickler.unpickle(TreeUnpickler.scala:117)
at dotty.tools.dotc.core.tasty.DottyUnpickler.computeRootTrees(DottyUnpickler.scala:62)
at dotty.tools.dotc.ast.tpd$TreeProvider.rootTrees(tpd.scala:1299)
at dotty.tools.dotc.ast.tpd$TreeProvider.rootTrees$(tpd.scala:1288)
at dotty.tools.dotc.core.tasty.DottyUnpickler.rootTrees(DottyUnpickler.scala:44)
at dotty.tools.dotc.ast.tpd$TreeProvider.tree(tpd.scala:1303)
at dotty.tools.dotc.ast.tpd$TreeProvider.tree$(tpd.scala:1288)
at dotty.tools.dotc.core.tasty.DottyUnpickler.tree(DottyUnpickler.scala:44)
at dotty.tools.dotc.quoted.PickledQuotes$.unpickle(PickledQuotes.scala:274)
at dotty.tools.dotc.quoted.PickledQuotes$.unpickleTerm(PickledQuotes.scala:84)
at scala.quoted.runtime.impl.QuotesImpl.unpickleExprV2(QuotesImpl.scala:3143)
at Meta$package$.f(Meta.scala:7)
at Meta$package$.$init$$$anonfun$1$$anonfun$1$$anonfun$1(Meta.scala:9)
at Meta$package$.$init$$$anonfun$1$$anonfun$1(Meta.scala:9)
at Meta$package$.$init$$$anonfun$1$$anonfun$adapted$1(Meta.scala:9)
at dotty.tools.dotc.quoted.PickledQuotes$$anon$1.transform(PickledQuotes.scala:110)
at dotty.tools.dotc.ast.Trees$Instance$TreeMap.transform(Trees.scala:1538)
at dotty.tools.dotc.quoted.PickledQuotes$$anon$1.transform(PickledQuotes.scala:135)
at dotty.tools.dotc.ast.Trees$Instance$TreeMap.transformBlock(Trees.scala:1603)
at dotty.tools.dotc.ast.Trees$Instance$TreeMap.transform(Trees.scala:1518)
at dotty.tools.dotc.quoted.PickledQuotes$$anon$1.transform(PickledQuotes.scala:135)
at dotty.tools.dotc.ast.Trees$Instance$TreeMap.transform(Trees.scala:1570)
at dotty.tools.dotc.quoted.PickledQuotes$$anon$1.transform(PickledQuotes.scala:135)
at dotty.tools.dotc.ast.Trees$Instance$TreeMap.transform$$anonfun$1(Trees.scala:1605)
at scala.collection.immutable.List.mapConserve(List.scala:472)
at dotty.tools.dotc.ast.Trees$Instance$TreeMap.transform(Trees.scala:1605)
at dotty.tools.dotc.ast.Trees$Instance$TreeMap.transformStats(Trees.scala:1601)
at dotty.tools.dotc.ast.Trees$Instance$TreeMap.transformBlock(Trees.scala:1603)
at dotty.tools.dotc.ast.Trees$Instance$TreeMap.transform(Trees.scala:1518)
at dotty.tools.dotc.quoted.PickledQuotes$$anon$1.transform(PickledQuotes.scala:135)
at dotty.tools.dotc.quoted.PickledQuotes$.spliceTerms(PickledQuotes.scala:152)
at dotty.tools.dotc.quoted.PickledQuotes$.unpickleTerm(PickledQuotes.scala:88)
at scala.quoted.runtime.impl.QuotesImpl.unpickleExprV2(QuotesImpl.scala:3143)
at Meta$package$.$init$$$anonfun$1(Meta.scala:9)
at scala.quoted.staging.QuoteCompiler$QuotedFrontend.runOn$$anonfun$1(QuoteCompiler.scala:83)
at scala.collection.immutable.List.flatMap(List.scala:293)
at scala.quoted.staging.QuoteCompiler$QuotedFrontend.runOn(QuoteCompiler.scala:98)
at dotty.tools.dotc.Run.runPhases$1$$anonfun$1(Run.scala:246)
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:1321)
at dotty.tools.dotc.Run.runPhases$1(Run.scala:262)
at dotty.tools.dotc.Run.compileUnits$$anonfun$1(Run.scala:270)
at dotty.tools.dotc.Run.compileUnits$$anonfun$adapted$1(Run.scala:279)
at dotty.tools.dotc.util.Stats$.maybeMonitored(Stats.scala:67)
at dotty.tools.dotc.Run.compileUnits(Run.scala:279)
at dotty.tools.dotc.Run.compileUnits(Run.scala:200)
at scala.quoted.staging.QuoteCompiler$ExprRun.compileExpr(QuoteCompiler.scala:118)
at scala.quoted.staging.QuoteDriver.run(QuoteDriver.scala:43)
at scala.quoted.staging.Compiler$$anon$1.run(Compiler.scala:38)
at scala.quoted.staging.package$.run(staging.scala:19)
at Meta$package$.(Meta.scala:9)
... 66 elided
Expectation
...for this not to happen.
Activity
hamzaremmal commentedon Dec 1, 2023
Compiling the file below (
i19170.scala
) will emit a valid warningFull stack trace when running
scala i19170.scala
:hamzaremmal commentedon Dec 1, 2023
Running it on the main branch (d96e9e4) gives a different output :
nicolasstucki commentedon Dec 2, 2023
@hamzaremmal you are missing the dependency on the staging jar. You should use
tests/pos-staging
to write tests with that dependency .You can also use the
-with-compiler
flag.christophkoch commentedon Dec 2, 2023
Sorry, my code wasn't minimal. This smaller snippet still causes the crash:
import scala.quoted.*
given staging.Compiler = staging.Compiler.make(getClass.getClassLoader)
class A
val g: A = staging.run { '{ new A } }
Also, I would be curious to learn from the experts how to get rid of the warning about the "given staging.Compiler = ..." line, which Hamza also reported. This line is boilerplate I copied in from the latest online documentation, which may be outdated.
hamzaremmal commentedon Dec 2, 2023
The warning comes from the fact that you're calling a method from the top level, in this case
getClass
, and that this function call might end up calling the wrong method. That's why the message of the warning contains the following "Suspicious top-level unqualified call to getClass". The best way to get rid of this warning is to qualify the call togetClass
, eg.Predef.getClass
@nicolasstucki Do you think this can be solved during a Spree ?
christophkoch commentedon Dec 2, 2023
Thanks a lot, Hamza! It would be good to fix this in the documentation, e.g. at
https://docs.scala-lang.org/scala3/reference/metaprogramming/staging.html
nicolasstucki commentedon Jan 11, 2024
This points to the actual issue with this code, but it does not make the solution evident. In the past, when we called
getClass
in a top-level method we used to callthis.getClass
wherethis
was on the synthetic package object. Now we get aPredef.getClass
.What we need to pass to
staging.Compiler.make
is the classloader that loaded the application. Some tools (scala
,SBT
, or others) load the standard library before the application is loaded in a parent classloader. If we use this classloader, the runtime staging compiler will not know how to load the classes of the application.This seems to be the simplest workaround for top-level definitions
We should update the documentation using this version, unless we find a simpler safe incantation for this classloader.
christophkoch commentedon Jan 12, 2024
Thanks a lot Nicolas. If I do this in the Repl, I get
dotty.tools.dotc.MissingCoreLibraryException: Could not find package scala from compiler core libraries.
Make sure the compiler core libraries are on the classpath.
Is there an easy way to fix this?
Update `staging.Compiler.make` documentation
staging.Compiler.make
documentation #19428nicolasstucki commentedon Jan 12, 2024
How are you executing the repl? In an SBT project or from the
scala
command?A patch for this could be to add explicitly a dependency on the compiler.
Unfortunately, there seem to be other issues related to the classloader in the REPL.
nicolasstucki commentedon Jan 12, 2024
I suspect that the issue in the REPL is located in https://github.com/lampepfl/dotty/blob/main/compiler/src/dotty/tools/dotc/util/ClasspathFromClassloader.scala
Update `staging.Compiler.make` documentation (#19428)
Update `staging.Compiler.make` documentation