Skip to content

Commit c03c83f

Browse files
committed
Merge remote-tracking branch 'staging/fix-#6007' into fix-#5409
2 parents 9f67132 + 906cb3b commit c03c83f

File tree

111 files changed

+247
-214
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

111 files changed

+247
-214
lines changed

compiler/src/dotty/tools/dotc/consumetasty/ConsumeTasty.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ object ConsumeTasty {
1616
new TastyFromClass(tastyConsumer)
1717
}
1818

19-
val currentClasspath = QuoteDriver.currentClasspath
19+
val currentClasspath = QuoteDriver.currentClasspath(getClass.getClassLoader)
2020
import java.io.File.{ pathSeparator => sep }
2121
val args = "-from-tasty" :: "-Yretain-trees" :: "-classpath" :: s"$classpath$sep$currentClasspath" :: classes
2222
(new Consume).process(args.toArray)

compiler/src/dotty/tools/dotc/parsing/Parsers.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -341,6 +341,7 @@ object Parsers {
341341
case NEWLINE | NEWLINES => in.nextToken()
342342
case SEMI => in.nextToken()
343343
case _ =>
344+
syntaxError("end of statement expected")
344345
in.nextToken() // needed to ensure progress; otherwise we might cycle forever
345346
accept(SEMI)
346347
}

compiler/src/dotty/tools/dotc/quoted/QuoteCompiler.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ class QuoteCompiler extends Compiler {
3737
new ExprRun(this, ctx.addMode(Mode.ReadPositions))
3838
}
3939

40-
def outputClassName: TypeName = "Quoted".toTypeName
40+
def outputClassName: TypeName = "Generated$Code$From$Quoted".toTypeName
4141

4242
/** Frontend that receives a scala.quoted.Expr or scala.quoted.Type as input */
4343
class QuotedFrontend(putInClass: Boolean) extends Phase {

compiler/src/dotty/tools/dotc/quoted/QuoteDriver.scala

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,11 @@ import scala.quoted.{Expr, Type}
1111
import scala.quoted.Toolbox
1212
import java.net.URLClassLoader
1313

14-
class QuoteDriver extends Driver {
14+
/** Driver to compile quoted code
15+
*
16+
* @param appClassloader classloader of the application that generated the quotes
17+
*/
18+
class QuoteDriver(appClassloader: ClassLoader) extends Driver {
1519
import tpd._
1620

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

35-
val classLoader = new AbstractFileClassLoader(outDir, this.getClass.getClassLoader)
39+
assert(!ctx.reporter.hasErrors)
40+
41+
val classLoader = new AbstractFileClassLoader(outDir, appClassloader)
3642

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

8389
override def initCtx: Context = {
8490
val ictx = contextBase.initialCtx
85-
ictx.settings.classpath.update(QuoteDriver.currentClasspath)(ictx)
91+
ictx.settings.classpath.update(QuoteDriver.currentClasspath(appClassloader))(ictx)
8692
ictx
8793
}
8894

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

95101
object QuoteDriver {
96102

97-
def currentClasspath: String = {
103+
def currentClasspath(cl: ClassLoader): String = {
98104
val classpath0 = System.getProperty("java.class.path")
99-
this.getClass.getClassLoader match {
105+
cl match {
100106
case cl: URLClassLoader =>
101107
// Loads the classes loaded by this class loader
102108
// When executing `run` or `test` in sbt the classpath is not in the property java.class.path

compiler/src/dotty/tools/dotc/quoted/ToolboxImpl.scala

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,15 @@ import scala.quoted.Exprs.{LiftedExpr, TastyTreeExpr}
99
object ToolboxImpl {
1010
import tpd._
1111

12-
def make(settings: scala.quoted.Toolbox.Settings): scala.quoted.Toolbox = new scala.quoted.Toolbox {
12+
/** Create a new instance of the toolbox using the the classloader of the application.
13+
*
14+
* @param appClassloader classloader of the application that generated the quotes
15+
* @param settings toolbox settings
16+
* @return A new instance of the toolbox
17+
*/
18+
def make(settings: scala.quoted.Toolbox.Settings, appClassloader: ClassLoader): scala.quoted.Toolbox = new scala.quoted.Toolbox {
1319

14-
private[this] val driver: QuoteDriver = new QuoteDriver()
20+
private[this] val driver: QuoteDriver = new QuoteDriver(appClassloader)
1521

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

2733
def show[T](tpe: Type[T]): String = synchronized(driver.show(tpe, settings))
2834
}
35+
2936
}

compiler/src/dotty/tools/dotc/transform/Erasure.scala

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -358,9 +358,13 @@ object Erasure {
358358
/** This override is only needed to semi-erase type ascriptions */
359359
override def typedTyped(tree: untpd.Typed, pt: Type)(implicit ctx: Context): Tree = {
360360
val Typed(expr, tpt) = tree
361-
val tpt1 = promote(tpt)
362-
val expr1 = typed(expr, tpt1.tpe)
363-
assignType(untpd.cpy.Typed(tree)(expr1, tpt1), tpt1)
361+
val tpt1 = tpt match {
362+
case Block(_, tpt) => tpt // erase type aliases (statements) from type block
363+
case tpt => tpt
364+
}
365+
val tpt2 = promote(tpt1)
366+
val expr1 = typed(expr, tpt2.tpe)
367+
assignType(untpd.cpy.Typed(tree)(expr1, tpt2), tpt2)
364368
}
365369

366370
override def typedLiteral(tree: untpd.Literal)(implicit ctx: Context): Tree =

compiler/test-resources/repl/i6007

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
scala> implicit def toolbox: scala.quoted.Toolbox = scala.quoted.Toolbox.make(getClass.getClassLoader)
2+
def toolbox: quoted.Toolbox
3+
scala> val v = '{ (if true then Some(1) else None).map(v => v+1) }
4+
val v: quoted.Expr[Option[Int]] = Expr(<pickled tasty>)
5+
scala> v.show
6+
val res0: String = (if (true) scala.Some.apply[scala.Int](1) else scala.None).map[scala.Int](((v: scala.Int) => v.+(1)))
7+
scala> v.run
8+
val res1: Option[Int] = Some(2)

library/src/scala/quoted/Toolbox.scala

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ package scala.quoted
22

33
import scala.annotation.implicitNotFound
44

5-
@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._`")
5+
@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")
66
trait Toolbox {
77
def run[T](expr: Expr[T]): T
88
def show[T](expr: Expr[T]): String
@@ -11,17 +11,22 @@ trait Toolbox {
1111

1212
object Toolbox {
1313

14-
object Default {
15-
// TODO remove? It may be better to only have one way to instantiate the toolbox
16-
implicit def make(implicit settings: Settings): Toolbox = Toolbox.make
17-
}
18-
19-
def make(implicit settings: Settings): Toolbox = {
20-
val cl = getClass.getClassLoader
14+
/** Create a new instance of the toolbox using the the classloader of the application.
15+
*
16+
* Usuage:
17+
* ```
18+
* implicit val toolbox: scala.quoted.Toolbox = scala.quoted.Toolbox.make(getClass.getClassLoader)
19+
* ```
20+
*
21+
* @param appClassloader classloader of the application that generated the quotes
22+
* @param settings toolbox settings
23+
* @return A new instance of the toolbox
24+
*/
25+
def make(appClassloader: ClassLoader)(implicit settings: Settings): Toolbox = {
2126
try {
22-
val toolboxImplCls = cl.loadClass("dotty.tools.dotc.quoted.ToolboxImpl")
23-
val makeMeth = toolboxImplCls.getMethod("make", classOf[Settings])
24-
makeMeth.invoke(null, settings).asInstanceOf[Toolbox]
27+
val toolboxImplCls = appClassloader.loadClass("dotty.tools.dotc.quoted.ToolboxImpl")
28+
val makeMeth = toolboxImplCls.getMethod("make", classOf[Settings], classOf[ClassLoader])
29+
makeMeth.invoke(null, settings, appClassloader).asInstanceOf[Toolbox]
2530
}
2631
catch {
2732
case ex: ClassNotFoundException =>
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
scalaVersion := sys.props("plugin.scalaVersion")
2+
3+
libraryDependencies ++= Seq(
4+
"ch.epfl.lamp" % "dotty_0.14" % scalaVersion.value,
5+
"ch.epfl.lamp" % "dotty_0.14" % scalaVersion.value % "test->runtime",
6+
"com.novocode" % "junit-interface" % "0.11" % "test"
7+
)
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
addSbtPlugin("ch.epfl.lamp" % "sbt-dotty" % sys.props("plugin.version"))
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
package hello
2+
3+
// Import Expr and some extension methods
4+
import scala.quoted._
5+
6+
object Main {
7+
8+
implicit val toolbox: scala.quoted.Toolbox = scala.quoted.Toolbox.make(getClass.getClassLoader)
9+
10+
def main(args: Array[String]): Unit = {
11+
12+
val square = stagedPower(2)
13+
14+
assert(Math.pow(3, 2) == square(3))
15+
16+
square(3)
17+
square(4)
18+
19+
assert(Math.pow(4, 2) == square(4))
20+
21+
val cube = stagedPower(3)
22+
cube(2)
23+
24+
25+
assert(Math.pow(2, 3) == cube(2))
26+
27+
28+
29+
val toTheFourth = stagedPower(4)
30+
assert(Math.pow(3, 4) == toTheFourth(3))
31+
}
32+
33+
def stagedPower(n: Int): Double => Double = {
34+
// Code representing the labmda where the recursion is unrolled based on the value of n
35+
val code = '{ (x: Double) => ${powerCode(n, '{x})}}
36+
37+
code.show
38+
39+
// Evaluate the contents of the code and return it's value
40+
code.run
41+
}
42+
43+
def powerCode(n: Int, x: Expr[Double]): Expr[Double] =
44+
if (n == 0) '{1.0}
45+
else if (n == 1) x
46+
else if (n < 0) throw new Exception("Negative powers not implemented. Left as a small exercise. Dont be shy, try it out.")
47+
else if (n == 2) '{$x * $x}
48+
else if (n % 2 == 1) '{$x * ${powerCode(n - 1, x)}}
49+
else '{ val y = $x * $x; ${powerCode(n / 2, '{y})}}
50+
51+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
> run

tests/neg-with-compiler/i5941/macro_1.scala

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,9 @@ object Lens {
1313
}
1414

1515
def impl[S: Type, T: Type](getter: Expr[S => T])(implicit refl: Reflection): Expr[Lens[S, T]] = {
16+
implicit val toolbox: scala.quoted.Toolbox = scala.quoted.Toolbox.make(this.getClass.getClassLoader)
1617
import refl._
1718
import util._
18-
import quoted.Toolbox.Default._
19-
2019
// obj.copy(field = value)
2120
def setterBody(obj: Expr[S], value: Expr[T], field: String): Expr[S] =
2221
Select.overloaded(obj.unseal, "copy", Nil, NamedArg(field, value.unseal) :: Nil).seal.cast[S]

tests/neg-with-compiler/quote-run-in-macro-1/quoted_1.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import scala.quoted._
22
import scala.quoted.autolift._
33

4-
import scala.quoted.Toolbox.Default._
5-
64
object Macros {
5+
6+
implicit val toolbox: scala.quoted.Toolbox = scala.quoted.Toolbox.make(getClass.getClassLoader)
77
inline def foo(i: => Int): Int = ${ fooImpl('i) }
88
def fooImpl(i: Expr[Int]): Expr[Int] = {
99
val y: Int = i.run

tests/neg-with-compiler/quote-run-in-macro-2/quoted_1.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
import scala.quoted._
22
import scala.quoted.autolift._
3-
import scala.quoted.Toolbox.Default._
43

54
object Macros {
5+
66
inline def foo(i: => Int): Int = ${ fooImpl('i) }
77
def fooImpl(i: Expr[Int]): Expr[Int] = {
8+
implicit val toolbox: scala.quoted.Toolbox = scala.quoted.Toolbox.make(getClass.getClassLoader)
89
val y: Int = i.run
910
y
1011
}

tests/neg/i1779.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,6 @@ object Test {
88
def f = {
99
val _parent = 3
1010
q"val hello = $_parent"
11-
q"class $_" // error
11+
q"class $_" // error // error
1212
} // error
1313
}

tests/neg/i4934.scala

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
object Foo {
2+
val a = ""); // error: end of statement expected
3+
}
4+
// From #5824:
5+
object Main {
6+
def main(args: Array[String]): Unit = {
7+
val foo = 123 ""; // error: end of statement expected
8+
println(foo)
9+
}
10+
}

tests/neg/parser-stability-16.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,5 @@ class x0[x0] {
22
val x1 : x0
33
}
44
trait x3 extends x0 { // error
5-
x1 = 0 object // error
5+
x1 = 0 object // error // error
66
// error

tests/neg/parser-stability-17.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
trait x0[] { x0: x0 => } // error // error
2-
class x0[x1] extends x0[x0 x0] x2 x0 // error // error
2+
class x0[x1] extends x0[x0 x0] x2 x0 // error // error // error

tests/neg/parser-stability-23.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
object i0 {
2-
import Ordering.{ implicitly => } (true: Boolean) match { case _: i1 => true } // error // error
2+
import Ordering.{ implicitly => } (true: Boolean) match { case _: i1 => true } // error // error // error
33
}

tests/neg/parser-stability-4.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
class x0{
2-
def x0: x0 = (x0 => x0) => x0) // error
2+
def x0: x0 = (x0 => x0) => x0) // error // error
33
// error

tests/neg/tasty-string-interpolator-position-a/Macro_1.scala

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ import scala.quoted._
22
import scala.tasty.Reflection
33
import scala.language.implicitConversions
44
import scala.quoted.Exprs.LiftedExpr
5-
import scala.quoted.Toolbox.Default._
65

76
object Macro {
87

tests/neg/tasty-string-interpolator-position-b/Macro_1.scala

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ import scala.quoted._
22
import scala.tasty.Reflection
33
import scala.language.implicitConversions
44
import scala.quoted.Exprs.LiftedExpr
5-
import scala.quoted.Toolbox.Default._
65

76
object Macro {
87

@@ -11,7 +10,7 @@ object Macro {
1110
}
1211

1312
object FIntepolator {
14-
13+
implicit val toolbox: scala.quoted.Toolbox = scala.quoted.Toolbox.make(getClass.getClassLoader)
1514
def apply(strCtxExpr: Expr[StringContext], argsExpr: Expr[Seq[Any]])(implicit reflect: Reflection): Expr[String] = {
1615
import reflect._
1716
error("there are no args", argsExpr.unseal.underlyingArgument.pos)

tests/pos-with-compiler/quote-0.scala

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
import scala.quoted._
22
import scala.quoted.autolift._
33

4-
import scala.quoted.Toolbox.Default._
5-
64
object Macros {
75

86

@@ -41,5 +39,6 @@ class Test {
4139
${ powerCode(3, '{math.sqrt(2.0)}) }
4240
}
4341

42+
implicit val toolbox: scala.quoted.Toolbox = scala.quoted.Toolbox.make(getClass.getClassLoader)
4443
program.run
4544
}

tests/pos-with-compiler/quote-assert/quoted_2.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import scala.quoted.Toolbox.Default._
1+
22
import scala.quoted._
33
import Macros._
44

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

18+
implicit val toolbox: scala.quoted.Toolbox = scala.quoted.Toolbox.make(getClass.getClassLoader)
1819
program.run
1920
}

tests/pos/i6210/Macros_1.scala

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import scala.quoted._
2+
3+
object Macro {
4+
inline def test[A, B]: Any =
5+
${ impl[A, B] }
6+
7+
def impl[A : Type, B : Type]: Expr[Any] = {
8+
val t = '[Map[A, B]]
9+
'{
10+
new Object().asInstanceOf[$t]
11+
???.asInstanceOf[$t]
12+
}
13+
}
14+
}

tests/pos/i6210/Test_2.scala

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
object Test {
2+
type T
3+
def t1 = Macro.test[Int, String]
4+
def t2 = Macro.test[Test.type, T]
5+
}

tests/run-with-compiler-custom-args/staged-streams_1.scala

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -677,8 +677,7 @@ object Test {
677677
.fold('{0}, ((a: Expr[Int], b : Expr[Int]) => '{ $a + $b }))
678678

679679
def main(args: Array[String]): Unit = {
680-
implicit val toolbox: scala.quoted.Toolbox = scala.quoted.Toolbox.make
681-
680+
implicit val toolbox: scala.quoted.Toolbox = scala.quoted.Toolbox.make(getClass.getClassLoader)
682681
println(test1().run)
683682
println
684683
println(test2().run)

0 commit comments

Comments
 (0)