From 5616145d012bbf270caacb7f505c71e811d7a680 Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Fri, 16 Mar 2018 17:52:14 +0100 Subject: [PATCH 1/2] Remove implicit conversion from liftable types to Expr[T] Use `import scala.quotes.Liftable._` and `x.toExpr` notation instead. --- .../reference/principled-meta-programming.md | 29 +++++----- library/src/scala/quoted/Expr.scala | 4 +- library/src/scala/quoted/Liftable.scala | 4 +- library/src/scala/quoted/Type.scala | 2 +- tests/pos/i3898/quoted_1.scala | 2 +- tests/pos/i3898b/quoted_1.scala | 2 +- tests/pos/i3898c/quoted_1.scala | 2 +- tests/pos/i3916/Macro_1.scala | 3 +- tests/pos/i4023b/Macro_1.scala | 2 +- tests/pos/quote-0.scala | 4 +- .../quote-interpolator-core/quoted_1.scala | 3 +- tests/pos/quote-lift.scala | 2 +- tests/pos/quote-liftable.scala | 22 ++++---- tests/run-with-compiler/i4044b.scala | 4 +- tests/run-with-compiler/quote-lib.scala | 19 +++---- .../quote-run-constants-extract-1.scala | 3 +- .../quote-run-constants-extract-2.scala | 5 +- .../quote-run-constants-extract-3.scala | 5 +- .../quote-run-constants-extract-4.scala | 5 +- .../quote-run-constants-extract-5.scala | 5 +- .../quote-run-constants-extract-6.scala | 5 +- .../quote-run-constants.scala | 53 ++++++++++--------- .../quote-run-staged-interpreter.scala | 4 +- .../quote-splice-interpret-1/Macro_1.scala | 6 ++- 24 files changed, 107 insertions(+), 88 deletions(-) diff --git a/docs/docs/reference/principled-meta-programming.md b/docs/docs/reference/principled-meta-programming.md index ea11ac33c3fc..3758292e7946 100644 --- a/docs/docs/reference/principled-meta-programming.md +++ b/docs/docs/reference/principled-meta-programming.md @@ -507,7 +507,7 @@ The compiler takes an environment that maps variable names to Scala `Expr`s. def compile(e: Exp, env: Map[String, Expr[Int]]): Expr[Int] = e match { case Num(n) => - n + n.toExpr case Plus(e1, e2) => ’(~compile(e1, env) + ~compile(e2, env)) case Var(x) => @@ -520,24 +520,25 @@ Running `compile(letExp, Map())` would yield the following Scala code: ’{ val y = 3; (2 + y) + 4 } -The body of the first clause, `case Num(n) => n`, looks suspicious. `n` -is declared as an `Int`, yet the result of `compile` is declared to be -`Expr[Int]`. Shouldn’t `n` be quoted? In fact this would not +The body of the first clause, `case Num(n) => n.toExpr`, looks suspicious. `n` +is declared as an `Int`, yet it is conveted to an `Expr[Int]` with `toExpr`. +Shouldn’t `n` be quoted? In fact this would not work since replacing `n` by `’n` in the clause would not be phase correct. -What happens instead "under the hood" is an implicit conversion: `n` -is expanded to `scala.quoted.Expr.toExpr(n)`. The `toExpr` conversion -is defined in the companion object of class `Expr` as follows: +What happens instead "under the hood" is an extension method `toExpr` is added: `n.toExpr` +is expanded to `new scala.quoted.Liftable.LiftExprOps(n).toExpr`. The `toExpr` extension +is defined in the companion object of class `Liftable` as follows: - object Expr { - implicit def toExpr[T](x: T)(implicit ev: Liftable[T]): Expr[T] = - ev.toExpr(x) + object Liftable { + implicit class LiftExprOps[T](val x: T) extends AnyVal { + def toExpr(implicit ev: Liftable[T]): Expr[T] = ev.toExpr(x) + } } -The conversion says that values of types implementing the `Liftable` -type class can be converted ("lifted") automatically to `Expr` -values. Dotty comes with instance definitions of `Liftable` for +The extension says that values of types implementing the `Liftable` type class can be +converted ("lifted") to `Expr` values using `toExpr` when `Liftable._` is imported. +Dotty comes with instance definitions of `Liftable` for several types including `Boolean`, `String`, and all primitive number types. For example, `Int` values can be converted to `Expr[Int]` values by wrapping the value in a `Literal` tree node. This makes use @@ -570,7 +571,7 @@ a `List` is liftable if its element type is: implicit def ListIsLiftable[T: Liftable]: Liftable[List[T]] = new { def toExpr(xs: List[T]): Expr[List[T]] = xs match { - case x :: xs1 => ’(~implicitly[Liftable[T]].toExpr(x) :: ~toExpr(xs1)) + case x :: xs1 => ’(~x.toExpr :: ~toExpr(xs1)) case Nil => ’(Nil: List[T]) } } diff --git a/library/src/scala/quoted/Expr.scala b/library/src/scala/quoted/Expr.scala index c1e4cbf9ff7c..7bde768c5501 100644 --- a/library/src/scala/quoted/Expr.scala +++ b/library/src/scala/quoted/Expr.scala @@ -10,8 +10,6 @@ sealed abstract class Expr[T] { } object Expr { - implicit def toExpr[T](x: T)(implicit ev: Liftable[T]): Expr[T] = - ev.toExpr(x) implicit class AsFunction[T, U](private val f: Expr[T => U]) extends AnyVal { def apply(x: Expr[T]): Expr[U] = new Exprs.FunctionAppliedTo[T, U](f, x) @@ -25,7 +23,7 @@ object Expr { object Exprs { /** An Expr backed by a pickled TASTY tree */ final class TastyExpr[T](val tasty: Pickled, val args: Seq[Any]) extends Expr[T] { - override def toString(): String = s"Expr()" + override def toString: String = s"Expr()" } /** An Expr backed by a value. diff --git a/library/src/scala/quoted/Liftable.scala b/library/src/scala/quoted/Liftable.scala index 2419f44405e1..4b5039595616 100644 --- a/library/src/scala/quoted/Liftable.scala +++ b/library/src/scala/quoted/Liftable.scala @@ -6,7 +6,7 @@ import scala.quoted.Exprs.ValueExpr * without going through an explicit `'(...)` operation. */ abstract class Liftable[T] { - implicit def toExpr(x: T): Expr[T] + def toExpr(x: T): Expr[T] } /** Some liftable base types. To be completed with at least all types @@ -17,7 +17,7 @@ abstract class Liftable[T] { object Liftable { implicit class LiftExprOps[T](val x: T) extends AnyVal { - def toExpr(implicit liftable: Liftable[T]): Expr[T] = liftable.toExpr(x) + def toExpr(implicit ev: Liftable[T]): Expr[T] = ev.toExpr(x) } implicit def BooleanIsLiftable: Liftable[Boolean] = (x: Boolean) => new ValueExpr(x) diff --git a/library/src/scala/quoted/Type.scala b/library/src/scala/quoted/Type.scala index 66ace17f1bee..0b7b2b469165 100644 --- a/library/src/scala/quoted/Type.scala +++ b/library/src/scala/quoted/Type.scala @@ -39,4 +39,4 @@ object Types { final class TreeType[Tree](val tree: Tree) extends quoted.Type[Any] { override def toString: String = s"Type()" } -} \ No newline at end of file +} diff --git a/tests/pos/i3898/quoted_1.scala b/tests/pos/i3898/quoted_1.scala index fc9ff2f97f48..61fa38781138 100644 --- a/tests/pos/i3898/quoted_1.scala +++ b/tests/pos/i3898/quoted_1.scala @@ -1,5 +1,5 @@ import scala.quoted._ object Macro { inline def ff(args: Any*): String = ~impl('(args)) - def impl(args: Expr[Seq[Any]]): Expr[String] = "" + def impl(args: Expr[Seq[Any]]): Expr[String] = '("") } diff --git a/tests/pos/i3898b/quoted_1.scala b/tests/pos/i3898b/quoted_1.scala index 821744e111ca..fb2072ab4cb9 100644 --- a/tests/pos/i3898b/quoted_1.scala +++ b/tests/pos/i3898b/quoted_1.scala @@ -1,5 +1,5 @@ import scala.quoted._ object Macro { inline def ff(x: Int, inline y: Int): String = ~impl('(x)) - def impl(x: Expr[Int]): Expr[String] = "" + def impl(x: Expr[Int]): Expr[String] = '("") } diff --git a/tests/pos/i3898c/quoted_1.scala b/tests/pos/i3898c/quoted_1.scala index 821744e111ca..fb2072ab4cb9 100644 --- a/tests/pos/i3898c/quoted_1.scala +++ b/tests/pos/i3898c/quoted_1.scala @@ -1,5 +1,5 @@ import scala.quoted._ object Macro { inline def ff(x: Int, inline y: Int): String = ~impl('(x)) - def impl(x: Expr[Int]): Expr[String] = "" + def impl(x: Expr[Int]): Expr[String] = '("") } diff --git a/tests/pos/i3916/Macro_1.scala b/tests/pos/i3916/Macro_1.scala index a981f575764a..190ceac21ed3 100644 --- a/tests/pos/i3916/Macro_1.scala +++ b/tests/pos/i3916/Macro_1.scala @@ -1,4 +1,5 @@ import scala.quoted._ +import scala.quoted.Liftable._ class FInterpolatorHelper(val sc: StringContext) extends AnyVal { inline def ff(arg1: Any): String = ~FInterpolation.fInterpolation(sc, Seq('(arg1))) @@ -14,7 +15,7 @@ object FInterpolation { } def fInterpolation(sc: StringContext, args: Seq[Expr[Any]]): Expr[String] = { - val str: Expr[String] = sc.parts.mkString("") + val str: Expr[String] = sc.parts.mkString("").toExpr val args1: Expr[Seq[Any]] = liftSeq(args) '{ (~str).format(~args1: _*) } } diff --git a/tests/pos/i4023b/Macro_1.scala b/tests/pos/i4023b/Macro_1.scala index 7aa305e3183a..e440b4e1923a 100644 --- a/tests/pos/i4023b/Macro_1.scala +++ b/tests/pos/i4023b/Macro_1.scala @@ -1,5 +1,5 @@ import scala.quoted._ object Macro { inline def ff[T](implicit t: Type[T]): Int = ~impl[T] - def impl[T]: Expr[Int] = 4 + def impl[T]: Expr[Int] = '(4) } diff --git a/tests/pos/quote-0.scala b/tests/pos/quote-0.scala index 9c44151eef36..ab1073dae303 100644 --- a/tests/pos/quote-0.scala +++ b/tests/pos/quote-0.scala @@ -1,4 +1,6 @@ import scala.quoted._ +import scala.quoted.Liftable._ + import dotty.tools.dotc.quoted.Toolbox._ class Test { @@ -11,7 +13,7 @@ class Test { def assertImpl(expr: Expr[Boolean]) = '{ if !(~expr) then throw new AssertionError(s"failed assertion: ${~showExpr(expr)}") } - def showExpr[T](expr: Expr[T]): Expr[String] = expr.toString + def showExpr[T](expr: Expr[T]): Expr[String] = expr.toString.toExpr inline def power(inline n: Int, x: Double) = ~powerCode(n, '(x)) diff --git a/tests/pos/quote-interpolator-core/quoted_1.scala b/tests/pos/quote-interpolator-core/quoted_1.scala index bd24977de5a5..f4bb2a1c2c03 100644 --- a/tests/pos/quote-interpolator-core/quoted_1.scala +++ b/tests/pos/quote-interpolator-core/quoted_1.scala @@ -1,4 +1,5 @@ import scala.quoted._ +import scala.quoted.Liftable._ // This test checks the correct interpretation of the inlined value class @@ -17,7 +18,7 @@ object FInterpolation { } def fInterpolation(sc: StringContext, args: Seq[Expr[Any]]): Expr[String] = { - val str: Expr[String] = sc.parts.mkString("") + val str: Expr[String] = sc.parts.mkString("").toExpr val args1: Expr[Seq[Any]] = liftSeq(args) '{ (~str).format(~args1: _*) } } diff --git a/tests/pos/quote-lift.scala b/tests/pos/quote-lift.scala index 2616b524ccf3..92df158898cd 100644 --- a/tests/pos/quote-lift.scala +++ b/tests/pos/quote-lift.scala @@ -1,7 +1,7 @@ import scala.quoted._ +import scala.quoted.Liftable._ object Test { - '{ ~(1: Expr[Int]) } '{ ~implicitly[Liftable[Int]].toExpr(1) } diff --git a/tests/pos/quote-liftable.scala b/tests/pos/quote-liftable.scala index 0388a1da6432..86d994d2fb73 100644 --- a/tests/pos/quote-liftable.scala +++ b/tests/pos/quote-liftable.scala @@ -1,5 +1,7 @@ import scala.quoted._ +import scala.quoted.Liftable._ + object Test { implicit def IntIsLiftable: Liftable[Int] = new { @@ -24,15 +26,15 @@ object Test { } } - (true: Expr[Boolean]) - (1: Expr[Byte]) - ('a': Expr[Char]) - (1: Expr[Short]) - (1: Expr[Int]) - (1L: Expr[Long]) - (1.0f: Expr[Float]) - (1.0: Expr[Double]) - ("abc": Expr[String]) + true.toExpr + 1.toExpr + 'a'.toExpr + 1.toExpr + 1.toExpr + 1L.toExpr + 1.0f.toExpr + 1.0.toExpr + "abc".toExpr - val xs: Expr[List[Int]] = 1 :: 2 :: 3 :: Nil + val xs: Expr[List[Int]] = (1 :: 2 :: 3 :: Nil).toExpr } diff --git a/tests/run-with-compiler/i4044b.scala b/tests/run-with-compiler/i4044b.scala index c4255d7d8d7a..b2602f6c7040 100644 --- a/tests/run-with-compiler/i4044b.scala +++ b/tests/run-with-compiler/i4044b.scala @@ -1,4 +1,6 @@ import scala.quoted._ +import scala.quoted.Liftable._ + import dotty.tools.dotc.quoted.Toolbox._ sealed abstract class VarRef[T] { @@ -21,7 +23,7 @@ object VarRef { object Test { def main(args: Array[String]): Unit = { - val q = VarRef(4)(varRef => '{ ~varRef.update(3); ~varRef.expr }) + val q = VarRef('(4))(varRef => '{ ~varRef.update('(3)); ~varRef.expr }) println(q.show) } } diff --git a/tests/run-with-compiler/quote-lib.scala b/tests/run-with-compiler/quote-lib.scala index 630b2df6d7d2..f4916fab966e 100644 --- a/tests/run-with-compiler/quote-lib.scala +++ b/tests/run-with-compiler/quote-lib.scala @@ -1,5 +1,6 @@ import scala.quoted._ +import scala.quoted.Liftable._ import dotty.tools.dotc.quoted.Toolbox._ import liftable.Units._ @@ -12,7 +13,7 @@ import liftable.Exprs._ object Test { def main(args: Array[String]): Unit = { - val liftedUnit: Expr[Unit] = () + val liftedUnit: Expr[Unit] = '() letVal('(1))(a => '{ ~a + 1 }).show letLazyVal('(1))(a => '{ ~a + 1 }).show @@ -21,18 +22,18 @@ object Test { liftedWhile('(true))('{ println(1) }).show liftedDoWhile('{ println(1) })('(true)).show - val t1: Expr[Tuple1[Int]] = Tuple1(4) - val t2: Expr[(Int, Int)] = (2, 3) - val t3: Expr[(Int, Int, Int)] = (2, 3, 4) - val t4: Expr[(Int, Int, Int, Int)] = (2, 3, 4, 5) + val t1: Expr[Tuple1[Int]] = Tuple1(4).toExpr + val t2: Expr[(Int, Int)] = (2, 3).toExpr + val t3: Expr[(Int, Int, Int)] = (2, 3, 4).toExpr + val t4: Expr[(Int, Int, Int, Int)] = (2, 3, 4, 5).toExpr val list: List[Int] = List(1, 2, 3) - val liftedList: Expr[List[Int]] = list + val liftedList: Expr[List[Int]] = list.toExpr - liftedList.foldLeft[Int](0)('{ (acc: Int, x: Int) => acc + x }).show + liftedList.foldLeft[Int](0.toExpr)('{ (acc: Int, x: Int) => acc + x }).show liftedList.foreach('{ (x: Int) => println(x) }).show - list.unrolledFoldLeft[Int](0)('{ (acc: Int, x: Int) => acc + x }).show + list.unrolledFoldLeft[Int](0.toExpr)('{ (acc: Int, x: Int) => acc + x }).show list.unrolledForeach('{ (x: Int) => println(x) }).show println("quote lib ok") @@ -113,7 +114,7 @@ package liftable { } def unrolledForeach(f: Expr[T => Unit]): Expr[Unit] = list match { case x :: xs => '{ (~f).apply(~x.toExpr); ~xs.unrolledForeach(f) } - case Nil => () + case Nil => '() } } diff --git a/tests/run-with-compiler/quote-run-constants-extract-1.scala b/tests/run-with-compiler/quote-run-constants-extract-1.scala index 2d8b5a151655..f08ccf90b737 100644 --- a/tests/run-with-compiler/quote-run-constants-extract-1.scala +++ b/tests/run-with-compiler/quote-run-constants-extract-1.scala @@ -1,11 +1,12 @@ import scala.quoted._ +import scala.quoted.Liftable._ import dotty.tools.dotc.quoted.Toolbox._ object Test { def main(args: Array[String]): Unit = { - (3: Expr[Int]) match { case Constant(n) => println(n) } + 3.toExpr match { case Constant(n) => println(n) } '(4) match { case Constant(n) => println(n) } '("abc") match { case Constant(n) => println(n) } '(null) match { case Constant(n) => println(n) } diff --git a/tests/run-with-compiler/quote-run-constants-extract-2.scala b/tests/run-with-compiler/quote-run-constants-extract-2.scala index 2108a6b604a2..c4b8bdf3a0ef 100644 --- a/tests/run-with-compiler/quote-run-constants-extract-2.scala +++ b/tests/run-with-compiler/quote-run-constants-extract-2.scala @@ -1,4 +1,5 @@ import scala.quoted._ +import scala.quoted.Liftable._ import dotty.tools.dotc.quoted.Toolbox._ @@ -6,8 +7,8 @@ object Test { def main(args: Array[String]): Unit = { // 2 is a lifted constant - println(power(2, 3.0).show) - println(power(2, 3.0).run) + println(power(2.toExpr, 3.0.toExpr).show) + println(power(2.toExpr, 3.0.toExpr).run) } def power(n: Expr[Int], x: Expr[Double]): Expr[Double] = { diff --git a/tests/run-with-compiler/quote-run-constants-extract-3.scala b/tests/run-with-compiler/quote-run-constants-extract-3.scala index 2108a6b604a2..c4b8bdf3a0ef 100644 --- a/tests/run-with-compiler/quote-run-constants-extract-3.scala +++ b/tests/run-with-compiler/quote-run-constants-extract-3.scala @@ -1,4 +1,5 @@ import scala.quoted._ +import scala.quoted.Liftable._ import dotty.tools.dotc.quoted.Toolbox._ @@ -6,8 +7,8 @@ object Test { def main(args: Array[String]): Unit = { // 2 is a lifted constant - println(power(2, 3.0).show) - println(power(2, 3.0).run) + println(power(2.toExpr, 3.0.toExpr).show) + println(power(2.toExpr, 3.0.toExpr).run) } def power(n: Expr[Int], x: Expr[Double]): Expr[Double] = { diff --git a/tests/run-with-compiler/quote-run-constants-extract-4.scala b/tests/run-with-compiler/quote-run-constants-extract-4.scala index ca31a75211c8..fa1faf1358c2 100644 --- a/tests/run-with-compiler/quote-run-constants-extract-4.scala +++ b/tests/run-with-compiler/quote-run-constants-extract-4.scala @@ -1,4 +1,5 @@ import scala.quoted._ +import scala.quoted.Liftable._ import dotty.tools.dotc.quoted.Toolbox._ @@ -7,8 +8,8 @@ object Test { def main(args: Array[String]): Unit = { // n is a lifted constant val n = 2 - println(power(n, 4.0).show) - println(power(n, 4.0).run) + println(power(n.toExpr, 4.0.toExpr).show) + println(power(n.toExpr, 4.0.toExpr).run) } def power(n: Expr[Int], x: Expr[Double]): Expr[Double] = { diff --git a/tests/run-with-compiler/quote-run-constants-extract-5.scala b/tests/run-with-compiler/quote-run-constants-extract-5.scala index 84632588cccb..b581919024b9 100644 --- a/tests/run-with-compiler/quote-run-constants-extract-5.scala +++ b/tests/run-with-compiler/quote-run-constants-extract-5.scala @@ -1,4 +1,5 @@ import scala.quoted._ +import scala.quoted.Liftable._ import dotty.tools.dotc.quoted.Toolbox._ @@ -6,8 +7,8 @@ object Test { def main(args: Array[String]): Unit = { // n is a constant in a quote - println(power('(2), 5.0).show) - println(power('(2), 5.0).run) + println(power('(2), 5.0.toExpr).show) + println(power('(2), 5.0.toExpr).run) } def power(n: Expr[Int], x: Expr[Double]): Expr[Double] = { diff --git a/tests/run-with-compiler/quote-run-constants-extract-6.scala b/tests/run-with-compiler/quote-run-constants-extract-6.scala index 3e8c8ab84fa2..a7736f0a73a3 100644 --- a/tests/run-with-compiler/quote-run-constants-extract-6.scala +++ b/tests/run-with-compiler/quote-run-constants-extract-6.scala @@ -1,4 +1,5 @@ import scala.quoted._ +import scala.quoted.Liftable._ import dotty.tools.dotc.quoted.Toolbox._ @@ -7,8 +8,8 @@ object Test { def main(args: Array[String]): Unit = { // n2 is clearly not a constant val n2 = '{ println("foo"); 2 } - println(power(n2, 6.0).show) - println(power(n2, 6.0).run) + println(power(n2, 6.0.toExpr).show) + println(power(n2, 6.0.toExpr).run) } def power(n: Expr[Int], x: Expr[Double]): Expr[Double] = { diff --git a/tests/run-with-compiler/quote-run-constants.scala b/tests/run-with-compiler/quote-run-constants.scala index c612e08ca066..07953639e0e8 100644 --- a/tests/run-with-compiler/quote-run-constants.scala +++ b/tests/run-with-compiler/quote-run-constants.scala @@ -2,41 +2,42 @@ import dotty.tools.dotc.quoted.Toolbox._ import scala.quoted._ +import scala.quoted.Liftable._ object Test { def main(args: Array[String]): Unit = { def run[T](expr: Expr[T]): Unit = println(expr.run) def show[T](expr: Expr[T]): Unit = println(expr.show) - run(true) - run('a') - run('\n') - run('"') - run('\'') - run('\\') - run(1) - run(2) - run(3L) - run(4.0f) - run(5.0d) - run("xyz") + run(true.toExpr) + run('a'.toExpr) + run('\n'.toExpr) + run('"'.toExpr) + run('\''.toExpr) + run('\\'.toExpr) + run(1.toExpr) + run(2.toExpr) + run(3L.toExpr) + run(4.0f.toExpr) + run(5.0d.toExpr) + run("xyz".toExpr) println("======") - show(true) - show('a') - show('\n') - show('"') - show('\'') - show('\\') - show(1) - show(2) - show(3L) - show(4.0f) - show(5.0d) - show("xyz") - show("\n\\\"'") + show(true.toExpr) + show('a'.toExpr) + show('\n'.toExpr) + show('"'.toExpr) + show('\''.toExpr) + show('\\'.toExpr) + show(1.toExpr) + show(2.toExpr) + show(3L.toExpr) + show(4.0f.toExpr) + show(5.0d.toExpr) + show("xyz".toExpr) + show("\n\\\"'".toExpr) show("""abc - xyz""") + xyz""".toExpr) } } diff --git a/tests/run-with-compiler/quote-run-staged-interpreter.scala b/tests/run-with-compiler/quote-run-staged-interpreter.scala index 76311f2f0bd6..712d4b05f3d0 100644 --- a/tests/run-with-compiler/quote-run-staged-interpreter.scala +++ b/tests/run-with-compiler/quote-run-staged-interpreter.scala @@ -1,4 +1,6 @@ import scala.quoted._ +import scala.quoted.Liftable._ + import dotty.tools.dotc.quoted.Toolbox._ enum Exp { @@ -13,7 +15,7 @@ object Test { def compile(e: Exp, env: Map[String, Expr[Int]], keepLets: Boolean): Expr[Int] = { def compileImpl(e: Exp, env: Map[String, Expr[Int]]): Expr[Int] = e match { - case Num(n) => n + case Num(n) => n.toExpr case Plus(e1, e2) => '(~compileImpl(e1, env) + ~compileImpl(e2, env)) case Var(x) => env(x) case Let(x, e, body) => diff --git a/tests/run/quote-splice-interpret-1/Macro_1.scala b/tests/run/quote-splice-interpret-1/Macro_1.scala index 051c434a9a86..b05808d4af74 100644 --- a/tests/run/quote-splice-interpret-1/Macro_1.scala +++ b/tests/run/quote-splice-interpret-1/Macro_1.scala @@ -1,14 +1,16 @@ import dotty.tools.dotc.ast.Trees.Import import scala.quoted._ +import scala.quoted.Liftable._ + object Macros { sealed trait Nat case object Z extends Nat case class S[N <: Nat]() extends Nat inline def isZero(inline n: Int): Boolean = ~{ - if (n == 0) (true: Expr[Boolean]) - else (false: Expr[Boolean]) + if (n == 0) '(true) + else '(false) } } From d65148ff3671d496379c85da7906a3a55d33c9fc Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Fri, 16 Mar 2018 18:02:49 +0100 Subject: [PATCH 2/2] Move LiftExprOps to quoted package To use `import scala.quotes._` to import `toExpr` extension --- docs/docs/reference/principled-meta-programming.md | 6 +++--- library/src/scala/quoted/Liftable.scala | 5 ----- library/src/scala/quoted/package.scala | 9 +++++++++ tests/pos/i3916/Macro_1.scala | 1 - tests/pos/quote-0.scala | 1 - tests/pos/quote-interpolator-core/quoted_1.scala | 1 - tests/pos/quote-lift.scala | 1 - tests/pos/quote-liftable.scala | 2 -- tests/run-with-compiler/i4044b.scala | 1 - tests/run-with-compiler/quote-lib.scala | 2 -- .../quote-run-constants-extract-1.scala | 1 - .../quote-run-constants-extract-2.scala | 1 - .../quote-run-constants-extract-3.scala | 1 - .../quote-run-constants-extract-4.scala | 1 - .../quote-run-constants-extract-5.scala | 1 - .../quote-run-constants-extract-6.scala | 1 - tests/run-with-compiler/quote-run-constants.scala | 1 - .../run-with-compiler/quote-run-staged-interpreter.scala | 1 - tests/run-with-compiler/quote-show-blocks-raw.scala | 1 - tests/run-with-compiler/quote-show-blocks.scala | 1 - tests/run/quote-splice-interpret-1/Macro_1.scala | 1 - 21 files changed, 12 insertions(+), 28 deletions(-) create mode 100644 library/src/scala/quoted/package.scala diff --git a/docs/docs/reference/principled-meta-programming.md b/docs/docs/reference/principled-meta-programming.md index 3758292e7946..a10f1a312bd7 100644 --- a/docs/docs/reference/principled-meta-programming.md +++ b/docs/docs/reference/principled-meta-programming.md @@ -527,17 +527,17 @@ work since replacing `n` by `’n` in the clause would not be phase correct. What happens instead "under the hood" is an extension method `toExpr` is added: `n.toExpr` -is expanded to `new scala.quoted.Liftable.LiftExprOps(n).toExpr`. The `toExpr` extension +is expanded to `new scala.quoted.LiftExprOps(n).toExpr`. The `toExpr` extension is defined in the companion object of class `Liftable` as follows: - object Liftable { + package object quoted { implicit class LiftExprOps[T](val x: T) extends AnyVal { def toExpr(implicit ev: Liftable[T]): Expr[T] = ev.toExpr(x) } } The extension says that values of types implementing the `Liftable` type class can be -converted ("lifted") to `Expr` values using `toExpr` when `Liftable._` is imported. +converted ("lifted") to `Expr` values using `toExpr` when `scala.quoted._` is imported. Dotty comes with instance definitions of `Liftable` for several types including `Boolean`, `String`, and all primitive number types. For example, `Int` values can be converted to `Expr[Int]` diff --git a/library/src/scala/quoted/Liftable.scala b/library/src/scala/quoted/Liftable.scala index 4b5039595616..e36b9bfa32cd 100644 --- a/library/src/scala/quoted/Liftable.scala +++ b/library/src/scala/quoted/Liftable.scala @@ -15,11 +15,6 @@ abstract class Liftable[T] { * gives an alternative implementation using just the basic staging system. */ object Liftable { - - implicit class LiftExprOps[T](val x: T) extends AnyVal { - def toExpr(implicit ev: Liftable[T]): Expr[T] = ev.toExpr(x) - } - implicit def BooleanIsLiftable: Liftable[Boolean] = (x: Boolean) => new ValueExpr(x) implicit def ByteLiftable: Liftable[Byte] = (x: Byte) => new ValueExpr(x) implicit def CharIsLiftable: Liftable[Char] = (x: Char) => new ValueExpr(x) diff --git a/library/src/scala/quoted/package.scala b/library/src/scala/quoted/package.scala new file mode 100644 index 000000000000..3a1be2f5f5e1 --- /dev/null +++ b/library/src/scala/quoted/package.scala @@ -0,0 +1,9 @@ +package scala + +package object quoted { + + implicit class LiftExprOps[T](val x: T) extends AnyVal { + def toExpr(implicit ev: Liftable[T]): Expr[T] = ev.toExpr(x) + } + +} diff --git a/tests/pos/i3916/Macro_1.scala b/tests/pos/i3916/Macro_1.scala index 190ceac21ed3..3ad93b037a5a 100644 --- a/tests/pos/i3916/Macro_1.scala +++ b/tests/pos/i3916/Macro_1.scala @@ -1,5 +1,4 @@ import scala.quoted._ -import scala.quoted.Liftable._ class FInterpolatorHelper(val sc: StringContext) extends AnyVal { inline def ff(arg1: Any): String = ~FInterpolation.fInterpolation(sc, Seq('(arg1))) diff --git a/tests/pos/quote-0.scala b/tests/pos/quote-0.scala index ab1073dae303..c6b17d609e0f 100644 --- a/tests/pos/quote-0.scala +++ b/tests/pos/quote-0.scala @@ -1,5 +1,4 @@ import scala.quoted._ -import scala.quoted.Liftable._ import dotty.tools.dotc.quoted.Toolbox._ diff --git a/tests/pos/quote-interpolator-core/quoted_1.scala b/tests/pos/quote-interpolator-core/quoted_1.scala index f4bb2a1c2c03..7b136b080957 100644 --- a/tests/pos/quote-interpolator-core/quoted_1.scala +++ b/tests/pos/quote-interpolator-core/quoted_1.scala @@ -1,5 +1,4 @@ import scala.quoted._ -import scala.quoted.Liftable._ // This test checks the correct interpretation of the inlined value class diff --git a/tests/pos/quote-lift.scala b/tests/pos/quote-lift.scala index 92df158898cd..1ec60672d34d 100644 --- a/tests/pos/quote-lift.scala +++ b/tests/pos/quote-lift.scala @@ -1,5 +1,4 @@ import scala.quoted._ -import scala.quoted.Liftable._ object Test { diff --git a/tests/pos/quote-liftable.scala b/tests/pos/quote-liftable.scala index 86d994d2fb73..2edb101fdaa9 100644 --- a/tests/pos/quote-liftable.scala +++ b/tests/pos/quote-liftable.scala @@ -1,7 +1,5 @@ import scala.quoted._ -import scala.quoted.Liftable._ - object Test { implicit def IntIsLiftable: Liftable[Int] = new { diff --git a/tests/run-with-compiler/i4044b.scala b/tests/run-with-compiler/i4044b.scala index b2602f6c7040..a7fab6ff914c 100644 --- a/tests/run-with-compiler/i4044b.scala +++ b/tests/run-with-compiler/i4044b.scala @@ -1,5 +1,4 @@ import scala.quoted._ -import scala.quoted.Liftable._ import dotty.tools.dotc.quoted.Toolbox._ diff --git a/tests/run-with-compiler/quote-lib.scala b/tests/run-with-compiler/quote-lib.scala index f4916fab966e..bef58a4a2174 100644 --- a/tests/run-with-compiler/quote-lib.scala +++ b/tests/run-with-compiler/quote-lib.scala @@ -1,6 +1,5 @@ import scala.quoted._ -import scala.quoted.Liftable._ import dotty.tools.dotc.quoted.Toolbox._ import liftable.Units._ @@ -43,7 +42,6 @@ object Test { package liftable { import scala.quoted.Liftable - import scala.quoted.Liftable._ import scala.reflect.ClassTag object Exprs { diff --git a/tests/run-with-compiler/quote-run-constants-extract-1.scala b/tests/run-with-compiler/quote-run-constants-extract-1.scala index f08ccf90b737..e019defeba11 100644 --- a/tests/run-with-compiler/quote-run-constants-extract-1.scala +++ b/tests/run-with-compiler/quote-run-constants-extract-1.scala @@ -1,5 +1,4 @@ import scala.quoted._ -import scala.quoted.Liftable._ import dotty.tools.dotc.quoted.Toolbox._ diff --git a/tests/run-with-compiler/quote-run-constants-extract-2.scala b/tests/run-with-compiler/quote-run-constants-extract-2.scala index c4b8bdf3a0ef..8c3edbb72cfd 100644 --- a/tests/run-with-compiler/quote-run-constants-extract-2.scala +++ b/tests/run-with-compiler/quote-run-constants-extract-2.scala @@ -1,5 +1,4 @@ import scala.quoted._ -import scala.quoted.Liftable._ import dotty.tools.dotc.quoted.Toolbox._ diff --git a/tests/run-with-compiler/quote-run-constants-extract-3.scala b/tests/run-with-compiler/quote-run-constants-extract-3.scala index c4b8bdf3a0ef..8c3edbb72cfd 100644 --- a/tests/run-with-compiler/quote-run-constants-extract-3.scala +++ b/tests/run-with-compiler/quote-run-constants-extract-3.scala @@ -1,5 +1,4 @@ import scala.quoted._ -import scala.quoted.Liftable._ import dotty.tools.dotc.quoted.Toolbox._ diff --git a/tests/run-with-compiler/quote-run-constants-extract-4.scala b/tests/run-with-compiler/quote-run-constants-extract-4.scala index fa1faf1358c2..330549fb6f8e 100644 --- a/tests/run-with-compiler/quote-run-constants-extract-4.scala +++ b/tests/run-with-compiler/quote-run-constants-extract-4.scala @@ -1,5 +1,4 @@ import scala.quoted._ -import scala.quoted.Liftable._ import dotty.tools.dotc.quoted.Toolbox._ diff --git a/tests/run-with-compiler/quote-run-constants-extract-5.scala b/tests/run-with-compiler/quote-run-constants-extract-5.scala index b581919024b9..3362a82ee4fe 100644 --- a/tests/run-with-compiler/quote-run-constants-extract-5.scala +++ b/tests/run-with-compiler/quote-run-constants-extract-5.scala @@ -1,5 +1,4 @@ import scala.quoted._ -import scala.quoted.Liftable._ import dotty.tools.dotc.quoted.Toolbox._ diff --git a/tests/run-with-compiler/quote-run-constants-extract-6.scala b/tests/run-with-compiler/quote-run-constants-extract-6.scala index a7736f0a73a3..50110602c844 100644 --- a/tests/run-with-compiler/quote-run-constants-extract-6.scala +++ b/tests/run-with-compiler/quote-run-constants-extract-6.scala @@ -1,5 +1,4 @@ import scala.quoted._ -import scala.quoted.Liftable._ import dotty.tools.dotc.quoted.Toolbox._ diff --git a/tests/run-with-compiler/quote-run-constants.scala b/tests/run-with-compiler/quote-run-constants.scala index 07953639e0e8..6e432baba955 100644 --- a/tests/run-with-compiler/quote-run-constants.scala +++ b/tests/run-with-compiler/quote-run-constants.scala @@ -2,7 +2,6 @@ import dotty.tools.dotc.quoted.Toolbox._ import scala.quoted._ -import scala.quoted.Liftable._ object Test { def main(args: Array[String]): Unit = { diff --git a/tests/run-with-compiler/quote-run-staged-interpreter.scala b/tests/run-with-compiler/quote-run-staged-interpreter.scala index 712d4b05f3d0..5f580fd82d21 100644 --- a/tests/run-with-compiler/quote-run-staged-interpreter.scala +++ b/tests/run-with-compiler/quote-run-staged-interpreter.scala @@ -1,5 +1,4 @@ import scala.quoted._ -import scala.quoted.Liftable._ import dotty.tools.dotc.quoted.Toolbox._ diff --git a/tests/run-with-compiler/quote-show-blocks-raw.scala b/tests/run-with-compiler/quote-show-blocks-raw.scala index f41be403d69b..bcd6480451dc 100644 --- a/tests/run-with-compiler/quote-show-blocks-raw.scala +++ b/tests/run-with-compiler/quote-show-blocks-raw.scala @@ -2,7 +2,6 @@ import dotty.tools.dotc.quoted.Toolbox._ import scala.quoted._ -import scala.quoted.Liftable._ object Test { def main(args: Array[String]): Unit = { diff --git a/tests/run-with-compiler/quote-show-blocks.scala b/tests/run-with-compiler/quote-show-blocks.scala index 0c99149934f8..1b84dde97a9c 100644 --- a/tests/run-with-compiler/quote-show-blocks.scala +++ b/tests/run-with-compiler/quote-show-blocks.scala @@ -2,7 +2,6 @@ import dotty.tools.dotc.quoted.Toolbox._ import scala.quoted._ -import scala.quoted.Liftable._ object Test { def main(args: Array[String]): Unit = { diff --git a/tests/run/quote-splice-interpret-1/Macro_1.scala b/tests/run/quote-splice-interpret-1/Macro_1.scala index b05808d4af74..6ba8f0259e4e 100644 --- a/tests/run/quote-splice-interpret-1/Macro_1.scala +++ b/tests/run/quote-splice-interpret-1/Macro_1.scala @@ -1,7 +1,6 @@ import dotty.tools.dotc.ast.Trees.Import import scala.quoted._ -import scala.quoted.Liftable._ object Macros { sealed trait Nat