Skip to content

Commit b37d8e3

Browse files
committed
Fix #4846: Allow transparent parameters at any stage
Stop checking and using capture tranformation for transparent parameters
1 parent 05c5ba1 commit b37d8e3

File tree

2 files changed

+19
-48
lines changed

2 files changed

+19
-48
lines changed

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

Lines changed: 13 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,7 @@ class ReifyQuotes extends MacroTransformWithImplicits {
225225
def levelOK(sym: Symbol)(implicit ctx: Context): Boolean = levelOf.get(sym) match {
226226
case Some(l) =>
227227
l == level ||
228-
l == 0 && level == -1 && isStageNegOneValue(sym)
228+
level == -1 && sym == defn.TastyTopLevelSplice_tastyContext
229229
case None =>
230230
!sym.is(Param) || levelOK(sym.owner)
231231
}
@@ -359,18 +359,12 @@ class ReifyQuotes extends MacroTransformWithImplicits {
359359
}
360360
else body match {
361361
case body: RefTree if isCaptured(body.symbol, level + 1) =>
362-
if (isStageNegOneValue(body.symbol)) {
363-
// Optimization: avoid the full conversion when capturing inlined `x`
364-
// in '{ x } to '{ x$1.toExpr.unary_~ } and go directly to `x$1.toExpr`
365-
liftInlineParamValue(capturers(body.symbol)(body))
366-
} else {
367-
// Optimization: avoid the full conversion when capturing `x`
368-
// in '{ x } to '{ x$1.unary_~ } and go directly to `x$1`
369-
capturers(body.symbol)(body)
370-
}
362+
// Optimization: avoid the full conversion when capturing `x`
363+
// in '{ x } to '{ x$1.unary_~ } and go directly to `x$1`
364+
capturers(body.symbol)(body)
371365
case _=>
372366
val (body1, splices) = nested(isQuote = true).split(body)
373-
if (level >= 0) pickledQuote(body1, splices, body.tpe, isType).withPos(quote.pos)
367+
if (level == 0 && !ctx.owner.ownersIterator.exists(_.isTransparentMethod)) pickledQuote(body1, splices, body.tpe, isType).withPos(quote.pos)
374368
else {
375369
// In top-level splice in an transparent def. Keep the tree as it is, it will be transformed at inline site.
376370
body
@@ -464,7 +458,6 @@ class ReifyQuotes extends MacroTransformWithImplicits {
464458
val tpw = tree.tpe.widen
465459
val argTpe =
466460
if (tree.isType) defn.QuotedTypeType.appliedTo(tpw)
467-
else if (isStageNegOneValue(tree.symbol)) tpw
468461
else defn.QuotedExprType.appliedTo(tpw)
469462
val selectArg = arg.select(nme.apply).appliedTo(Literal(Constant(i))).asInstance(argTpe)
470463
val capturedArg = SyntheticValDef(UniqueName.fresh(tree.symbol.name.toTermName).toTermName, selectArg)
@@ -489,21 +482,17 @@ class ReifyQuotes extends MacroTransformWithImplicits {
489482
val captured = mutable.LinkedHashMap.empty[Symbol, Tree]
490483
val captured2 = capturer(captured)
491484

492-
outer.enteredSyms.foreach(sym => capturers.put(sym, captured2))
485+
outer.enteredSyms.foreach(sym => if (!sym.is(Transparent)) capturers.put(sym, captured2))
493486

494487
val tree2 = transform(tree)
495488
capturers --= outer.enteredSyms
496489

497490
seq(captured.result().valuesIterator.toList, tree2)
498491
}
499492

500-
/** Returns true if this tree will be captured by `makeLambda` */
501-
private def isCaptured(sym: Symbol, level: Int)(implicit ctx: Context): Boolean = {
502-
// Check phase consistency and presence of capturer
503-
( (level == 1 && levelOf.get(sym).contains(1)) ||
504-
(level == 0 && isStageNegOneValue(sym))
505-
) && capturers.contains(sym)
506-
}
493+
/** Returns true if this tree will be captured by `makeLambda`. Checks phase consistency and presence of capturer. */
494+
private def isCaptured(sym: Symbol, level: Int)(implicit ctx: Context): Boolean =
495+
level == 1 && levelOf.get(sym).contains(1) && capturers.contains(sym) //
507496

508497
/** Transform `tree` and return the resulting tree and all `embedded` quotes
509498
* or splices as a pair, after performing the `addTags` transform.
@@ -539,13 +528,11 @@ class ReifyQuotes extends MacroTransformWithImplicits {
539528
splice(ref(splicedType).select(tpnme.UNARY_~).withPos(tree.pos))
540529
case tree: Select if tree.symbol.isSplice =>
541530
splice(tree)
531+
case tree: RefTree if tree.symbol.is(Transparent) && tree.symbol.is(Param) =>
532+
tree
542533
case tree: RefTree if isCaptured(tree.symbol, level) =>
543-
val capturer = capturers(tree.symbol)
544-
def captureAndSplice(t: Tree) =
545-
splice(t.select(if (tree.isTerm) nme.UNARY_~ else tpnme.UNARY_~))
546-
if (!isStageNegOneValue(tree.symbol)) captureAndSplice(capturer(tree))
547-
else if (level == 0) capturer(tree)
548-
else captureAndSplice(liftInlineParamValue(capturer(tree)))
534+
val t = capturers(tree.symbol).apply(tree)
535+
splice(t.select(if (tree.isTerm) nme.UNARY_~ else tpnme.UNARY_~))
549536
case Block(stats, _) =>
550537
val last = enteredSyms
551538
stats.foreach(markDef)
@@ -589,28 +576,6 @@ class ReifyQuotes extends MacroTransformWithImplicits {
589576
}
590577
}
591578

592-
/** Takes a reference to an transparent parameter `tree` and lifts it to an Expr */
593-
private def liftInlineParamValue(tree: Tree)(implicit ctx: Context): Tree = {
594-
val tpSym = tree.tpe.widenDealias.classSymbol
595-
596-
val lifter =
597-
if (tpSym eq defn.BooleanClass) defn.QuotedLiftable_BooleanIsLiftable
598-
else if (tpSym eq defn.ByteClass) defn.QuotedLiftable_ByteIsLiftable
599-
else if (tpSym eq defn.CharClass) defn.QuotedLiftable_CharIsLiftable
600-
else if (tpSym eq defn.ShortClass) defn.QuotedLiftable_ShortIsLiftable
601-
else if (tpSym eq defn.IntClass) defn.QuotedLiftable_IntIsLiftable
602-
else if (tpSym eq defn.LongClass) defn.QuotedLiftable_LongIsLiftable
603-
else if (tpSym eq defn.FloatClass) defn.QuotedLiftable_FloatIsLiftable
604-
else if (tpSym eq defn.DoubleClass) defn.QuotedLiftable_DoubleIsLiftable
605-
else defn.QuotedLiftable_StringIsLiftable
606-
607-
ref(lifter).select("toExpr".toTermName).appliedTo(tree)
608-
}
609-
610-
private def isStageNegOneValue(sym: Symbol)(implicit ctx: Context): Boolean =
611-
(sym.is(Transparent) && sym.owner.is(Transparent) && !defn.isFunctionType(sym.info)) ||
612-
sym == defn.TastyTopLevelSplice_tastyContext // intrinsic value at stage 0
613-
614579
private def liftList(list: List[Tree], tpe: Type)(implicit ctx: Context): Tree = {
615580
list.foldRight[Tree](ref(defn.NilModule)) { (x, acc) =>
616581
acc.select("::".toTermName).appliedToType(tpe).appliedTo(x)

tests/pos/i4846.scala

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import scala.quoted._
2+
3+
object Test {
4+
transparent def foo(transparent x: Int): Int = ~fooImpl(x, '(x), '( '(x) ), '( '( '(x) ) ))
5+
def fooImpl(a: Int, b: Expr[Int], c: Expr[Expr[Int]], d: Expr[Expr[Expr[Int]]]): Expr[Int] = ???
6+
}

0 commit comments

Comments
 (0)