Skip to content

Commit 6f6816d

Browse files
Merge pull request #4458 from dotty-staging/fix-#4455
Fix #4455: Lift inlined values when quoted
2 parents 48a2f4b + 25f9bbd commit 6f6816d

File tree

5 files changed

+54
-6
lines changed

5 files changed

+54
-6
lines changed

compiler/src/dotty/tools/dotc/core/Definitions.scala

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -660,6 +660,9 @@ class Definitions {
660660
lazy val QuotedType_applyR = QuotedTypeModule.requiredMethodRef(nme.apply)
661661
def QuotedType_apply(implicit ctx: Context) = QuotedType_applyR.symbol
662662

663+
lazy val QuotedLiftableType = ctx.requiredClassRef("scala.quoted.Liftable")
664+
def QuotedLiftableClass(implicit ctx: Context) = QuotedLiftableType.symbol.asClass
665+
663666
def Unpickler_unpickleExpr = ctx.requiredMethod("scala.runtime.quoted.Unpickler.unpickleExpr")
664667
def Unpickler_liftedExpr = ctx.requiredMethod("scala.runtime.quoted.Unpickler.liftedExpr")
665668
def Unpickler_unpickleType = ctx.requiredMethod("scala.runtime.quoted.Unpickler.unpickleType")

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

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ import dotty.tools.dotc.core.quoted._
7373
* ...
7474
* val y1$1 = args(1).asInstanceOf[Expr[Y]]
7575
* ...
76-
* { ... T1$1.unary_~ ... x ... '(y1$1.unary_~) ... }
76+
* { ... x1$1 .... '{ ... T1$1.unary_~ ... x1$1.toExpr.unary_~ ... y1$1.unary_~ ... } ... }
7777
* }
7878
* ```
7979
* Note: the parameters of `foo` are kept for simple overloading resolution but they are not used in the body of `foo`.
@@ -375,9 +375,15 @@ class ReifyQuotes extends MacroTransformWithImplicits with InfoTransformer {
375375
}
376376
else body match {
377377
case body: RefTree if isCaptured(body, level + 1) =>
378-
// Optimization: avoid the full conversion when capturing `x`
379-
// in '{ x } to '{ x$1.unary_~ } and go directly to `x$1`
380-
capturers(body.symbol)(body)
378+
if (body.symbol.is(Inline)) {
379+
// Optimization: avoid the full conversion when capturing inlined `x`
380+
// in '{ x } to '{ x$1.toExpr.unary_~ } and go directly to `x$1.toExpr`
381+
liftValue(capturers(body.symbol)(body))
382+
} else {
383+
// Optimization: avoid the full conversion when capturing `x`
384+
// in '{ x } to '{ x$1.unary_~ } and go directly to `x$1`
385+
capturers(body.symbol)(body)
386+
}
381387
case _=>
382388
val (body1, splices) = nested(isQuote = true).split(body)
383389
pickledQuote(body1, splices, isType).withPos(quote.pos)
@@ -546,8 +552,11 @@ class ReifyQuotes extends MacroTransformWithImplicits with InfoTransformer {
546552
splice(tree)
547553
case tree: RefTree if isCaptured(tree, level) =>
548554
val capturer = capturers(tree.symbol)
549-
if (tree.symbol.is(Inline)) capturer(tree)
550-
else splice(capturer(tree).select(if (tree.isTerm) nme.UNARY_~ else tpnme.UNARY_~))
555+
def captureAndSplice(t: Tree) =
556+
splice(t.select(if (tree.isTerm) nme.UNARY_~ else tpnme.UNARY_~))
557+
if (tree.symbol.is(Inline) && level == 0) capturer(tree)
558+
else if (tree.symbol.is(Inline)) captureAndSplice(liftValue(capturer(tree)))
559+
else captureAndSplice(capturer(tree))
551560
case Block(stats, _) =>
552561
val last = enteredSyms
553562
stats.foreach(markDef)
@@ -601,6 +610,21 @@ class ReifyQuotes extends MacroTransformWithImplicits with InfoTransformer {
601610
}
602611
}
603612

613+
private def liftValue(tree: Tree)(implicit ctx: Context): Tree = {
614+
val reqType = defn.QuotedLiftableType.appliedTo(tree.tpe.widen)
615+
val liftable = ctx.typer.inferImplicitArg(reqType, tree.pos)
616+
liftable.tpe match {
617+
case fail: SearchFailureType =>
618+
ctx.error(i"""
619+
|
620+
| The access would be accepted with the right Liftable, but
621+
| ${ctx.typer.missingArgMsg(liftable, reqType, "")}""")
622+
EmptyTree
623+
case _ =>
624+
liftable.select("toExpr".toTermName).appliedTo(tree)
625+
}
626+
}
627+
604628
private def liftList(list: List[Tree], tpe: Type)(implicit ctx: Context): Tree = {
605629
list.foldRight[Tree](ref(defn.NilModule)) { (x, acc) =>
606630
acc.select("::".toTermName).appliedToType(tpe).appliedTo(x)

tests/run/i4455.check

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

tests/run/i4455/Macro_1.scala

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import scala.quoted._
2+
object Macros {
3+
inline def foo(inline i: Int): Int = ~bar('(i))
4+
5+
inline def foo2(inline i: Int): Int = ~bar('(i + 1))
6+
7+
def bar(x: Expr[Int]): Expr[Int] = x
8+
}

tests/run/i4455/Test_2.scala

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import Macros._
2+
object Test {
3+
def main(args: Array[String]): Unit = {
4+
println(foo(1))
5+
println(foo(3))
6+
println(foo2(2))
7+
println(foo2(4))
8+
}
9+
}

0 commit comments

Comments
 (0)