diff --git a/compiler/src/dotty/tools/dotc/transform/ReifyQuotes.scala b/compiler/src/dotty/tools/dotc/transform/ReifyQuotes.scala index e19b701a06f1..cb6dc2999e3f 100644 --- a/compiler/src/dotty/tools/dotc/transform/ReifyQuotes.scala +++ b/compiler/src/dotty/tools/dotc/transform/ReifyQuotes.scala @@ -322,10 +322,15 @@ class ReifyQuotes extends MacroTransformWithImplicits { stats.foreach(markDef) mapOverTree(last) case Inlined(call, bindings, expansion @ Select(body, name)) if expansion.symbol.isSplice => - // To maintain phase consistency, convert inlined expressions of the form - // `{ bindings; ~expansion }` to `~{ bindings; expansion }` - if (level == 0) transform(Splicer.splice(cpy.Inlined(tree)(call, bindings, body))) - else transform(cpy.Select(expansion)(cpy.Inlined(tree)(call, bindings, 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) case _: Import => tree case tree: DefDef if tree.symbol.is(Macro) && level == 0 => diff --git a/compiler/src/dotty/tools/dotc/transform/Splicer.scala b/compiler/src/dotty/tools/dotc/transform/Splicer.scala index 6e05b9d85873..9237028dfd38 100644 --- a/compiler/src/dotty/tools/dotc/transform/Splicer.scala +++ b/compiler/src/dotty/tools/dotc/transform/Splicer.scala @@ -19,6 +19,7 @@ object Splicer { case tree: RefTree => reflectiveSplice(tree) case tree: Apply => reflectiveSplice(tree) case tree: Inlined => reflectiveSplice(tree) + case tree: Block => reflectiveSplice(tree) } /** Splice the Tree for a Quoted expression which is constructed via a reflective call to the given method */ diff --git a/compiler/src/dotty/tools/dotc/typer/Inliner.scala b/compiler/src/dotty/tools/dotc/typer/Inliner.scala index 587cc3f5153f..49a507e0994c 100644 --- a/compiler/src/dotty/tools/dotc/typer/Inliner.scala +++ b/compiler/src/dotty/tools/dotc/typer/Inliner.scala @@ -394,7 +394,7 @@ class Inliner(call: tpd.Tree, rhs: tpd.Tree)(implicit ctx: Context) { case tpe: ThisType if !canElideThis(tpe) && !thisProxy.contains(tpe.cls) => val proxyName = s"${tpe.cls.name}_this".toTermName val proxyType = tpe.asSeenFrom(prefix.tpe, meth.owner) - thisProxy(tpe.cls) = newSym(proxyName, EmptyFlags, proxyType).termRef + thisProxy(tpe.cls) = newSym(proxyName, Synthetic, proxyType).termRef if (!tpe.cls.isStaticOwner) registerType(meth.owner.thisType) // make sure we have a base from which to outer-select case tpe: NamedType diff --git a/tests/pos/i3898/quoted_1.scala b/tests/pos/i3898/quoted_1.scala new file mode 100644 index 000000000000..fc9ff2f97f48 --- /dev/null +++ b/tests/pos/i3898/quoted_1.scala @@ -0,0 +1,5 @@ +import scala.quoted._ +object Macro { + inline def ff(args: Any*): String = ~impl('(args)) + def impl(args: Expr[Seq[Any]]): Expr[String] = "" +} diff --git a/tests/pos/i3898/quoted_2.scala b/tests/pos/i3898/quoted_2.scala new file mode 100644 index 000000000000..8bb85b8998a7 --- /dev/null +++ b/tests/pos/i3898/quoted_2.scala @@ -0,0 +1,6 @@ +object Test { + def main(args: Array[String]): Unit = { + def x: Int = 5 + Macro.ff(x) + } +} diff --git a/tests/pos/i3898b/quoted_1.scala b/tests/pos/i3898b/quoted_1.scala new file mode 100644 index 000000000000..821744e111ca --- /dev/null +++ b/tests/pos/i3898b/quoted_1.scala @@ -0,0 +1,5 @@ +import scala.quoted._ +object Macro { + inline def ff(x: Int, inline y: Int): String = ~impl('(x)) + def impl(x: Expr[Int]): Expr[String] = "" +} diff --git a/tests/pos/i3898b/quoted_2.scala b/tests/pos/i3898b/quoted_2.scala new file mode 100644 index 000000000000..e16407c904ef --- /dev/null +++ b/tests/pos/i3898b/quoted_2.scala @@ -0,0 +1,6 @@ +object Test { + def main(args: Array[String]): Unit = { + def z: Int = 5 + Macro.ff(z, 5) + } +} diff --git a/tests/pos/i3898c/quoted_1.scala b/tests/pos/i3898c/quoted_1.scala new file mode 100644 index 000000000000..821744e111ca --- /dev/null +++ b/tests/pos/i3898c/quoted_1.scala @@ -0,0 +1,5 @@ +import scala.quoted._ +object Macro { + inline def ff(x: Int, inline y: Int): String = ~impl('(x)) + def impl(x: Expr[Int]): Expr[String] = "" +} diff --git a/tests/pos/i3898c/quoted_2.scala b/tests/pos/i3898c/quoted_2.scala new file mode 100644 index 000000000000..c94794b2b4ac --- /dev/null +++ b/tests/pos/i3898c/quoted_2.scala @@ -0,0 +1,9 @@ +object Test { + def main(args: Array[String]): Unit = { + val a = '{ + def z: Int = 5 + Macro.ff(z, 5) + } + + } +} diff --git a/tests/pos/quote-interpolator-core/quoted_1.scala b/tests/pos/quote-interpolator-core/quoted_1.scala index f32b1a32f6f6..bd24977de5a5 100644 --- a/tests/pos/quote-interpolator-core/quoted_1.scala +++ b/tests/pos/quote-interpolator-core/quoted_1.scala @@ -21,4 +21,7 @@ object FInterpolation { val args1: Expr[Seq[Any]] = liftSeq(args) '{ (~str).format(~args1: _*) } } + + def hello = "hello" + } \ No newline at end of file diff --git a/tests/pos/quote-interpolator-core/quoted_2.scala b/tests/pos/quote-interpolator-core/quoted_2.scala index e1e65d5c18d3..807c458f6420 100644 --- a/tests/pos/quote-interpolator-core/quoted_2.scala +++ b/tests/pos/quote-interpolator-core/quoted_2.scala @@ -5,4 +5,7 @@ object Test { println(ff"integer: ${5}%d") println(ff"string: ${"l"}%s") println(ff"${5}%s, ${6}%d, ${"hello"}%s") + val hello = "hello" + println(ff"${5}%s, ${6}%d, ${hello}%s") + println(ff"${5}%s, ${6}%d, ${FInterpolation.hello}%s") } \ No newline at end of file