diff --git a/compiler/src/dotty/tools/dotc/core/Definitions.scala b/compiler/src/dotty/tools/dotc/core/Definitions.scala index 38e949aa3f4b..e744e1c08d66 100644 --- a/compiler/src/dotty/tools/dotc/core/Definitions.scala +++ b/compiler/src/dotty/tools/dotc/core/Definitions.scala @@ -686,8 +686,11 @@ class Definitions { def Unpickler_liftedExpr = ctx.requiredMethod("scala.runtime.quoted.Unpickler.liftedExpr") def Unpickler_unpickleType = ctx.requiredMethod("scala.runtime.quoted.Unpickler.unpickleType") - lazy val TastyTopLevelSpliceModule = ctx.requiredModule("scala.tasty.TopLevelSplice") - lazy val TastyTopLevelSplice_tastyContext = TastyTopLevelSpliceModule.requiredMethod("tastyContext") + lazy val TastyTastyType = ctx.requiredClassRef("scala.tasty.Tasty") + def TastyTastyClass(implicit ctx: Context) = TastyTastyType.symbol.asClass + + lazy val TastyTastyModule = ctx.requiredModule("scala.tasty.Tasty") + lazy val TastyTasty_macroContext = TastyTastyModule.requiredMethod("macroContext") lazy val EqType = ctx.requiredClassRef("scala.Eq") def EqClass(implicit ctx: Context) = EqType.symbol.asClass diff --git a/compiler/src/dotty/tools/dotc/transform/ReifyQuotes.scala b/compiler/src/dotty/tools/dotc/transform/ReifyQuotes.scala index eac7e5c0b92a..54828aadf569 100644 --- a/compiler/src/dotty/tools/dotc/transform/ReifyQuotes.scala +++ b/compiler/src/dotty/tools/dotc/transform/ReifyQuotes.scala @@ -237,7 +237,7 @@ 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.TastyTopLevelSplice_tastyContext + level == -1 && sym == defn.TastyTasty_macroContext case None => !sym.is(Param) || levelOK(sym.owner) } diff --git a/compiler/src/dotty/tools/dotc/transform/Splicer.scala b/compiler/src/dotty/tools/dotc/transform/Splicer.scala index f4e11cbb984f..27cb275e7e4c 100644 --- a/compiler/src/dotty/tools/dotc/transform/Splicer.scala +++ b/compiler/src/dotty/tools/dotc/transform/Splicer.scala @@ -268,7 +268,7 @@ object Splicer { case Literal(Constant(value)) => interpretLiteral(value) - case _ if tree.symbol == defn.TastyTopLevelSplice_tastyContext => + case _ if tree.symbol == defn.TastyTasty_macroContext => interpretTastyContext() case StaticMethodCall(fn, args) => @@ -286,6 +286,8 @@ object Splicer { case NamedArg(_, arg) => interpretTree(arg) case Ident(name) if env.contains(name) => env(name) + case Inlined(EmptyTree, Nil, expansion) => interpretTree(expansion) + case _ => unexpectedTree(tree) } diff --git a/compiler/src/dotty/tools/dotc/typer/Implicits.scala b/compiler/src/dotty/tools/dotc/typer/Implicits.scala index 1e09e7e9702f..e7faf156ad0c 100644 --- a/compiler/src/dotty/tools/dotc/typer/Implicits.scala +++ b/compiler/src/dotty/tools/dotc/typer/Implicits.scala @@ -620,10 +620,16 @@ trait Implicits { self: Typer => val tag = bindFreeVars(arg) if (bindFreeVars.ok) ref(defn.QuotedType_apply).appliedToType(tag) else EmptyTree + case arg :: Nil if ctx.inRewriteMethod => + ref(defn.QuotedType_apply).appliedToType(arg) case _ => EmptyTree } + def synthesizedTastyContext(formal: Type): Tree = + if (ctx.inRewriteMethod || enclosingInlineds.nonEmpty) ref(defn.TastyTasty_macroContext) + else EmptyTree + /** If `formal` is of the form Eq[T, U], where no `Eq` instance exists for * either `T` or `U`, synthesize `Eq.eqAny[T, U]` as solution. */ @@ -694,7 +700,8 @@ trait Implicits { self: Typer => else trySpecialCase(defn.ClassTagClass, synthesizedClassTag, trySpecialCase(defn.QuotedTypeClass, synthesizedTypeTag, - trySpecialCase(defn.EqClass, synthesizedEq, failed))) + trySpecialCase(defn.TastyTastyClass, synthesizedTastyContext, + trySpecialCase(defn.EqClass, synthesizedEq, failed)))) } } diff --git a/library/src/scala/tasty/Tasty.scala b/library/src/scala/tasty/Tasty.scala index ab5a0047ddf7..42ab03078cb8 100644 --- a/library/src/scala/tasty/Tasty.scala +++ b/library/src/scala/tasty/Tasty.scala @@ -19,3 +19,8 @@ abstract class Tasty with TreeOps with TypeOrBoundsTreeOps with TypeOrBoundsOps + +object Tasty { + /** Compiler tasty context available in a top level ~ of a transparent macro */ + def macroContext: Tasty = throw new Exception("Not in transparent macro.") +} diff --git a/library/src/scala/tasty/TopLevelSplice.scala b/library/src/scala/tasty/TopLevelSplice.scala deleted file mode 100644 index a425adf78a06..000000000000 --- a/library/src/scala/tasty/TopLevelSplice.scala +++ /dev/null @@ -1,7 +0,0 @@ -package scala.tasty - -/** Context in a top level ~ at inline site, intrinsically as `import TopLevelSplice._` */ -object TopLevelSplice { - /** Compiler tasty context available in a top level ~ at inline site */ - implicit def tastyContext: Tasty = throw new Exception("Not in macro.") -} diff --git a/tests/neg/tasty-macro-assert/quoted_1.scala b/tests/neg/tasty-macro-assert/quoted_1.scala index 9a9c0ccffb3e..9a5344f2430c 100644 --- a/tests/neg/tasty-macro-assert/quoted_1.scala +++ b/tests/neg/tasty-macro-assert/quoted_1.scala @@ -12,7 +12,7 @@ object Asserts { object Ops rewrite def macroAssert(cond: => Boolean): Unit = - ~impl('(cond))(TopLevelSplice.tastyContext) // FIXME infer TopLevelSplice.tastyContext within top level ~ + ~impl('(cond)) def impl(cond: Expr[Boolean])(implicit tasty: Tasty): Expr[Unit] = { import tasty._ diff --git a/tests/run-with-compiler/tasty-extractors-constants-2/quoted_1.scala b/tests/run-with-compiler/tasty-extractors-constants-2/quoted_1.scala index d8eaa2011178..a074f926ba16 100644 --- a/tests/run-with-compiler/tasty-extractors-constants-2/quoted_1.scala +++ b/tests/run-with-compiler/tasty-extractors-constants-2/quoted_1.scala @@ -6,8 +6,7 @@ import scala.tasty.util._ object Macros { - rewrite def testMacro: Unit = - ~impl(TopLevelSplice.tastyContext) // FIXME infer TopLevelSplice.tastyContext within top level ~ + rewrite def testMacro: Unit = ~impl def impl(implicit tasty: Tasty): Expr[Unit] = { // 2 is a lifted constant diff --git a/tests/run/i4515/Macro_1.scala b/tests/run/i4515/Macro_1.scala new file mode 100644 index 000000000000..0c6eaf425cb8 --- /dev/null +++ b/tests/run/i4515/Macro_1.scala @@ -0,0 +1,5 @@ + +object Macro { + rewrite def foo[X](x: X): Unit = ~fooImpl('(x)) + def fooImpl[X: quoted.Type](x: quoted.Expr[X]): quoted.Expr[Unit] = '() +} diff --git a/tests/run/i4515/Test_2.scala b/tests/run/i4515/Test_2.scala new file mode 100644 index 000000000000..c053a6e49b3c --- /dev/null +++ b/tests/run/i4515/Test_2.scala @@ -0,0 +1,6 @@ + +object Test { + def main(args: Array[String]): Unit = { + Macro.foo(4) + } +} diff --git a/tests/run/i4515b/Macro_1.scala b/tests/run/i4515b/Macro_1.scala new file mode 100644 index 000000000000..8be8a7a6c8ed --- /dev/null +++ b/tests/run/i4515b/Macro_1.scala @@ -0,0 +1,6 @@ +import scala.tasty.Tasty + +object Macro { + rewrite def foo: Unit = ~fooImpl + def fooImpl(implicit tasty: Tasty): quoted.Expr[Unit] = '() +} diff --git a/tests/run/i4515b/Test_2.scala b/tests/run/i4515b/Test_2.scala new file mode 100644 index 000000000000..dc8b0c4e7040 --- /dev/null +++ b/tests/run/i4515b/Test_2.scala @@ -0,0 +1,6 @@ + +object Test { + def main(args: Array[String]): Unit = { + Macro.foo + } +} diff --git a/tests/run/tasty-custom-show/quoted_1.scala b/tests/run/tasty-custom-show/quoted_1.scala index f0b7bf75a15b..de016f40c961 100644 --- a/tests/run/tasty-custom-show/quoted_1.scala +++ b/tests/run/tasty-custom-show/quoted_1.scala @@ -1,13 +1,12 @@ import scala.quoted._ -import scala.tasty.TopLevelSplice import scala.tasty.Tasty import scala.tasty.util.{TreeTraverser, Show} object Macros { implicit rewrite def printOwners[T](x: => T): Unit = - ~impl('(x))(TopLevelSplice.tastyContext) // FIXME infer TopLevelSplice.tastyContext within top level ~ + ~impl('(x)) def impl[T](x: Expr[T])(implicit tasty: Tasty): Expr[Unit] = { import tasty._ diff --git a/tests/run/tasty-definitions-1/quoted_1.scala b/tests/run/tasty-definitions-1/quoted_1.scala index 2dd21d8d0819..9f9d0f8e2ce3 100644 --- a/tests/run/tasty-definitions-1/quoted_1.scala +++ b/tests/run/tasty-definitions-1/quoted_1.scala @@ -5,8 +5,7 @@ import scala.tasty.util.TreeTraverser object Macros { - rewrite def testDefinitions(): Unit = - ~testDefinitionsImpl(TopLevelSplice.tastyContext) // FIXME infer TopLevelSplice.tastyContext within top level ~ + rewrite def testDefinitions(): Unit = ~testDefinitionsImpl def testDefinitionsImpl(implicit tasty: Tasty): Expr[Unit] = { import tasty._ diff --git a/tests/run/tasty-definitions-2/Macro_1.scala b/tests/run/tasty-definitions-2/Macro_1.scala index 8345d9613828..46d290a9271f 100644 --- a/tests/run/tasty-definitions-2/Macro_1.scala +++ b/tests/run/tasty-definitions-2/Macro_1.scala @@ -4,7 +4,7 @@ import scala.tasty._ object Foo { rewrite def inspectBody(i: => Int): String = - ~inspectBodyImpl('(i))(TopLevelSplice.tastyContext) // FIXME infer TopLevelSplice.tastyContext within top level ~ + ~inspectBodyImpl('(i)) def inspectBodyImpl(x: Expr[Int])(implicit tasty: Tasty): Expr[String] = { import tasty._ diff --git a/tests/run/tasty-definitions-3/Macro_1.scala b/tests/run/tasty-definitions-3/Macro_1.scala index 940bb827a7c9..ddf6aa5fdccd 100644 --- a/tests/run/tasty-definitions-3/Macro_1.scala +++ b/tests/run/tasty-definitions-3/Macro_1.scala @@ -4,7 +4,7 @@ import scala.tasty._ object Foo { rewrite def inspectBody(i: => Int): String = - ~inspectBodyImpl('(i))(TopLevelSplice.tastyContext) // FIXME infer TopLevelSplice.tastyContext within top level ~ + ~inspectBodyImpl('(i)) def inspectBodyImpl(x: Expr[Int])(implicit tasty: Tasty): Expr[String] = { import tasty._ diff --git a/tests/run/tasty-eval/quoted_1.scala b/tests/run/tasty-eval/quoted_1.scala index 38b863ce7f2f..215f0ae0648d 100644 --- a/tests/run/tasty-eval/quoted_1.scala +++ b/tests/run/tasty-eval/quoted_1.scala @@ -6,7 +6,7 @@ import scala.tasty.util.TreeTraverser object Macros { implicit rewrite def foo(i: Int): String = - ~impl('(i))(TopLevelSplice.tastyContext) // FIXME infer TopLevelSplice.tastyContext within top level ~ + ~impl('(i)) def impl(i: Expr[Int])(implicit tasty: Tasty): Expr[String] = { value(i).toString.toExpr diff --git a/tests/run/tasty-extractors-1/quoted_1.scala b/tests/run/tasty-extractors-1/quoted_1.scala index 3e5679acb852..2e9c12ce06ce 100644 --- a/tests/run/tasty-extractors-1/quoted_1.scala +++ b/tests/run/tasty-extractors-1/quoted_1.scala @@ -5,7 +5,7 @@ import scala.tasty._ object Macros { implicit rewrite def printTree[T](x: => T): Unit = - ~impl('(x))(TopLevelSplice.tastyContext) // FIXME infer TopLevelSplice.tastyContext within top level ~ + ~impl('(x)) def impl[T](x: Expr[T])(implicit tasty: Tasty): Expr[Unit] = { import tasty._ diff --git a/tests/run/tasty-extractors-2/quoted_1.scala b/tests/run/tasty-extractors-2/quoted_1.scala index d8405f10c06a..02b7d9ca3cc3 100644 --- a/tests/run/tasty-extractors-2/quoted_1.scala +++ b/tests/run/tasty-extractors-2/quoted_1.scala @@ -5,7 +5,7 @@ import scala.tasty._ object Macros { implicit rewrite def printTree[T](x: => T): Unit = - ~impl('(x))(TopLevelSplice.tastyContext) // FIXME infer TopLevelSplice.tastyContext within top level ~ + ~impl('(x)) def impl[T](x: Expr[T])(implicit tasty: Tasty): Expr[Unit] = { import tasty._ diff --git a/tests/run/tasty-extractors-3/quoted_1.scala b/tests/run/tasty-extractors-3/quoted_1.scala index 7628654ea990..2767a1cd16c7 100644 --- a/tests/run/tasty-extractors-3/quoted_1.scala +++ b/tests/run/tasty-extractors-3/quoted_1.scala @@ -1,13 +1,12 @@ import scala.quoted._ -import scala.tasty.TopLevelSplice import scala.tasty.Tasty import scala.tasty.util.TreeTraverser object Macros { implicit rewrite def printTypes[T](x: => T): Unit = - ~impl('(x))(TopLevelSplice.tastyContext) // FIXME infer TopLevelSplice.tastyContext within top level ~ + ~impl('(x)) def impl[T](x: Expr[T])(implicit tasty: Tasty): Expr[Unit] = { import tasty._ diff --git a/tests/run/tasty-extractors-constants-1/quoted_1.scala b/tests/run/tasty-extractors-constants-1/quoted_1.scala index aad9755d2de8..fbf2c66ebba2 100644 --- a/tests/run/tasty-extractors-constants-1/quoted_1.scala +++ b/tests/run/tasty-extractors-constants-1/quoted_1.scala @@ -5,8 +5,7 @@ import scala.tasty.util._ object Macros { - implicit rewrite def testMacro: Unit = - ~impl(TopLevelSplice.tastyContext) // FIXME infer TopLevelSplice.tastyContext within top level ~ + implicit rewrite def testMacro: Unit = ~impl def impl(implicit tasty: Tasty): Expr[Unit] = { import tasty._ diff --git a/tests/run/tasty-extractors-owners/quoted_1.scala b/tests/run/tasty-extractors-owners/quoted_1.scala index 97ab658f508f..bcbb9180a7d3 100644 --- a/tests/run/tasty-extractors-owners/quoted_1.scala +++ b/tests/run/tasty-extractors-owners/quoted_1.scala @@ -6,7 +6,7 @@ import scala.tasty.util.TreeTraverser object Macros { implicit rewrite def printOwners[T](x: => T): Unit = - ~impl('(x))(TopLevelSplice.tastyContext) // FIXME infer TopLevelSplice.tastyContext within top level ~ + ~impl('(x)) def impl[T](x: Expr[T])(implicit tasty: Tasty): Expr[Unit] = { import tasty._ diff --git a/tests/run/tasty-extractors-types/quoted_1.scala b/tests/run/tasty-extractors-types/quoted_1.scala index f24eea16e2ef..e8da8682c4cc 100644 --- a/tests/run/tasty-extractors-types/quoted_1.scala +++ b/tests/run/tasty-extractors-types/quoted_1.scala @@ -5,8 +5,7 @@ import scala.tasty.util.TreeTraverser object Macros { - implicit rewrite def printType[T]: Unit = - ~impl('[T])(TopLevelSplice.tastyContext) // FIXME infer TopLevelSplice.tastyContext within top level ~ + implicit rewrite def printType[T]: Unit = ~impl('[T]) def impl[T](x: Type[T])(implicit tasty: Tasty): Expr[Unit] = { import tasty._ diff --git a/tests/run/tasty-getfile/Macro_1.scala b/tests/run/tasty-getfile/Macro_1.scala index 34d6bfb5402c..69b55f62c313 100644 --- a/tests/run/tasty-getfile/Macro_1.scala +++ b/tests/run/tasty-getfile/Macro_1.scala @@ -1,10 +1,10 @@ import scala.quoted._ -import scala.tasty.{Tasty, TopLevelSplice} +import scala.tasty.Tasty object SourceFiles { implicit rewrite def getThisFile: String = - ~getThisFileImpl(TopLevelSplice.tastyContext) // FIXME infer TopLevelSplice.tastyContext within top level ~ + ~getThisFileImpl private def getThisFileImpl(implicit tasty: Tasty): Expr[String] = { import tasty._ diff --git a/tests/run/tasty-indexed-map/quoted_1.scala b/tests/run/tasty-indexed-map/quoted_1.scala index 7c3aa6f45d0b..751c091fdeb6 100644 --- a/tests/run/tasty-indexed-map/quoted_1.scala +++ b/tests/run/tasty-indexed-map/quoted_1.scala @@ -24,9 +24,9 @@ object Index { implicit def zero[K, T]: Index[K, (K, T)] = new Index(0) - implicit rewrite def succ[K, H, T](implicit prev: => Index[K, T]): Index[K, (H, T)] = ~succImpl(TopLevelSplice.tastyContext)('[K], '[H], '[T]) + implicit rewrite def succ[K, H, T](implicit prev: => Index[K, T]): Index[K, (H, T)] = ~succImpl[K, H, T] - def succImpl[K, H, T](tasty: Tasty)(implicit k: Type[K], h: Type[H], t: Type[T]): Expr[Index[K, (H, T)]] = { + def succImpl[K, H, T](implicit tasty: Tasty, k: Type[K], h: Type[H], t: Type[T]): Expr[Index[K, (H, T)]] = { import tasty._ def name(tp: TypeOrBounds): String = tp match { diff --git a/tests/run/tasty-linenumber-2/quoted_1.scala b/tests/run/tasty-linenumber-2/quoted_1.scala index d825cce1e942..bae6d9368d35 100644 --- a/tests/run/tasty-linenumber-2/quoted_1.scala +++ b/tests/run/tasty-linenumber-2/quoted_1.scala @@ -8,8 +8,7 @@ class LineNumber(val value: Int) { object LineNumber { - implicit rewrite def line: LineNumber = - ~lineImpl(TopLevelSplice.tastyContext) // FIXME infer TopLevelSplice.tastyContext within top level ~ + implicit rewrite def line: LineNumber = ~lineImpl def lineImpl(implicit tasty: Tasty): Expr[LineNumber] = { import tasty._ diff --git a/tests/run/tasty-linenumber/quoted_1.scala b/tests/run/tasty-linenumber/quoted_1.scala index 4946c859be72..c6c1b35c331d 100644 --- a/tests/run/tasty-linenumber/quoted_1.scala +++ b/tests/run/tasty-linenumber/quoted_1.scala @@ -9,7 +9,7 @@ class LineNumber(val value: Int) { object LineNumber { implicit rewrite def line[T >: Unit <: Unit]: LineNumber = - ~lineImpl('[T])(TopLevelSplice.tastyContext) // FIXME infer TopLevelSplice.tastyContext within top level ~ + ~lineImpl('[T]) def lineImpl(x: Type[Unit])(implicit tasty: Tasty): Expr[LineNumber] = { import tasty._ diff --git a/tests/run/tasty-location/quoted_1.scala b/tests/run/tasty-location/quoted_1.scala index c7b7fca9aa42..11660bece718 100644 --- a/tests/run/tasty-location/quoted_1.scala +++ b/tests/run/tasty-location/quoted_1.scala @@ -6,8 +6,7 @@ case class Location(owners: List[String]) object Location { - implicit rewrite def location: Location = - ~impl(TopLevelSplice.tastyContext) // FIXME infer TopLevelSplice.tastyContext within top level ~ + implicit rewrite def location: Location = ~impl def impl(implicit tasty: Tasty): Expr[Location] = { import tasty._ diff --git a/tests/run/tasty-macro-assert/quoted_1.scala b/tests/run/tasty-macro-assert/quoted_1.scala index 92c609bd2d72..0c150f6b2537 100644 --- a/tests/run/tasty-macro-assert/quoted_1.scala +++ b/tests/run/tasty-macro-assert/quoted_1.scala @@ -12,7 +12,7 @@ object Asserts { object Ops rewrite def macroAssert(cond: => Boolean): Unit = - ~impl('(cond))(TopLevelSplice.tastyContext) // FIXME infer TopLevelSplice.tastyContext within top level ~ + ~impl('(cond)) def impl(cond: Expr[Boolean])(implicit tasty: Tasty): Expr[Unit] = { import tasty._ diff --git a/tests/run/tasty-positioned/quoted_1.scala b/tests/run/tasty-positioned/quoted_1.scala index 799aaa0c9f05..e8ae65d8a27d 100644 --- a/tests/run/tasty-positioned/quoted_1.scala +++ b/tests/run/tasty-positioned/quoted_1.scala @@ -9,8 +9,7 @@ case class Positioned[T](value: T, position: Position) object Positioned { - implicit rewrite def apply[T](x: => T): Positioned[T] = - ~impl('(x))('[T], TopLevelSplice.tastyContext) // FIXME infer TopLevelSplice.tastyContext within top level ~ + implicit rewrite def apply[T](x: => T): Positioned[T] = ~impl('(x)) def impl[T](x: Expr[T])(implicit ev: Type[T], tasty: Tasty): Expr[Positioned[T]] = { import tasty.{Position => _, _} diff --git a/tests/run/tasty-subtyping/quoted_1.scala b/tests/run/tasty-subtyping/quoted_1.scala index 5a5217662579..601e47b04b79 100644 --- a/tests/run/tasty-subtyping/quoted_1.scala +++ b/tests/run/tasty-subtyping/quoted_1.scala @@ -5,10 +5,10 @@ import scala.tasty._ object Macros { rewrite def isTypeEqual[T, U]: Boolean = - ~isTypeEqualImpl('[T], '[U])(TopLevelSplice.tastyContext) // FIXME infer TopLevelSplice.tastyContext within top level ~ + ~isTypeEqualImpl('[T], '[U]) rewrite def isSubTypeOf[T, U]: Boolean = - ~isSubTypeOfImpl('[T], '[U])(TopLevelSplice.tastyContext) // FIXME infer TopLevelSplice.tastyContext within top level ~ + ~isSubTypeOfImpl('[T], '[U]) def isTypeEqualImpl[T, U](t: Type[T], u: Type[U])(implicit tasty: Tasty): Expr[Boolean] = { import tasty._