diff --git a/compiler/src/dotty/tools/dotc/core/Definitions.scala b/compiler/src/dotty/tools/dotc/core/Definitions.scala index ff8f08f0249e..d057817c9b79 100644 --- a/compiler/src/dotty/tools/dotc/core/Definitions.scala +++ b/compiler/src/dotty/tools/dotc/core/Definitions.scala @@ -645,8 +645,6 @@ class Definitions { @tu lazy val QuotedExprModule_unitExpr: Symbol = QuotedExprModule.requiredMethod(nme.unitExpr) @tu lazy val QuoteContextClass: ClassSymbol = ctx.requiredClass("scala.quoted.QuoteContext") - @tu lazy val QuoteContextModule: Symbol = QuoteContextClass.companionModule - @tu lazy val QuoteContext_macroContext: Symbol = QuoteContextModule.requiredMethod("macroContext") @tu lazy val LiftableModule: Symbol = ctx.requiredModule("scala.quoted.Liftable") @tu lazy val LiftableModule_BooleanIsLiftable: Symbol = LiftableModule.requiredMethod("BooleanIsLiftable") diff --git a/compiler/src/dotty/tools/dotc/transform/PCPCheckAndHeal.scala b/compiler/src/dotty/tools/dotc/transform/PCPCheckAndHeal.scala index c976599c7f19..264319746933 100644 --- a/compiler/src/dotty/tools/dotc/transform/PCPCheckAndHeal.scala +++ b/compiler/src/dotty/tools/dotc/transform/PCPCheckAndHeal.scala @@ -192,7 +192,6 @@ class PCPCheckAndHeal(@constructorOnly ictx: Context) extends TreeMapWithStages( case Some(l) => l == level || level == -1 && ( - sym == defn.QuoteContext_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. diff --git a/compiler/src/dotty/tools/dotc/transform/Splicer.scala b/compiler/src/dotty/tools/dotc/transform/Splicer.scala index 6086ad9e7756..cc7f6690c10a 100644 --- a/compiler/src/dotty/tools/dotc/transform/Splicer.scala +++ b/compiler/src/dotty/tools/dotc/transform/Splicer.scala @@ -98,9 +98,6 @@ object Splicer { case Literal(Constant(value)) => // OK - case _ if tree.symbol == defn.QuoteContext_macroContext => - // OK - case Call(fn, args) if (fn.symbol.isConstructor && fn.symbol.owner.owner.is(Package)) || fn.symbol.is(Module) || fn.symbol.isStatic || @@ -191,9 +188,6 @@ object Splicer { case Literal(Constant(value)) => interpretLiteral(value) - case _ if tree.symbol == defn.QuoteContext_macroContext => - interpretQuoteContext() - // TODO disallow interpreted method calls as arguments case Call(fn, args) => if (fn.symbol.isConstructor && fn.symbol.owner.owner.is(Package)) @@ -263,9 +257,6 @@ object Splicer { private def interpretVarargs(args: List[Object])(implicit env: Env): Object = args.toSeq - private def interpretQuoteContext()(implicit env: Env): Object = - QuoteContext() - private def interpretedStaticMethodCall(moduleClass: Symbol, fn: Symbol)(implicit env: Env): List[Object] => Object = { val (inst, clazz) = if (moduleClass.name.startsWith(str.REPL_SESSION_LINE)) diff --git a/compiler/src/dotty/tools/dotc/typer/Implicits.scala b/compiler/src/dotty/tools/dotc/typer/Implicits.scala index 084af34ddfc1..451c107f98ac 100644 --- a/compiler/src/dotty/tools/dotc/typer/Implicits.scala +++ b/compiler/src/dotty/tools/dotc/typer/Implicits.scala @@ -732,11 +732,6 @@ trait Implicits { self: Typer => } } - lazy val synthesizedQuoteContext: SpecialHandler = - (formal, span) => implicit ctx => - if (ctx.inMacro || enclosingInlineds.nonEmpty) ref(defn.QuoteContext_macroContext) - else EmptyTree - lazy val synthesizedTupleFunction: SpecialHandler = (formal, span) => implicit ctx => formal match { case AppliedType(_, funArgs @ fun :: tupled :: Nil) => @@ -1082,7 +1077,6 @@ trait Implicits { self: Typer => mySpecialHandlers = List( defn.ClassTagClass -> synthesizedClassTag, defn.QuotedTypeClass -> synthesizedTypeTag, - defn.QuoteContextClass -> synthesizedQuoteContext, defn.EqlClass -> synthesizedEq, defn.TupledFunctionClass -> synthesizedTupleFunction, defn.ValueOfClass -> synthesizedValueOf, @@ -1464,7 +1458,6 @@ trait Implicits { self: Typer => case alt1: SearchSuccess => var diff = compareCandidate(alt1, alt2.ref, alt2.level) assert(diff <= 0) // diff > 0 candidates should already have been eliminated in `rank` - if diff == 0 then // Fall back: if both results are extension method applications, // compare the extension methods instead of their wrappers. diff --git a/library/src/scala/quoted/QuoteContext.scala b/library/src/scala/quoted/QuoteContext.scala index 6831663e4a0f..30f0a1b22b0f 100644 --- a/library/src/scala/quoted/QuoteContext.scala +++ b/library/src/scala/quoted/QuoteContext.scala @@ -47,7 +47,3 @@ class QuoteContext(val tasty: scala.tasty.Reflection) { } } - -object QuoteContext { - def macroContext: QuoteContext = throw new Exception("Not in inline macro.") -} diff --git a/tests/neg/i7618.scala b/tests/neg/i7618.scala new file mode 100644 index 000000000000..42c68bb8de4a --- /dev/null +++ b/tests/neg/i7618.scala @@ -0,0 +1,36 @@ +package macros + +import scala.quoted.{given, _} + +enum Exp { + case Num(n: Int) + case Plus(e1: Exp, e2: Exp) + case Var(x: String) + case Let(x: String, e: Exp, in: Exp) +} + +object Compiler { + import Exp._ + + inline def compile(e: Exp, env: Map[String, Expr[Int]])(given ctx: QuoteContext): Expr[Int] = inline e match { // error + case Num(n) => + Expr(n) + case Plus(e1, e2) => + '{ ${ compile(e1, env) } + ${ compile(e2, env) } } + case Var(x) => + env(x) + case Let(x, e, body) => + '{ val y = ${ compile(e, env) }; ${ compile(body, env + (x -> 'y)) } } + } +} + +object Example { + def run(): Unit = { + import Exp._ + + val exp = Plus(Plus(Num(2), Var("x")), Num(4)) + val letExp = Let("x", Num(3), exp) + + Compiler.compile(letExp, Map.empty)(given QuoteContext.macroContext) // error + } +} diff --git a/tests/neg/i7618b.scala b/tests/neg/i7618b.scala new file mode 100644 index 000000000000..d69e6299826f --- /dev/null +++ b/tests/neg/i7618b.scala @@ -0,0 +1,36 @@ +package macros + +import scala.quoted.{given, _} + +enum Exp { + case Num(n: Int) + case Plus(e1: Exp, e2: Exp) + case Var(x: String) + case Let(x: String, e: Exp, in: Exp) +} + +object Compiler { + import Exp._ + + inline def compile(e: Exp, env: Map[String, Expr[Int]])(given ctx: QuoteContext): Expr[Int] = inline e match { // error + case Num(n) => + Expr(n) + case Plus(e1, e2) => + '{ ${ compile(e1, env) } + ${ compile(e2, env) } } + case Var(x) => + env(x) + case Let(x, e, body) => + '{ val y = ${ compile(e, env) }; ${ compile(body, env + (x -> 'y)) } } + } +} + +object Example { + def run(): Unit = { + import Exp._ + + val exp = Plus(Plus(Num(2), Var("x")), Num(4)) + val letExp = Let("x", Num(3), exp) + + Compiler.compile(letExp, Map.empty)(given (??? : QuoteContext)) + } +} diff --git a/tests/pos/i7358.scala b/tests/pos/i7358.scala index 9a20680bed76..3d60dcb621ec 100644 --- a/tests/pos/i7358.scala +++ b/tests/pos/i7358.scala @@ -3,7 +3,7 @@ package test import scala.quoted._ import scala.compiletime._ -inline def summonT[Tp <: Tuple] <: Tuple = inline erasedValue[Tp] match { +inline def summonT[Tp <: Tuple](given QuoteContext) <: Tuple = inline erasedValue[Tp] match { case _ : Unit => () case _ : (hd *: tl) => { type H = hd @@ -13,4 +13,4 @@ inline def summonT[Tp <: Tuple] <: Tuple = inline erasedValue[Tp] match { } } -def test[T : Type] = summonT[Tuple1[List[T]]] +def test[T : Type](given QuoteContext) = summonT[Tuple1[List[T]]] diff --git a/tests/run-staging/quote-macro-in-splice/quoted_2.scala b/tests/run-staging/quote-macro-in-splice/quoted_2.scala index 263c0bebfcbc..a8dd1960d56c 100644 --- a/tests/run-staging/quote-macro-in-splice/quoted_2.scala +++ b/tests/run-staging/quote-macro-in-splice/quoted_2.scala @@ -8,14 +8,11 @@ object Test { val x = '{ val y = 1 ${ - // FIXME remove context when $ will provide one - // Currently we would accidentally capture the one from withQuoteContext - inline def a(z: Int): Int = ${ impl('z)(given QuoteContext.macroContext) } + inline def a(z: Int): Int = ${ impl('z) } val b = Expr(a(7)) '{ y + $b } } } println(x.show) } - }