diff --git a/compiler/src/dotty/tools/dotc/transform/ReifyQuotes.scala b/compiler/src/dotty/tools/dotc/transform/ReifyQuotes.scala index 4923946ce682..a51a8b00f380 100644 --- a/compiler/src/dotty/tools/dotc/transform/ReifyQuotes.scala +++ b/compiler/src/dotty/tools/dotc/transform/ReifyQuotes.scala @@ -237,7 +237,14 @@ class ReifyQuotes extends MacroTransformWithImplicits { def levelOK(sym: Symbol)(implicit ctx: Context): Boolean = levelOf.get(sym) match { case Some(l) => l == level || - level == -1 && sym == defn.TastyTasty_macroContext + level == -1 && ( + sym == defn.TastyTasty_macroContext || + // here we assume that Splicer.canBeSpliced was true before going to level -1, + // this implies that all non-inline arguments are quoted and that the following two cases are checked + // on inline parameters or type parameters. + sym.is(Param) || + sym.isClass // reference to this in inline methods + ) case None => !sym.is(Param) || levelOK(sym.owner) } @@ -584,9 +591,10 @@ class ReifyQuotes extends MacroTransformWithImplicits { """Malformed macro. | |Expected the ~ to be at the top of the RHS: - | inline def foo(x: X, ..., y: Y): Int = ~impl(x, ... '(y)) + | inline def foo(inline x: X, ..., y: Y): Int = ~impl(x, ... '(y)) | - |The contents of the splice must call a static method. Arguments must be quoted or inlined. + | * The contents of the splice must call a static method + | * All arguments must be quoted or inline """.stripMargin, tree.rhs.pos) EmptyTree } diff --git a/tests/neg/quote-this.scala b/tests/neg/quote-this.scala new file mode 100644 index 000000000000..b9b2d0034ea3 --- /dev/null +++ b/tests/neg/quote-this.scala @@ -0,0 +1,29 @@ +import scala.quoted._ + +class Foo { + + def f: Unit = '{ + def bar[T](x: T): T = x + bar[ + this.type // error + ] { + this // error + } + } + + inline def i(): Unit = ~Foo.impl[Any]('{ + '(this) // error + }) + + inline def j(that: Foo): Unit = ~Foo.impl[Any]('{ + '(that) // error + }) + + inline def k(): Unit = ~Foo.impl[Any](this) // error + inline def l(that: Foo): Unit = ~Foo.impl[Any](that) // error + +} + +object Foo { + def impl[T](x: Any): Expr[Unit] = '() +} diff --git a/tests/pos/quote-this.scala b/tests/pos/quote-this.scala new file mode 100644 index 000000000000..2472188ce2b3 --- /dev/null +++ b/tests/pos/quote-this.scala @@ -0,0 +1,28 @@ +import scala.quoted._ + +class Foo { + def a: Expr[Int] = '(1) + def b: Expr[Int] = '{ + ~this.a + } + + def d: Expr[Expr[Int]] = '{ '(1) } + def e: Expr[Expr[Int]] = '{ + '( ~(~this.d) ) + } + + def foo[T](x: T): T = x + + def f = '{ + ~foo[this.type](this).a + } + + inline def g(): Unit = ~Foo.impl[this.type](1) + inline def h(): Unit = ~Foo.impl[Any]('(this)) + inline def i(that: Foo): Unit = ~Foo.impl[that.type](1) + +} + +object Foo { + def impl[T](x: Any): Expr[Unit] = '() +}