Skip to content

Commit c8fcd1e

Browse files
committed
Fix inline parameters lifted for 0 to 1
In theory the inline parameters are available in level 1, but we can access it "unlifted" as a value in level 0. To only pass the parameter once it is passed as a value and lifted using the standard lifter for the values. Unsing lifter is just an implementation detail and should not be observable by the user. The issue was that the lifter used could be replaced or unimported which yield unexpected error messages.
1 parent 64bd0fe commit c8fcd1e

File tree

5 files changed

+49
-15
lines changed

5 files changed

+49
-15
lines changed

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

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -654,6 +654,19 @@ class Definitions {
654654
lazy val QuotedType_applyR = QuotedTypeModule.requiredMethodRef(nme.apply)
655655
def QuotedType_apply(implicit ctx: Context) = QuotedType_applyR.symbol
656656

657+
lazy val QuotedLiftableModule = ctx.requiredModule("scala.quoted.Liftable")
658+
def QuotedLiftableModuleClass(implicit ctx: Context) = QuotedLiftableModule.asClass
659+
660+
def QuotedLiftable_BooleanIsLiftable = QuotedLiftableModule.requiredMethodRef("BooleanIsLiftable")
661+
def QuotedLiftable_ByteLiftable = QuotedLiftableModule.requiredMethodRef("ByteLiftable")
662+
def QuotedLiftable_CharIsLiftable = QuotedLiftableModule.requiredMethodRef("CharIsLiftable")
663+
def QuotedLiftable_ShortIsLiftable = QuotedLiftableModule.requiredMethodRef("ShortIsLiftable")
664+
def QuotedLiftable_IntIsLiftable = QuotedLiftableModule.requiredMethodRef("IntIsLiftable")
665+
def QuotedLiftable_LongIsLiftable = QuotedLiftableModule.requiredMethodRef("LongIsLiftable")
666+
def QuotedLiftable_FloatIsLiftable = QuotedLiftableModule.requiredMethodRef("FloatIsLiftable")
667+
def QuotedLiftable_DoubleIsLiftable = QuotedLiftableModule.requiredMethodRef("DoubleIsLiftable")
668+
def QuotedLiftable_StringIsLiftable = QuotedLiftableModule.requiredMethodRef("StringIsLiftable")
669+
657670
lazy val QuotedLiftableType = ctx.requiredClassRef("scala.quoted.Liftable")
658671
def QuotedLiftableClass(implicit ctx: Context) = QuotedLiftableType.symbol.asClass
659672

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

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -387,7 +387,7 @@ class ReifyQuotes extends MacroTransformWithImplicits with InfoTransformer {
387387
if (isStage0Value(body.symbol)) {
388388
// Optimization: avoid the full conversion when capturing inlined `x`
389389
// in '{ x } to '{ x$1.toExpr.unary_~ } and go directly to `x$1.toExpr`
390-
liftValue(capturers(body.symbol)(body))
390+
liftInlineParamValue(capturers(body.symbol)(body))
391391
} else {
392392
// Optimization: avoid the full conversion when capturing `x`
393393
// in '{ x } to '{ x$1.unary_~ } and go directly to `x$1`
@@ -577,7 +577,7 @@ class ReifyQuotes extends MacroTransformWithImplicits with InfoTransformer {
577577
splice(t.select(if (tree.isTerm) nme.UNARY_~ else tpnme.UNARY_~))
578578
if (!isStage0Value(tree.symbol)) captureAndSplice(capturer(tree))
579579
else if (level == 0) capturer(tree)
580-
else captureAndSplice(liftValue(capturer(tree)))
580+
else captureAndSplice(liftInlineParamValue(capturer(tree)))
581581
case Block(stats, _) =>
582582
val last = enteredSyms
583583
stats.foreach(markDef)
@@ -632,19 +632,22 @@ class ReifyQuotes extends MacroTransformWithImplicits with InfoTransformer {
632632
}
633633
}
634634

635-
private def liftValue(tree: Tree)(implicit ctx: Context): Tree = {
636-
val reqType = defn.QuotedLiftableType.appliedTo(tree.tpe.widen)
637-
val liftable = ctx.typer.inferImplicitArg(reqType, tree.pos)
638-
liftable.tpe match {
639-
case fail: SearchFailureType =>
640-
ctx.error(i"""
641-
|
642-
| The access would be accepted with the right Liftable, but
643-
| ${ctx.typer.missingArgMsg(liftable, reqType, "")}""")
644-
EmptyTree
645-
case _ =>
646-
liftable.select("toExpr".toTermName).appliedTo(tree)
647-
}
635+
/** Takes a reference to an inline parameter `tree` and lifts it to an Expr */
636+
private def liftInlineParamValue(tree: Tree)(implicit ctx: Context): Tree = {
637+
val tpSym = tree.tpe.widenDealias.classSymbol
638+
639+
val lifter =
640+
if (tpSym eq defn.BooleanClass) defn.QuotedLiftable_BooleanIsLiftable
641+
else if (tpSym eq defn.ByteClass) defn.QuotedLiftable_ByteLiftable
642+
else if (tpSym eq defn.CharClass) defn.QuotedLiftable_CharIsLiftable
643+
else if (tpSym eq defn.ShortClass) defn.QuotedLiftable_ShortIsLiftable
644+
else if (tpSym eq defn.IntClass) defn.QuotedLiftable_IntIsLiftable
645+
else if (tpSym eq defn.LongClass) defn.QuotedLiftable_LongIsLiftable
646+
else if (tpSym eq defn.FloatClass) defn.QuotedLiftable_FloatIsLiftable
647+
else if (tpSym eq defn.DoubleClass) defn.QuotedLiftable_DoubleIsLiftable
648+
else defn.QuotedLiftable_StringIsLiftable
649+
650+
ref(lifter).select("toExpr".toTermName).appliedTo(tree)
648651
}
649652

650653
private def isStage0Value(sym: Symbol)(implicit ctx: Context): Boolean =
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import scala.quoted.Expr
2+
object Macro {
3+
inline def foo(inline n: Int): Int = ~{
4+
import quoted.Liftable.{IntIsLiftable => _}
5+
'(n)
6+
}
7+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
2+
object App {
3+
Macro.foo(3)
4+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import scala.quoted.Expr
2+
object Macro {
3+
inline def foo(inline n: Int): Int = ~{
4+
import quoted.Liftable.{IntIsLiftable => _}
5+
'(n)
6+
}
7+
}

0 commit comments

Comments
 (0)