Skip to content

Commit 7ed9a69

Browse files
Merge pull request #6038 from dotty-staging/autolift
Fix #5986: Add autolift implicit conversion
2 parents 09d6155 + ef06ad7 commit 7ed9a69

File tree

70 files changed

+331
-246
lines changed

Some content is hidden

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

70 files changed

+331
-246
lines changed

docs/docs/reference/other-new-features/principled-meta-programming.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -600,6 +600,12 @@ Using lifting, we can now give the missing definition of `showExpr` in the intro
600600
That is, the `showExpr` method converts its `Expr` argument to a string (`code`), and lifts
601601
the result back to an `Expr[String]` using the `toExpr` wrapper.
602602

603+
**Note**: the `toExpr` extension method can be ommited by importing an implicit
604+
conversion with `import scala.quoted.autolift._`. The programmer is able to
605+
declutter slightly the code at the cost of readable _phase distinction_ between
606+
stages.
607+
608+
603609
## Implementation
604610

605611
### Syntax

library/src-bootstrapped/scala/quoted/package.scala

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@ package scala
22

33
package object quoted {
44

5+
object autolift {
6+
implicit def autoToExpr[T: Liftable](x: T): Expr[T] = x.toExpr
7+
}
8+
59
implicit class LiftExprOps[T](val x: T) extends AnyVal {
610
def toExpr(implicit ev: Liftable[T]): Expr[T] = ev.toExpr(x)
711
}

tests/disabled/run/xml-interpolation-3/XmlQuote_1.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import scala.quoted._
22
import scala.tasty.Tasty
3+
import scala.quoted.autolift._
34

45
import scala.language.implicitConversions
56

@@ -14,6 +15,6 @@ object XmlQuote {
1415

1516
def impl(receiver: StringContext, args: Expr[Seq[Any]]): Expr[Xml] = {
1617
val string = receiver.parts.mkString("??")
17-
'{new Xml(${string.toExpr}, ($args).toList)}
18+
'{new Xml(${string}, ($args).toList)}
1819
}
1920
}
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
import scala.quoted._
2+
import scala.quoted.autolift._
23

34
import scala.quoted.Toolbox.Default._
45

56
object Macros {
67
inline def foo(i: => Int): Int = ${ fooImpl('i) }
78
def fooImpl(i: Expr[Int]): Expr[Int] = {
89
val y: Int = i.run
9-
y.toExpr
10+
y
1011
}
1112
}
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
import scala.quoted._
2-
2+
import scala.quoted.autolift._
33
import scala.quoted.Toolbox.Default._
44

55
object Macros {
66
inline def foo(i: => Int): Int = ${ fooImpl('i) }
77
def fooImpl(i: Expr[Int]): Expr[Int] = {
88
val y: Int = i.run
9-
y.toExpr
9+
y
1010
}
1111
}

tests/neg/inline-case-objects/Macro_1.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11

22
import scala.quoted._
3+
import scala.quoted.autolift._
34

45
object Macros {
5-
def impl(foo: Any): Expr[String] = foo.getClass.getCanonicalName.toExpr
6+
def impl(foo: Any): Expr[String] = foo.getClass.getCanonicalName
67
}
78

89
class Bar {

tests/neg/inline-macro-staged-interpreter/Macro_1.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11

22
import scala.quoted._
3+
import scala.quoted.autolift._
34

45
object E {
56

@@ -14,7 +15,7 @@ trait E[T] {
1415
}
1516

1617
case class I(n: Int) extends E[Int] {
17-
def lift: Expr[Int] = n.toExpr
18+
def lift: Expr[Int] = n
1819
}
1920

2021
case class Plus[T](x: E[T], y: E[T])(implicit op: Plus2[T]) extends E[T] {

tests/neg/inline-option/Macro_1.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11

22
import scala.quoted._
3+
import scala.quoted.autolift._
34

45
object Macro {
56
def impl(opt: Option[Int]): Expr[Int] = opt match {
6-
case Some(i) => i.toExpr
7+
case Some(i) => i
78
case None => '{-1}
89
}
910
}
Lines changed: 23 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,28 @@
11

22
import scala.quoted._
3+
import scala.quoted.autolift._
34

45
object Macros {
5-
def tup1(tup: Tuple1[Int]): Expr[Int] = tup.productIterator.map(_.asInstanceOf[Int]).sum.toExpr
6-
def tup2(tup: Tuple2[Int, Int]): Expr[Int] = tup.productIterator.map(_.asInstanceOf[Int]).sum.toExpr
7-
def tup3(tup: Tuple3[Int, Int, Int]): Expr[Int] = tup.productIterator.map(_.asInstanceOf[Int]).sum.toExpr
8-
def tup4(tup: Tuple4[Int, Int, Int, Int]): Expr[Int] = tup.productIterator.map(_.asInstanceOf[Int]).sum.toExpr
9-
def tup5(tup: Tuple5[Int, Int, Int, Int, Int]): Expr[Int] = tup.productIterator.map(_.asInstanceOf[Int]).sum.toExpr
10-
def tup6(tup: Tuple6[Int, Int, Int, Int, Int, Int]): Expr[Int] = tup.productIterator.map(_.asInstanceOf[Int]).sum.toExpr
11-
def tup7(tup: Tuple7[Int, Int, Int, Int, Int, Int, Int]): Expr[Int] = tup.productIterator.map(_.asInstanceOf[Int]).sum.toExpr
12-
def tup8(tup: Tuple8[Int, Int, Int, Int, Int, Int, Int, Int]): Expr[Int] = tup.productIterator.map(_.asInstanceOf[Int]).sum.toExpr
13-
def tup9(tup: Tuple9[Int, Int, Int, Int, Int, Int, Int, Int, Int]): Expr[Int] = tup.productIterator.map(_.asInstanceOf[Int]).sum.toExpr
14-
def tup10(tup: Tuple10[Int, Int, Int, Int, Int, Int, Int, Int, Int, Int]): Expr[Int] = tup.productIterator.map(_.asInstanceOf[Int]).sum.toExpr
15-
def tup11(tup: Tuple11[Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int]): Expr[Int] = tup.productIterator.map(_.asInstanceOf[Int]).sum.toExpr
16-
def tup12(tup: Tuple12[Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int]): Expr[Int] = tup.productIterator.map(_.asInstanceOf[Int]).sum.toExpr
17-
def tup13(tup: Tuple13[Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int]): Expr[Int] = tup.productIterator.map(_.asInstanceOf[Int]).sum.toExpr
18-
def tup14(tup: Tuple14[Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int]): Expr[Int] = tup.productIterator.map(_.asInstanceOf[Int]).sum.toExpr
19-
def tup15(tup: Tuple15[Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int]): Expr[Int] = tup.productIterator.map(_.asInstanceOf[Int]).sum.toExpr
20-
def tup16(tup: Tuple16[Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int]): Expr[Int] = tup.productIterator.map(_.asInstanceOf[Int]).sum.toExpr
21-
def tup17(tup: Tuple17[Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int]): Expr[Int] = tup.productIterator.map(_.asInstanceOf[Int]).sum.toExpr
22-
def tup18(tup: Tuple18[Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int]): Expr[Int] = tup.productIterator.map(_.asInstanceOf[Int]).sum.toExpr
23-
def tup19(tup: Tuple19[Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int]): Expr[Int] = tup.productIterator.map(_.asInstanceOf[Int]).sum.toExpr
24-
def tup20(tup: Tuple20[Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int]): Expr[Int] = tup.productIterator.map(_.asInstanceOf[Int]).sum.toExpr
25-
def tup21(tup: Tuple21[Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int]): Expr[Int] = tup.productIterator.map(_.asInstanceOf[Int]).sum.toExpr
26-
def tup22(tup: Tuple22[Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int]): Expr[Int] = tup.productIterator.map(_.asInstanceOf[Int]).sum.toExpr
6+
def tup1(tup: Tuple1[Int]): Expr[Int] = tup.productIterator.map(_.asInstanceOf[Int]).sum
7+
def tup2(tup: Tuple2[Int, Int]): Expr[Int] = tup.productIterator.map(_.asInstanceOf[Int]).sum
8+
def tup3(tup: Tuple3[Int, Int, Int]): Expr[Int] = tup.productIterator.map(_.asInstanceOf[Int]).sum
9+
def tup4(tup: Tuple4[Int, Int, Int, Int]): Expr[Int] = tup.productIterator.map(_.asInstanceOf[Int]).sum
10+
def tup5(tup: Tuple5[Int, Int, Int, Int, Int]): Expr[Int] = tup.productIterator.map(_.asInstanceOf[Int]).sum
11+
def tup6(tup: Tuple6[Int, Int, Int, Int, Int, Int]): Expr[Int] = tup.productIterator.map(_.asInstanceOf[Int]).sum
12+
def tup7(tup: Tuple7[Int, Int, Int, Int, Int, Int, Int]): Expr[Int] = tup.productIterator.map(_.asInstanceOf[Int]).sum
13+
def tup8(tup: Tuple8[Int, Int, Int, Int, Int, Int, Int, Int]): Expr[Int] = tup.productIterator.map(_.asInstanceOf[Int]).sum
14+
def tup9(tup: Tuple9[Int, Int, Int, Int, Int, Int, Int, Int, Int]): Expr[Int] = tup.productIterator.map(_.asInstanceOf[Int]).sum
15+
def tup10(tup: Tuple10[Int, Int, Int, Int, Int, Int, Int, Int, Int, Int]): Expr[Int] = tup.productIterator.map(_.asInstanceOf[Int]).sum
16+
def tup11(tup: Tuple11[Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int]): Expr[Int] = tup.productIterator.map(_.asInstanceOf[Int]).sum
17+
def tup12(tup: Tuple12[Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int]): Expr[Int] = tup.productIterator.map(_.asInstanceOf[Int]).sum
18+
def tup13(tup: Tuple13[Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int]): Expr[Int] = tup.productIterator.map(_.asInstanceOf[Int]).sum
19+
def tup14(tup: Tuple14[Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int]): Expr[Int] = tup.productIterator.map(_.asInstanceOf[Int]).sum
20+
def tup15(tup: Tuple15[Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int]): Expr[Int] = tup.productIterator.map(_.asInstanceOf[Int]).sum
21+
def tup16(tup: Tuple16[Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int]): Expr[Int] = tup.productIterator.map(_.asInstanceOf[Int]).sum
22+
def tup17(tup: Tuple17[Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int]): Expr[Int] = tup.productIterator.map(_.asInstanceOf[Int]).sum
23+
def tup18(tup: Tuple18[Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int]): Expr[Int] = tup.productIterator.map(_.asInstanceOf[Int]).sum
24+
def tup19(tup: Tuple19[Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int]): Expr[Int] = tup.productIterator.map(_.asInstanceOf[Int]).sum
25+
def tup20(tup: Tuple20[Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int]): Expr[Int] = tup.productIterator.map(_.asInstanceOf[Int]).sum
26+
def tup21(tup: Tuple21[Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int]): Expr[Int] = tup.productIterator.map(_.asInstanceOf[Int]).sum
27+
def tup22(tup: Tuple22[Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int]): Expr[Int] = tup.productIterator.map(_.asInstanceOf[Int]).sum
2728
}

tests/neg/quote-interpolator-core-old.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import scala.quoted._
2+
import scala.quoted.autolift._
23

34
// This test checks the correct interpretation of the inlined value class
45

@@ -17,7 +18,7 @@ object FInterpolation {
1718
}
1819

1920
def fInterpolation(sc: StringContext, args: Seq[Expr[Any]]): Expr[String] = {
20-
val str: Expr[String] = sc.parts.mkString("").toExpr
21+
val str: Expr[String] = sc.parts.mkString("")
2122
val args1: Expr[Seq[Any]] = liftSeq(args)
2223
'{ $str.format($args1: _*) }
2324
}

tests/neg/quote-macro-splice.scala

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,16 @@
11
import scala.quoted._
2+
import scala.quoted.autolift._
23

34
object Test {
45

56
inline def foo1: Int = { // error
67
println()
7-
${ impl(1.toExpr) }
8+
${ impl(1) }
89
}
910

1011
inline def foo2: Int = { // error
11-
${ impl(1.toExpr) }
12-
${ impl(2.toExpr) }
12+
${ impl(1) }
13+
${ impl(2) }
1314
}
1415

1516
inline def foo3: Int = { // error
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import scala.quoted._
2+
import scala.quoted.autolift._
23

34
object Foo {
45
inline def foo(): Int = ${bar(${x})} // error
56
def x: Expr[Int] = '{1}
6-
def bar(i: Int): Expr[Int] = i.toExpr
7+
def bar(i: Int): Expr[Int] = i
78
}

tests/pending/run/tasty-comments/quoted_1.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import scala.quoted._
2+
import scala.quoted.autolift._
23

34
import scala.tasty._
45

@@ -12,7 +13,7 @@ object Macros {
1213

1314
val tree = x.unseal
1415
tree.symbol.comment.map(_.raw) match {
15-
case Some(str) => '{ println(${str.toExpr}) }
16+
case Some(str) => '{ println(${str}) }
1617
case None => '{ println() }
1718
}
1819
}

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,19 @@
11
import scala.quoted._
2+
import scala.quoted.autolift._
23

34
import scala.quoted.Toolbox.Default._
45

56
object Macros {
67

8+
79
inline def assert(expr: => Boolean): Unit =
810
${ assertImpl('expr) }
911

1012
def assertImpl(expr: Expr[Boolean]) =
1113
'{ if !($expr) then throw new AssertionError(s"failed assertion: ${${showExpr(expr)}}") }
1214

13-
def showExpr[T](expr: Expr[T]): Expr[String] = expr.toString.toExpr
15+
16+
def showExpr[T](expr: Expr[T]): Expr[String] = expr.toString
1417

1518
inline def power(inline n: Int, x: Double) = ${ powerCode(n, 'x) }
1619

tests/pos/quote-nested-object/Macro_1.scala

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11

22
import scala.quoted._
3+
import scala.quoted.autolift._
34

45
object Macro {
56

@@ -10,15 +11,15 @@ object Macro {
1011

1112
def plus(n: Int, m: Expr[Int]): Expr[Int] =
1213
if (n == 0) m
13-
else '{ ${n.toExpr} + $m }
14+
else '{ ${n} + $m }
1415

1516
object Implementation2 {
1617

1718
inline def plus(inline n: Int, m: Int): Int = ${ plus(n, 'm) }
1819

1920
def plus(n: Int, m: Expr[Int]): Expr[Int] =
2021
if (n == 0) m
21-
else '{ ${n.toExpr} + $m }
22+
else '{ ${n} + $m }
2223
}
2324
}
2425

tests/run-custom-args/Yretain-trees/tasty-definitions-2/Macro_1.scala

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import scala.quoted._
22
import scala.tasty._
3+
import scala.quoted.autolift._
34

45
object Foo {
56

@@ -9,9 +10,9 @@ object Foo {
910
def inspectBodyImpl(x: Expr[Int])(implicit reflect: Reflection): Expr[String] = {
1011
import reflect._
1112
def definitionString(tree: Tree): Expr[String] = tree.symbol match {
12-
case IsDefDefSymbol(sym) => sym.tree.show.toExpr
13-
case IsValDefSymbol(sym) => sym.tree.show.toExpr
14-
case IsBindSymbol(sym) => sym.tree.show.toExpr
13+
case IsDefDefSymbol(sym) => sym.tree.show
14+
case IsValDefSymbol(sym) => sym.tree.show
15+
case IsBindSymbol(sym) => sym.tree.show
1516
}
1617
x.unseal match {
1718
case Inlined(None, Nil, arg) => definitionString(arg)

tests/run-custom-args/Yretain-trees/tasty-definitions-3/Macro_1.scala

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import scala.quoted._
2+
import scala.quoted.autolift._
23
import scala.tasty._
34

45
object Foo {
@@ -9,9 +10,9 @@ object Foo {
910
def inspectBodyImpl(x: Expr[Int])(implicit reflect: Reflection): Expr[String] = {
1011
import reflect._
1112
def definitionString(tree: Tree): Expr[String] = tree.symbol match {
12-
case IsDefDefSymbol(sym) => sym.tree.show.toExpr
13-
case IsValDefSymbol(sym) => sym.tree.show.toExpr
14-
case IsBindSymbol(sym) => sym.tree.show.toExpr
13+
case IsDefDefSymbol(sym) => sym.tree.show
14+
case IsValDefSymbol(sym) => sym.tree.show
15+
case IsBindSymbol(sym) => sym.tree.show
1516
}
1617
x.unseal match {
1718
case Inlined(None, Nil, arg) => definitionString(arg)

tests/run-custom-args/Yretain-trees/tasty-extractors-owners/quoted_1.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import scala.quoted._
2+
import scala.quoted.autolift._
23

34
import scala.tasty._
45

@@ -42,7 +43,7 @@ object Macros {
4243

4344
val tree = x.unseal
4445
output.traverseTree(tree)
45-
'{print(${buff.result().toExpr})}
46+
'{print(${buff.result()})}
4647
}
4748

4849
}

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import scala.quoted._
2+
import scala.quoted.autolift._
23

34
/**
45
* Port of the strymonas library as described in O. Kiselyov et al., Stream fusion, to completeness (POPL 2017)
@@ -598,7 +599,7 @@ object Test {
598599

599600
def init(k: St => Expr[Unit]): Expr[Unit] = {
600601
Var('{($arr).length}) { n =>
601-
Var(0.toExpr){ i =>
602+
Var(0){ i =>
602603
k((i, n, arr))
603604
}
604605
}

tests/run-with-compiler/quote-impure-by-name/quoted_1.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import scala.quoted._
2+
import scala.quoted.autolift._
23

34
import scala.quoted.Toolbox.Default._
45

@@ -13,6 +14,6 @@ object Index {
1314

1415
def succImpl[K, H, T](prev: Expr[Index[K, T]])(implicit k: Type[K], h: Type[H], t: Type[T]): Expr[Index[K, (H, T)]] = {
1516
val value = s"1 + {${prev.show}}"
16-
'{new Index(${value.toExpr})}
17+
'{new Index(${value})}
1718
}
1819
}

tests/run-with-compiler/quote-inline-function/quoted_1.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import scala.quoted._
2+
import scala.quoted.autolift._
23

34
import scala.quoted.Toolbox.Default._
45

@@ -20,6 +21,6 @@ object Macros {
2021
i += 1
2122
} while (i < j)
2223
}
23-
res.show.toExpr
24+
res.show
2425
}
2526
}

0 commit comments

Comments
 (0)