Skip to content

Commit 2ca3f8b

Browse files
committed
Merge pull request scala#4692 from JanBessai/Fix-SI-6636
SI-6636 Fix macro expansion in toolboxes
2 parents e077787 + 43d3eec commit 2ca3f8b

File tree

4 files changed

+47
-0
lines changed

4 files changed

+47
-0
lines changed

src/compiler/scala/tools/nsc/typechecker/Macros.scala

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,13 @@ trait Macros extends MacroRuntimes with Traces with Helpers {
5555

5656
def globalSettings = global.settings
5757

58+
/** Obtains a `ClassLoader` instance used for macro expansion.
59+
*
60+
* By default a new `ScalaClassLoader` is created using the classpath
61+
* from global and the classloader of self as parent.
62+
*
63+
* Mirrors with runtime definitions (e.g. Repl) need to adjust this method.
64+
*/
5865
protected def findMacroClassLoader(): ClassLoader = {
5966
val classpath = global.classPath.asURLs
6067
macroLogVerbose("macro classloader: initializing from -cp: %s".format(classpath))

src/compiler/scala/tools/reflect/ReflectGlobal.scala

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,32 @@
11
package scala.tools
22
package reflect
33

4+
import scala.reflect.internal.util.ScalaClassLoader
45
import scala.tools.nsc.Global
56
import scala.tools.nsc.reporters.Reporter
67
import scala.tools.nsc.Settings
8+
import scala.tools.nsc.typechecker.Analyzer
79

810
/** A version of Global that uses reflection to get class
911
* infos, instead of reading class or source files.
1012
*/
1113
class ReflectGlobal(currentSettings: Settings, reporter: Reporter, override val rootClassLoader: ClassLoader)
1214
extends Global(currentSettings, reporter) with scala.tools.reflect.ReflectSetup with scala.reflect.runtime.SymbolTable {
1315

16+
override lazy val analyzer = new {
17+
val global: ReflectGlobal.this.type = ReflectGlobal.this
18+
} with Analyzer {
19+
/** Obtains the classLoader used for runtime macro expansion.
20+
*
21+
* Macro expansion can use everything available in [[global.classPath]] or [[rootClassLoader]].
22+
* The [[rootClassLoader]] is used to obtain runtime defined macros.
23+
*/
24+
override protected def findMacroClassLoader(): ClassLoader = {
25+
val classpath = global.classPath.asURLs
26+
ScalaClassLoader.fromURLs(classpath, rootClassLoader)
27+
}
28+
}
29+
1430
override def transformedType(sym: Symbol) =
1531
postErasure.transformInfo(sym,
1632
erasure.transformInfo(sym,
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
42
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import scala.reflect.runtime.universe._
2+
import scala.reflect.runtime.{universe => ru}
3+
import scala.reflect.runtime.{currentMirror => cm}
4+
import scala.tools.reflect.{ToolBox}
5+
6+
object Test extends App {
7+
val toolBox = cm.mkToolBox()
8+
val x = 21
9+
val runtimeMacro =
10+
q"""object RuntimeMacro {
11+
import scala.reflect.macros.whitebox.Context
12+
import scala.language.experimental.macros
13+
14+
def add(y: Int): Int = macro addImpl
15+
def addImpl(c: Context)(y: c.Expr[Int]): c.Expr[Int] = {
16+
import c.universe._
17+
val x = $x
18+
c.Expr[Int](q"$$x + $$y")
19+
}
20+
}"""
21+
val s = toolBox.define(runtimeMacro)
22+
println(toolBox.eval(q"$s.add(21)"))
23+
}

0 commit comments

Comments
 (0)