Skip to content

Commit 8b24a74

Browse files
committed
Only allow access to inline args at level 0
If it is needed at level 1 it can be explicitly lifted. This simplifies the rules that users need to know and the implementation of the phase.
1 parent 4821e2b commit 8b24a74

File tree

3 files changed

+17
-30
lines changed

3 files changed

+17
-30
lines changed

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

Lines changed: 7 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,7 @@ class ReifyQuotes extends MacroTransformWithImplicits with InfoTransformer {
236236
case tree: DefTree =>
237237
val sym = tree.symbol
238238
if ((sym.isClass || !sym.maybeOwner.isType) && !levelOf.contains(sym)) {
239-
levelOf(sym) = level
239+
levelOf(sym) = if (sym.is(Inline)) level - 1 else level
240240
enteredSyms = sym :: enteredSyms
241241
}
242242
case _ =>
@@ -250,7 +250,7 @@ class ReifyQuotes extends MacroTransformWithImplicits with InfoTransformer {
250250
def levelOK(sym: Symbol)(implicit ctx: Context): Boolean = levelOf.get(sym) match {
251251
case Some(l) =>
252252
l == level ||
253-
l == 1 && level == 0 && isStage0Value(sym)
253+
(0 == level && isStage0Value(sym))
254254
case None =>
255255
!sym.is(Param) || levelOK(sym.owner)
256256
}
@@ -384,15 +384,9 @@ class ReifyQuotes extends MacroTransformWithImplicits with InfoTransformer {
384384
}
385385
else body match {
386386
case body: RefTree if isCaptured(body.symbol, level + 1) =>
387-
if (isStage0Value(body.symbol)) {
388-
// Optimization: avoid the full conversion when capturing inlined `x`
389-
// in '{ x } to '{ x$1.toExpr.unary_~ } and go directly to `x$1.toExpr`
390-
liftValue(capturers(body.symbol)(body))
391-
} else {
392-
// Optimization: avoid the full conversion when capturing `x`
393-
// in '{ x } to '{ x$1.unary_~ } and go directly to `x$1`
394-
capturers(body.symbol)(body)
395-
}
387+
// Optimization: avoid the full conversion when capturing `x`
388+
// in '{ x } to '{ x$1.unary_~ } and go directly to `x$1`
389+
capturers(body.symbol)(body)
396390
case _=>
397391
val (body1, splices) = nested(isQuote = true).split(body)
398392
pickledQuote(body1, splices, body.tpe, isType).withPos(quote.pos)
@@ -575,9 +569,8 @@ class ReifyQuotes extends MacroTransformWithImplicits with InfoTransformer {
575569
val capturer = capturers(tree.symbol)
576570
def captureAndSplice(t: Tree) =
577571
splice(t.select(if (tree.isTerm) nme.UNARY_~ else tpnme.UNARY_~))
578-
if (!isStage0Value(tree.symbol)) captureAndSplice(capturer(tree))
579-
else if (level == 0) capturer(tree)
580-
else captureAndSplice(liftValue(capturer(tree)))
572+
if (level == 0 && isStage0Value(tree.symbol)) capturer(tree)
573+
else captureAndSplice(capturer(tree))
581574
case Block(stats, _) =>
582575
val last = enteredSyms
583576
stats.foreach(markDef)
@@ -632,21 +625,6 @@ class ReifyQuotes extends MacroTransformWithImplicits with InfoTransformer {
632625
}
633626
}
634627

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-
}
648-
}
649-
650628
private def isStage0Value(sym: Symbol)(implicit ctx: Context): Boolean =
651629
(sym.is(Inline) && sym.owner.is(Macro) && !defn.isFunctionType(sym.info)) ||
652630
sym == defn.TastyTopLevelSplice_compilationTopLevelSplice // intrinsic value at stage 0

docs/docs/reference/principled-meta-programming.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -400,7 +400,7 @@ as follows:
400400
function) of type Boolean, Byte, Short, Int, Long, Float, Double,
401401
Char or String, it can be accessed in all contexts where the number
402402
of splices minus the number of quotes between use and definition
403-
is either 0 or 1.
403+
is 0.
404404

405405
### Relationship with Staging
406406

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
object Test {
2+
3+
inline def foo(inline x: Int): Int = ~{
4+
if (x == 1) '(3)
5+
else '(x) // error
6+
}
7+
8+
}
9+

0 commit comments

Comments
 (0)