Skip to content

Commit 2a85106

Browse files
Merge pull request #4012 from dotty-staging/fix-#3912
Fix #3912: Account for units and blocks in inline and macros
2 parents b24f80d + 57afac6 commit 2a85106

File tree

8 files changed

+69
-4
lines changed

8 files changed

+69
-4
lines changed

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

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -321,16 +321,22 @@ class ReifyQuotes extends MacroTransformWithImplicits {
321321
val last = enteredSyms
322322
stats.foreach(markDef)
323323
mapOverTree(last)
324-
case Inlined(call, bindings, expansion @ Select(body, name)) if expansion.symbol.isSplice =>
324+
325+
case Inlined(call, bindings, InlineSplice(expansion @ Select(body, name))) =>
325326
// To maintain phase consistency, we move the binding of the this parameter into the spliced code
326327
val (splicedBindings, stagedBindings) = bindings.partition {
327328
case vdef: ValDef => vdef.symbol.is(Synthetic) // Assume that only _this bindings are tagged with Synthetic
328329
case _ => false
329330
}
331+
330332
val tree1 =
331333
if (level == 0) cpy.Inlined(tree)(call, stagedBindings, Splicer.splice(seq(splicedBindings, body)))
332334
else seq(stagedBindings, cpy.Select(expansion)(cpy.Inlined(tree)(call, splicedBindings, body), name))
333-
transform(tree1)
335+
val tree2 = transform(tree1)
336+
337+
// due to value-discarding which converts an { e } into { e; () })
338+
if (tree.tpe =:= defn.UnitType) Block(tree2 :: Nil, Literal(Constant(())))
339+
else tree2
334340
case _: Import =>
335341
tree
336342
case tree: DefDef if tree.symbol.is(Macro) && level == 0 =>
@@ -343,5 +349,20 @@ class ReifyQuotes extends MacroTransformWithImplicits {
343349
checkLevel(mapOverTree(enteredSyms))
344350
}
345351
}
352+
353+
/** InlineSplice is used to detect cases where the expansion
354+
* consists of a (possibly multiple & nested) block or a sole expression.
355+
*/
356+
object InlineSplice {
357+
def unapply(tree: Tree)(implicit ctx: Context): Option[Select] = {
358+
tree match {
359+
case expansion: Select if expansion.symbol.isSplice =>
360+
Some(expansion)
361+
case Block(List(stat), Literal(Constant(()))) => unapply(stat)
362+
case Block(Nil, expr) => unapply(expr)
363+
case _ => None
364+
}
365+
}
366+
}
346367
}
347368
}

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,13 @@ import dotty.tools.dotc.core.Contexts._
66
import dotty.tools.dotc.core.quoted._
77
import dotty.tools.dotc.interpreter._
88

9-
/** Utility class to slice quoted expressions */
9+
/** Utility class to splice quoted expressions */
1010
object Splicer {
1111
import tpd._
1212

1313
/** Splice the Tree for a Quoted expression. `~'(xyz)` becomes `xyz`
1414
* and for `~xyz` the tree of `xyz` is interpreted for which the
15-
* resulting expression is return as a `Tree`
15+
* resulting expression is returned as a `Tree`
1616
*/
1717
def splice(tree: Tree)(implicit ctx: Context): Tree = tree match {
1818
case Quoted(quotedTree) => quotedTree

tests/pos/i3912-1/i3912_1.scala

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

tests/pos/i3912-1/i3912_2.scala

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import scala.quoted._
2+
import Macros._
3+
4+
class Test {
5+
val a: Unit = foo()
6+
7+
}

tests/pos/i3912-2/i3912_1.scala

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

tests/pos/i3912-2/i3912_2.scala

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import scala.quoted._
2+
import Macros._
3+
4+
class Test {
5+
val a2: Unit = foo2()
6+
}

tests/pos/i3912-3/i3912_1.scala

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

tests/pos/i3912-3/i3912_2.scala

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import scala.quoted._
2+
import Macros._
3+
4+
class Test {
5+
val a3: Unit = foo3()
6+
}

0 commit comments

Comments
 (0)