diff --git a/docs/_spec/TODOreference/metaprogramming/staging.md b/docs/_spec/TODOreference/metaprogramming/staging.md index 6d9166e8249e..073012761513 100644 --- a/docs/_spec/TODOreference/metaprogramming/staging.md +++ b/docs/_spec/TODOreference/metaprogramming/staging.md @@ -108,7 +108,11 @@ to get a source-like representation of the expression. import scala.quoted.* // make available the necessary compiler for runtime code generation -given staging.Compiler = staging.Compiler.make(getClass.getClassLoader) +given staging.Compiler = + // We need an instance of a class that is defined in the current application (not the standard library) + // `this` can be used instead of an instance of `Dummy` if the Compiler is instantiated within one of the application classes. + object Dummy + staging.Compiler.make(Dummy.getClass.getClassLoader) val f: Array[Int] => Int = staging.run { val stagedSum: Expr[Array[Int] => Int] = diff --git a/staging/src/scala/quoted/staging/Compiler.scala b/staging/src/scala/quoted/staging/Compiler.scala index fbe6a3915a08..9ca994b6eb8f 100644 --- a/staging/src/scala/quoted/staging/Compiler.scala +++ b/staging/src/scala/quoted/staging/Compiler.scala @@ -13,15 +13,27 @@ object Compiler: /** Create a new instance of the compiler using the the classloader of the application. * - * Usage: - * ``` - * import scala.quoted.staging._ - * given Compiler = Compiler.make(getClass.getClassLoader) - * ``` + * Usage: + * ``` + * import scala.quoted.staging._ + * given Compiler = + * object Dummy + * Compiler.make(Dummy.getClass.getClassLoader) + * ``` * - * @param appClassloader classloader of the application that generated the quotes - * @param settings compiler settings - * @return A new instance of the compiler + * Note that we use an instance of `Dummy` to get the classloader that loaded the application. + * Any other instance of a class defined in the application would also work. + * Using a class defined in the standard library should be avoided as it might be loaded by a different classloader. + * + * If the given compiler is defined in one of your classes (e.i. not as a top-level definition), then + * the compiler can be instantiated with: + * ``` + * given Compiler = Compiler.make(this.getClass.getClassLoader) + * ``` + * + * @param appClassloader classloader of the application that generated the quotes + * @param settings compiler settings + * @return A new instance of the compiler */ def make(appClassloader: ClassLoader)(implicit settings: Settings): Compiler = new Compiler: diff --git a/tests/run-staging/i11162.scala b/tests/run-staging/i11162.scala index 81db85f24274..d15e976611af 100644 --- a/tests/run-staging/i11162.scala +++ b/tests/run-staging/i11162.scala @@ -2,7 +2,7 @@ import scala.quoted.* object Test { - given staging.Compiler = staging.Compiler.make(getClass.getClassLoader) + given staging.Compiler = staging.Compiler.make(this.getClass.getClassLoader) def main(args: Array[String]): Unit = staging.run { diff --git a/tests/run-staging/i19170.scala b/tests/run-staging/i19170.scala new file mode 100644 index 000000000000..5462929f9302 --- /dev/null +++ b/tests/run-staging/i19170.scala @@ -0,0 +1,14 @@ +import scala.quoted.* + +given staging.Compiler = + object Dummy + staging.Compiler.make(Dummy.getClass.getClassLoader) + +class A(i: Int) + +def f(i: Expr[Int])(using Quotes): Expr[A] = { '{ new A($i) } } + +@main def Test = { + val g: Int => A = staging.run { '{ (i: Int) => ${ f('{i}) } } } + println(g(3)) +} diff --git a/tests/run-staging/i19176.scala b/tests/run-staging/i19176.scala new file mode 100644 index 000000000000..a8367074d48e --- /dev/null +++ b/tests/run-staging/i19176.scala @@ -0,0 +1,10 @@ +import scala.quoted.* + +given staging.Compiler = + object Dummy + staging.Compiler.make(Dummy.getClass.getClassLoader) + +class A +val f: (A, Int) => Int = staging.run { '{ (q: A, x: Int) => x } } + +@main def Test = f(new A, 3)