diff --git a/compiler/src/dotty/tools/dotc/transform/ReifyQuotes.scala b/compiler/src/dotty/tools/dotc/transform/ReifyQuotes.scala index cb6dc2999e3f..163c3db800b0 100644 --- a/compiler/src/dotty/tools/dotc/transform/ReifyQuotes.scala +++ b/compiler/src/dotty/tools/dotc/transform/ReifyQuotes.scala @@ -321,16 +321,22 @@ class ReifyQuotes extends MacroTransformWithImplicits { val last = enteredSyms stats.foreach(markDef) mapOverTree(last) - case Inlined(call, bindings, expansion @ Select(body, name)) if expansion.symbol.isSplice => + + case Inlined(call, bindings, InlineSplice(expansion @ Select(body, name))) => // To maintain phase consistency, we move the binding of the this parameter into the spliced code val (splicedBindings, stagedBindings) = bindings.partition { case vdef: ValDef => vdef.symbol.is(Synthetic) // Assume that only _this bindings are tagged with Synthetic case _ => false } + val tree1 = if (level == 0) cpy.Inlined(tree)(call, stagedBindings, Splicer.splice(seq(splicedBindings, body))) else seq(stagedBindings, cpy.Select(expansion)(cpy.Inlined(tree)(call, splicedBindings, body), name)) - transform(tree1) + val tree2 = transform(tree1) + + // due to value-discarding which converts an { e } into { e; () }) + if (tree.tpe =:= defn.UnitType) Block(tree2 :: Nil, Literal(Constant(()))) + else tree2 case _: Import => tree case tree: DefDef if tree.symbol.is(Macro) && level == 0 => @@ -343,5 +349,20 @@ class ReifyQuotes extends MacroTransformWithImplicits { checkLevel(mapOverTree(enteredSyms)) } } + + /** InlineSplice is used to detect cases where the expansion + * consists of a (possibly multiple & nested) block or a sole expression. + */ + object InlineSplice { + def unapply(tree: Tree)(implicit ctx: Context): Option[Select] = { + tree match { + case expansion: Select if expansion.symbol.isSplice => + Some(expansion) + case Block(List(stat), Literal(Constant(()))) => unapply(stat) + case Block(Nil, expr) => unapply(expr) + case _ => None + } + } + } } } \ No newline at end of file diff --git a/compiler/src/dotty/tools/dotc/transform/Splicer.scala b/compiler/src/dotty/tools/dotc/transform/Splicer.scala index 11daaecd1965..2003dba73999 100644 --- a/compiler/src/dotty/tools/dotc/transform/Splicer.scala +++ b/compiler/src/dotty/tools/dotc/transform/Splicer.scala @@ -6,13 +6,13 @@ import dotty.tools.dotc.core.Contexts._ import dotty.tools.dotc.core.quoted._ import dotty.tools.dotc.interpreter._ -/** Utility class to slice quoted expressions */ +/** Utility class to splice quoted expressions */ object Splicer { import tpd._ /** Splice the Tree for a Quoted expression. `~'(xyz)` becomes `xyz` * and for `~xyz` the tree of `xyz` is interpreted for which the - * resulting expression is return as a `Tree` + * resulting expression is returned as a `Tree` */ def splice(tree: Tree)(implicit ctx: Context): Tree = tree match { case Quoted(quotedTree) => quotedTree diff --git a/tests/pos/i3912-1/i3912_1.scala b/tests/pos/i3912-1/i3912_1.scala new file mode 100644 index 000000000000..80faaf976743 --- /dev/null +++ b/tests/pos/i3912-1/i3912_1.scala @@ -0,0 +1,7 @@ +import scala.quoted._ + +object Macros { + inline def foo(): Int = { ~impl() } + + def impl(): Expr[Int] = '(1) +} \ No newline at end of file diff --git a/tests/pos/i3912-1/i3912_2.scala b/tests/pos/i3912-1/i3912_2.scala new file mode 100644 index 000000000000..d933fef2935c --- /dev/null +++ b/tests/pos/i3912-1/i3912_2.scala @@ -0,0 +1,7 @@ +import scala.quoted._ +import Macros._ + +class Test { + val a: Unit = foo() + +} \ No newline at end of file diff --git a/tests/pos/i3912-2/i3912_1.scala b/tests/pos/i3912-2/i3912_1.scala new file mode 100644 index 000000000000..e3d1ba91df37 --- /dev/null +++ b/tests/pos/i3912-2/i3912_1.scala @@ -0,0 +1,7 @@ +import scala.quoted._ + +object Macros { + inline def foo2(): Unit = ~impl() + + def impl(): Expr[Int] = '(1) +} \ No newline at end of file diff --git a/tests/pos/i3912-2/i3912_2.scala b/tests/pos/i3912-2/i3912_2.scala new file mode 100644 index 000000000000..8530ba3ffe62 --- /dev/null +++ b/tests/pos/i3912-2/i3912_2.scala @@ -0,0 +1,6 @@ +import scala.quoted._ +import Macros._ + +class Test { + val a2: Unit = foo2() +} \ No newline at end of file diff --git a/tests/pos/i3912-3/i3912_1.scala b/tests/pos/i3912-3/i3912_1.scala new file mode 100644 index 000000000000..a544cfd26282 --- /dev/null +++ b/tests/pos/i3912-3/i3912_1.scala @@ -0,0 +1,11 @@ +import scala.quoted._ + +object Macros { + inline def foo3(): Int = { + { + ~impl() + } + } + + def impl(): Expr[Int] = '(1) +} \ No newline at end of file diff --git a/tests/pos/i3912-3/i3912_2.scala b/tests/pos/i3912-3/i3912_2.scala new file mode 100644 index 000000000000..a029cdff8165 --- /dev/null +++ b/tests/pos/i3912-3/i3912_2.scala @@ -0,0 +1,6 @@ +import scala.quoted._ +import Macros._ + +class Test { + val a3: Unit = foo3() +} \ No newline at end of file