Skip to content

Fix #6007: Get the classloader that loaded the application #6017

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Apr 3, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ object ConsumeTasty {
new TastyFromClass(tastyConsumer)
}

val currentClasspath = QuoteDriver.currentClasspath
val currentClasspath = QuoteDriver.currentClasspath(getClass.getClassLoader)
import java.io.File.{ pathSeparator => sep }
val args = "-from-tasty" :: "-Yretain-trees" :: "-classpath" :: s"$classpath$sep$currentClasspath" :: classes
(new Consume).process(args.toArray)
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/quoted/QuoteCompiler.scala
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ class QuoteCompiler extends Compiler {
new ExprRun(this, ctx.addMode(Mode.ReadPositions))
}

def outputClassName: TypeName = "Quoted".toTypeName
def outputClassName: TypeName = "Generated$Code$From$Quoted".toTypeName

/** Frontend that receives a scala.quoted.Expr or scala.quoted.Type as input */
class QuotedFrontend(putInClass: Boolean) extends Phase {
Expand Down
16 changes: 11 additions & 5 deletions compiler/src/dotty/tools/dotc/quoted/QuoteDriver.scala
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,11 @@ import scala.quoted.{Expr, Type}
import scala.quoted.Toolbox
import java.net.URLClassLoader

class QuoteDriver extends Driver {
/** Driver to compile quoted code
*
* @param appClassloader classloader of the application that generated the quotes
*/
class QuoteDriver(appClassloader: ClassLoader) extends Driver {
import tpd._

private[this] val contextBase: ContextBase = new ContextBase
Expand All @@ -32,7 +36,9 @@ class QuoteDriver extends Driver {
val driver = new QuoteCompiler
driver.newRun(ctx).compileExpr(expr)

val classLoader = new AbstractFileClassLoader(outDir, this.getClass.getClassLoader)
assert(!ctx.reporter.hasErrors)

val classLoader = new AbstractFileClassLoader(outDir, appClassloader)

val clazz = classLoader.loadClass(driver.outputClassName.toString)
val method = clazz.getMethod("apply")
Expand Down Expand Up @@ -82,7 +88,7 @@ class QuoteDriver extends Driver {

override def initCtx: Context = {
val ictx = contextBase.initialCtx
ictx.settings.classpath.update(QuoteDriver.currentClasspath)(ictx)
ictx.settings.classpath.update(QuoteDriver.currentClasspath(appClassloader))(ictx)
ictx
}

Expand All @@ -94,9 +100,9 @@ class QuoteDriver extends Driver {

object QuoteDriver {

def currentClasspath: String = {
def currentClasspath(cl: ClassLoader): String = {
val classpath0 = System.getProperty("java.class.path")
this.getClass.getClassLoader match {
cl match {
case cl: URLClassLoader =>
// Loads the classes loaded by this class loader
// When executing `run` or `test` in sbt the classpath is not in the property java.class.path
Expand Down
11 changes: 9 additions & 2 deletions compiler/src/dotty/tools/dotc/quoted/ToolboxImpl.scala
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,15 @@ import scala.quoted.Exprs.{LiftedExpr, TastyTreeExpr}
object ToolboxImpl {
import tpd._

def make(settings: scala.quoted.Toolbox.Settings): scala.quoted.Toolbox = new scala.quoted.Toolbox {
/** Create a new instance of the toolbox using the the classloader of the application.
*
* @param appClassloader classloader of the application that generated the quotes
* @param settings toolbox settings
* @return A new instance of the toolbox
*/
def make(settings: scala.quoted.Toolbox.Settings, appClassloader: ClassLoader): scala.quoted.Toolbox = new scala.quoted.Toolbox {

private[this] val driver: QuoteDriver = new QuoteDriver()
private[this] val driver: QuoteDriver = new QuoteDriver(appClassloader)

def run[T](expr: Expr[T]): T = expr match {
case expr: LiftedExpr[T] =>
Expand All @@ -26,4 +32,5 @@ object ToolboxImpl {

def show[T](tpe: Type[T]): String = synchronized(driver.show(tpe, settings))
}

}
8 changes: 8 additions & 0 deletions compiler/test-resources/repl/i6007
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
scala> implicit def toolbox: scala.quoted.Toolbox = scala.quoted.Toolbox.make(getClass.getClassLoader)
def toolbox: quoted.Toolbox
scala> val v = '{ (if true then Some(1) else None).map(v => v+1) }
val v: quoted.Expr[Option[Int]] = Expr(<pickled tasty>)
scala> v.show
val res0: String = (if (true) scala.Some.apply[scala.Int](1) else scala.None).map[scala.Int](((v: scala.Int) => v.+(1)))
scala> v.run
val res1: Option[Int] = Some(2)
27 changes: 16 additions & 11 deletions library/src/scala/quoted/Toolbox.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package scala.quoted

import scala.annotation.implicitNotFound

@implicitNotFound("Could not find implicit quoted.Toolbox.\n\nDefault toolbox can be instantiated with:\n `implicit val toolbox: scala.quoted.Toolbox = scala.quoted.Toolbox.make`\n\nIf only needed once it can also be imported with:\n `import scala.quoted.Toolbox.Default._`")
@implicitNotFound("Could not find implicit quoted.Toolbox.\n\nDefault toolbox can be instantiated with:\n `implicit val toolbox: scala.quoted.Toolbox = scala.quoted.Toolbox.make(getClass.getClassLoader)`\n\n")
trait Toolbox {
def run[T](expr: Expr[T]): T
def show[T](expr: Expr[T]): String
Expand All @@ -11,17 +11,22 @@ trait Toolbox {

object Toolbox {

object Default {
// TODO remove? It may be better to only have one way to instantiate the toolbox
implicit def make(implicit settings: Settings): Toolbox = Toolbox.make
}

def make(implicit settings: Settings): Toolbox = {
val cl = getClass.getClassLoader
/** Create a new instance of the toolbox using the the classloader of the application.
*
* Usuage:
* ```
* implicit val toolbox: scala.quoted.Toolbox = scala.quoted.Toolbox.make(getClass.getClassLoader)
* ```
*
* @param appClassloader classloader of the application that generated the quotes
* @param settings toolbox settings
* @return A new instance of the toolbox
*/
def make(appClassloader: ClassLoader)(implicit settings: Settings): Toolbox = {
try {
val toolboxImplCls = cl.loadClass("dotty.tools.dotc.quoted.ToolboxImpl")
val makeMeth = toolboxImplCls.getMethod("make", classOf[Settings])
makeMeth.invoke(null, settings).asInstanceOf[Toolbox]
val toolboxImplCls = appClassloader.loadClass("dotty.tools.dotc.quoted.ToolboxImpl")
val makeMeth = toolboxImplCls.getMethod("make", classOf[Settings], classOf[ClassLoader])
makeMeth.invoke(null, settings, appClassloader).asInstanceOf[Toolbox]
}
catch {
case ex: ClassNotFoundException =>
Expand Down
7 changes: 7 additions & 0 deletions sbt-dotty/sbt-test/sbt-dotty/quoted-example-project/build.sbt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
scalaVersion := sys.props("plugin.scalaVersion")

libraryDependencies ++= Seq(
"ch.epfl.lamp" % "dotty_0.14" % scalaVersion.value,
"ch.epfl.lamp" % "dotty_0.14" % scalaVersion.value % "test->runtime",
"com.novocode" % "junit-interface" % "0.11" % "test"
)
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
addSbtPlugin("ch.epfl.lamp" % "sbt-dotty" % sys.props("plugin.version"))
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package hello

// Import Expr and some extension methods
import scala.quoted._

object Main {

implicit val toolbox: scala.quoted.Toolbox = scala.quoted.Toolbox.make(getClass.getClassLoader)

def main(args: Array[String]): Unit = {

val square = stagedPower(2)

assert(Math.pow(3, 2) == square(3))

square(3)
square(4)

assert(Math.pow(4, 2) == square(4))

val cube = stagedPower(3)
cube(2)


assert(Math.pow(2, 3) == cube(2))



val toTheFourth = stagedPower(4)
assert(Math.pow(3, 4) == toTheFourth(3))
}

def stagedPower(n: Int): Double => Double = {
// Code representing the labmda where the recursion is unrolled based on the value of n
val code = '{ (x: Double) => ${powerCode(n, '{x})}}

code.show

// Evaluate the contents of the code and return it's value
code.run
}

def powerCode(n: Int, x: Expr[Double]): Expr[Double] =
if (n == 0) '{1.0}
else if (n == 1) x
else if (n < 0) throw new Exception("Negative powers not implemented. Left as a small exercise. Dont be shy, try it out.")
else if (n == 2) '{$x * $x}
else if (n % 2 == 1) '{$x * ${powerCode(n - 1, x)}}
else '{ val y = $x * $x; ${powerCode(n / 2, '{y})}}

}
1 change: 1 addition & 0 deletions sbt-dotty/sbt-test/sbt-dotty/quoted-example-project/test
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
> run
3 changes: 1 addition & 2 deletions tests/neg-with-compiler/i5941/macro_1.scala
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,9 @@ object Lens {
}

def impl[S: Type, T: Type](getter: Expr[S => T])(implicit refl: Reflection): Expr[Lens[S, T]] = {
implicit val toolbox: scala.quoted.Toolbox = scala.quoted.Toolbox.make(this.getClass.getClassLoader)
import refl._
import util._
import quoted.Toolbox.Default._

// obj.copy(field = value)
def setterBody(obj: Expr[S], value: Expr[T], field: String): Expr[S] =
Select.overloaded(obj.unseal, "copy", Nil, NamedArg(field, value.unseal) :: Nil).seal.cast[S]
Expand Down
4 changes: 2 additions & 2 deletions tests/neg-with-compiler/quote-run-in-macro-1/quoted_1.scala
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import scala.quoted._
import scala.quoted.autolift._

import scala.quoted.Toolbox.Default._

object Macros {

implicit val toolbox: scala.quoted.Toolbox = scala.quoted.Toolbox.make(getClass.getClassLoader)
inline def foo(i: => Int): Int = ${ fooImpl('i) }
def fooImpl(i: Expr[Int]): Expr[Int] = {
val y: Int = i.run
Expand Down
3 changes: 2 additions & 1 deletion tests/neg-with-compiler/quote-run-in-macro-2/quoted_1.scala
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import scala.quoted._
import scala.quoted.autolift._
import scala.quoted.Toolbox.Default._

object Macros {

inline def foo(i: => Int): Int = ${ fooImpl('i) }
def fooImpl(i: Expr[Int]): Expr[Int] = {
implicit val toolbox: scala.quoted.Toolbox = scala.quoted.Toolbox.make(getClass.getClassLoader)
val y: Int = i.run
y
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import scala.quoted._
import scala.tasty.Reflection
import scala.language.implicitConversions
import scala.quoted.Exprs.LiftedExpr
import scala.quoted.Toolbox.Default._

object Macro {

Expand Down
3 changes: 1 addition & 2 deletions tests/neg/tasty-string-interpolator-position-b/Macro_1.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import scala.quoted._
import scala.tasty.Reflection
import scala.language.implicitConversions
import scala.quoted.Exprs.LiftedExpr
import scala.quoted.Toolbox.Default._

object Macro {

Expand All @@ -11,7 +10,7 @@ object Macro {
}

object FIntepolator {

implicit val toolbox: scala.quoted.Toolbox = scala.quoted.Toolbox.make(getClass.getClassLoader)
def apply(strCtxExpr: Expr[StringContext], argsExpr: Expr[Seq[Any]])(implicit reflect: Reflection): Expr[String] = {
import reflect._
error("there are no args", argsExpr.unseal.underlyingArgument.pos)
Expand Down
3 changes: 1 addition & 2 deletions tests/pos-with-compiler/quote-0.scala
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import scala.quoted._
import scala.quoted.autolift._

import scala.quoted.Toolbox.Default._

object Macros {


Expand Down Expand Up @@ -41,5 +39,6 @@ class Test {
${ powerCode(3, '{math.sqrt(2.0)}) }
}

implicit val toolbox: scala.quoted.Toolbox = scala.quoted.Toolbox.make(getClass.getClassLoader)
program.run
}
3 changes: 2 additions & 1 deletion tests/pos-with-compiler/quote-assert/quoted_2.scala
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import scala.quoted.Toolbox.Default._

import scala.quoted._
import Macros._

Expand All @@ -15,5 +15,6 @@ object Test {
${ assertImpl('{x != 0}) }
}

implicit val toolbox: scala.quoted.Toolbox = scala.quoted.Toolbox.make(getClass.getClassLoader)
program.run
}
3 changes: 1 addition & 2 deletions tests/run-with-compiler-custom-args/staged-streams_1.scala
Original file line number Diff line number Diff line change
Expand Up @@ -677,8 +677,7 @@ object Test {
.fold('{0}, ((a: Expr[Int], b : Expr[Int]) => '{ $a + $b }))

def main(args: Array[String]): Unit = {
implicit val toolbox: scala.quoted.Toolbox = scala.quoted.Toolbox.make

implicit val toolbox: scala.quoted.Toolbox = scala.quoted.Toolbox.make(getClass.getClassLoader)
println(test1().run)
println
println(test2().run)
Expand Down
2 changes: 1 addition & 1 deletion tests/run-with-compiler/i3823-b.scala
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import scala.quoted.Toolbox.Default._
import scala.quoted._
object Test {
def main(args: Array[String]): Unit = {
def f[T](x: Expr[T])(implicit t: Type[T]) = '{
val z: $t = $x
}
implicit val toolbox: scala.quoted.Toolbox = scala.quoted.Toolbox.make(getClass.getClassLoader)
println(f('{2})(Type.IntTag).show)
}
}
2 changes: 1 addition & 1 deletion tests/run-with-compiler/i3823-c.scala
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import scala.quoted.Toolbox.Default._
import scala.quoted._
object Test {
def main(args: Array[String]): Unit = {
def f[T](x: Expr[T])(implicit t: Type[T]) = '{
val z = $x
}
implicit val toolbox: scala.quoted.Toolbox = scala.quoted.Toolbox.make(getClass.getClassLoader)
println(f('{2})(Type.IntTag).show)
}
}
Expand Down
2 changes: 1 addition & 1 deletion tests/run-with-compiler/i3823.scala
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import scala.quoted.Toolbox.Default._
import scala.quoted._
object Test {
def main(args: Array[String]): Unit = {
def f[T: Type](x: Expr[T])(t: Type[T]) = '{
val z: $t = $x
}
implicit val toolbox: scala.quoted.Toolbox = scala.quoted.Toolbox.make(getClass.getClassLoader)
println(f('{2})('[Int]).show)
}
}
2 changes: 1 addition & 1 deletion tests/run-with-compiler/i3847-b.scala
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import scala.quoted.Toolbox.Default._
import scala.quoted._
import scala.reflect.ClassTag

Expand All @@ -15,6 +14,7 @@ object Arrays {

object Test {
def main(args: Array[String]): Unit = {
implicit val toolbox: scala.quoted.Toolbox = scala.quoted.Toolbox.make(getClass.getClassLoader)
import Arrays._
implicit val ct: Expr[ClassTag[Int]] = '{ClassTag.Int}
val arr: Expr[Array[List[Int]]] = Array[List[Int]](List(1, 2, 3)).toExpr
Expand Down
2 changes: 1 addition & 1 deletion tests/run-with-compiler/i3847.scala
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import scala.quoted.Toolbox.Default._
import scala.quoted._
import scala.reflect.ClassTag

Expand All @@ -15,6 +14,7 @@ object Arrays {

object Test {
def main(args: Array[String]): Unit = {
implicit val toolbox: scala.quoted.Toolbox = scala.quoted.Toolbox.make(this.getClass.getClassLoader)
import Arrays._
implicit val ct: Expr[ClassTag[Int]] = '{ClassTag.Int}
val arr: Expr[Array[Int]] = Array[Int](1, 2, 3).toExpr
Expand Down
3 changes: 1 addition & 2 deletions tests/run-with-compiler/i3876-b.scala
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import scala.quoted.Toolbox.Default._
import scala.quoted._
object Test {
def main(args: Array[String]): Unit = {
implicit val toolbox: scala.quoted.Toolbox = scala.quoted.Toolbox.make
implicit val toolbox: scala.quoted.Toolbox = scala.quoted.Toolbox.make(getClass.getClassLoader)

val x: Expr[Int] = '{3}

Expand Down
3 changes: 1 addition & 2 deletions tests/run-with-compiler/i3876-c.scala
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import scala.quoted.Toolbox.Default._
import scala.quoted._
object Test {
def main(args: Array[String]): Unit = {
implicit val toolbox: scala.quoted.Toolbox = scala.quoted.Toolbox.make
implicit val toolbox: scala.quoted.Toolbox = scala.quoted.Toolbox.make(getClass.getClassLoader)

val x: Expr[Int] = '{3}

Expand Down
Loading