Skip to content

Commit 2a2a4fd

Browse files
committed
Fix #5144: Avoid Expr of method type
1 parent 8ce1fcc commit 2a2a4fd

File tree

6 files changed

+62
-8
lines changed

6 files changed

+62
-8
lines changed

compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ import config.Config
2020

2121
object TreePickler {
2222

23-
case class Hole(idx: Int, args: List[tpd.Tree]) extends tpd.TermTree {
23+
case class Hole(idx: Int, args: List[tpd.Tree]) extends tpd.Tree {
2424
override def fallbackToText(printer: Printer): Text =
2525
s"[[$idx|" ~~ printer.toTextGlobal(args, ", ") ~~ "]]"
2626
}

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

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -123,13 +123,13 @@ class ReifyQuotes extends MacroTransformWithImplicits {
123123
* @param rctx the contex in the destination lifted lambda
124124
*/
125125
private class Reifier(inQuote: Boolean, val outer: Reifier, val level: Int, levels: LevelInfo,
126-
val embedded: mutable.ListBuffer[Tree], val rctx: Context) extends ImplicitsTransformer {
126+
val embedded: mutable.ListBuffer[(Symbol, Tree)], val rctx: Context) extends ImplicitsTransformer {
127127
import levels._
128128
assert(level >= -1)
129129

130130
/** A nested reifier for a quote (if `isQuote = true`) or a splice (if not) */
131131
def nested(isQuote: Boolean)(implicit ctx: Context): Reifier = {
132-
val nestedEmbedded = if (level > 1 || (level == 1 && isQuote)) embedded else new mutable.ListBuffer[Tree]
132+
val nestedEmbedded = if (level > 1 || (level == 1 && isQuote)) embedded else new mutable.ListBuffer[(Symbol, Tree)]
133133
new Reifier(isQuote, this, if (isQuote) level + 1 else level - 1, levels, nestedEmbedded, ctx)
134134
}
135135

@@ -423,7 +423,12 @@ class ReifyQuotes extends MacroTransformWithImplicits {
423423
}
424424
else if (level == 1) {
425425
val (body1, quotes) = nested(isQuote = false).split(splice.qualifier)
426-
makeHole(body1, quotes, splice.tpe).withPos(splice.pos)
426+
// TODO improve code
427+
val tpe = outer.embedded.toList.find(_._1 == splice.qualifier.symbol) match {
428+
case Some((_, tree)) => tree.tpe.widen
429+
case _ => splice.tpe
430+
}
431+
makeHole(body1, quotes, tpe).withPos(splice.pos)
427432
}
428433
else if (enclosingInlineds.nonEmpty) { // level 0 in an inlined call
429434
val spliceCtx = ctx.outer // drop the last `inlineContext`
@@ -478,14 +483,18 @@ class ReifyQuotes extends MacroTransformWithImplicits {
478483
(captured: mutable.Map[Symbol, Tree]) => {
479484
(tree: Tree) => {
480485
def newCapture = {
481-
val tpw = tree.tpe.widen
486+
val tpw = tree.tpe.widen match {
487+
case tpw: MethodicType => tpw.toFunctionType()
488+
case tpw => tpw
489+
}
490+
assert(tpw.isInstanceOf[ValueType])
482491
val argTpe =
483492
if (tree.isType) defn.QuotedTypeType.appliedTo(tpw)
484493
else defn.QuotedExprType.appliedTo(tpw)
485494
val selectArg = arg.select(nme.apply).appliedTo(Literal(Constant(i))).asInstance(argTpe)
486495
val capturedArg = SyntheticValDef(UniqueName.fresh(tree.symbol.name.toTermName).toTermName, selectArg)
487496
i += 1
488-
embedded += tree
497+
embedded += Tuple2(capturedArg.symbol, tree)
489498
captured.put(tree.symbol, capturedArg)
490499
capturedArg
491500
}
@@ -522,15 +531,15 @@ class ReifyQuotes extends MacroTransformWithImplicits {
522531
*/
523532
private def split(tree: Tree)(implicit ctx: Context): (Tree, List[Tree]) = {
524533
val tree1 = if (inQuote) addTags(transform(tree)) else makeLambda(tree)
525-
(tree1, embedded.toList)
534+
(tree1, embedded.toList.map(_._2))
526535
}
527536

528537
/** Register `body` as an `embedded` quote or splice
529538
* and return a hole with `splices` as arguments and the given type `tpe`.
530539
*/
531540
private def makeHole(body: Tree, splices: List[Tree], tpe: Type)(implicit ctx: Context): Hole = {
532541
val idx = embedded.length
533-
embedded += body
542+
embedded += Tuple2(NoSymbol, body)
534543
Hole(idx, splices).withType(tpe).asInstanceOf[Hole]
535544
}
536545

tests/run-with-compiler/i5144.check

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
def f(x: scala.Int): scala.Int = ((x: scala.Int) => f(x)).apply(42)
3+
()
4+
}

tests/run-with-compiler/i5144.scala

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import scala.quoted._
2+
3+
object Test {
4+
implicit val toolbox: scala.quoted.Toolbox = scala.quoted.Toolbox.make
5+
6+
def eval1(ff: Expr[Int => Int]): Expr[Int] = '((~ff)(42))
7+
8+
def peval1(): Expr[Unit] = '{
9+
def f(x: Int): Int = ~eval1('(f))
10+
}
11+
12+
def main(args: Array[String]): Unit = {
13+
val p = peval1()
14+
println(p.show)
15+
}
16+
17+
}

tests/run-with-compiler/i5144b.check

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
def f(x: scala.Int): scala.Int = {
3+
val x$1: scala.Int = 42
4+
f(x$1)
5+
}
6+
()
7+
}

tests/run-with-compiler/i5144b.scala

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import scala.quoted._
2+
3+
object Test {
4+
implicit val toolbox: scala.quoted.Toolbox = scala.quoted.Toolbox.make
5+
6+
def eval1(ff: Expr[Int => Int]): Expr[Int] = ff('(42))
7+
8+
def peval1(): Expr[Unit] = '{
9+
def f(x: Int): Int = ~eval1('(f))
10+
}
11+
12+
def main(args: Array[String]): Unit = {
13+
val p = peval1()
14+
println(p.show)
15+
}
16+
17+
}

0 commit comments

Comments
 (0)