Skip to content

Fix #4515: Synthesize implicit type tags in transparent methods #4899

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Aug 28, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions compiler/src/dotty/tools/dotc/core/Definitions.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/transform/ReifyQuotes.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
Expand Down
4 changes: 3 additions & 1 deletion compiler/src/dotty/tools/dotc/transform/Splicer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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) =>
Expand All @@ -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)
}

Expand Down
9 changes: 8 additions & 1 deletion compiler/src/dotty/tools/dotc/typer/Implicits.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*/
Expand Down Expand Up @@ -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))))
}
}

Expand Down
5 changes: 5 additions & 0 deletions library/src/scala/tasty/Tasty.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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.")
}
7 changes: 0 additions & 7 deletions library/src/scala/tasty/TopLevelSplice.scala

This file was deleted.

2 changes: 1 addition & 1 deletion tests/neg/tasty-macro-assert/quoted_1.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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._
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
5 changes: 5 additions & 0 deletions tests/run/i4515/Macro_1.scala
Original file line number Diff line number Diff line change
@@ -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] = '()
}
6 changes: 6 additions & 0 deletions tests/run/i4515/Test_2.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@

object Test {
def main(args: Array[String]): Unit = {
Macro.foo(4)
}
}
6 changes: 6 additions & 0 deletions tests/run/i4515b/Macro_1.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import scala.tasty.Tasty

object Macro {
rewrite def foo: Unit = ~fooImpl
def fooImpl(implicit tasty: Tasty): quoted.Expr[Unit] = '()
}
6 changes: 6 additions & 0 deletions tests/run/i4515b/Test_2.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@

object Test {
def main(args: Array[String]): Unit = {
Macro.foo
}
}
3 changes: 1 addition & 2 deletions tests/run/tasty-custom-show/quoted_1.scala
Original file line number Diff line number Diff line change
@@ -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._
Expand Down
3 changes: 1 addition & 2 deletions tests/run/tasty-definitions-1/quoted_1.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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._
Expand Down
2 changes: 1 addition & 1 deletion tests/run/tasty-definitions-2/Macro_1.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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._
Expand Down
2 changes: 1 addition & 1 deletion tests/run/tasty-definitions-3/Macro_1.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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._
Expand Down
2 changes: 1 addition & 1 deletion tests/run/tasty-eval/quoted_1.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion tests/run/tasty-extractors-1/quoted_1.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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._
Expand Down
2 changes: 1 addition & 1 deletion tests/run/tasty-extractors-2/quoted_1.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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._
Expand Down
3 changes: 1 addition & 2 deletions tests/run/tasty-extractors-3/quoted_1.scala
Original file line number Diff line number Diff line change
@@ -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._
Expand Down
3 changes: 1 addition & 2 deletions tests/run/tasty-extractors-constants-1/quoted_1.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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._
Expand Down
2 changes: 1 addition & 1 deletion tests/run/tasty-extractors-owners/quoted_1.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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._
Expand Down
3 changes: 1 addition & 2 deletions tests/run/tasty-extractors-types/quoted_1.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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._
Expand Down
4 changes: 2 additions & 2 deletions tests/run/tasty-getfile/Macro_1.scala
Original file line number Diff line number Diff line change
@@ -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._
Expand Down
4 changes: 2 additions & 2 deletions tests/run/tasty-indexed-map/quoted_1.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
3 changes: 1 addition & 2 deletions tests/run/tasty-linenumber-2/quoted_1.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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._
Expand Down
2 changes: 1 addition & 1 deletion tests/run/tasty-linenumber/quoted_1.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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._
Expand Down
3 changes: 1 addition & 2 deletions tests/run/tasty-location/quoted_1.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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._
Expand Down
2 changes: 1 addition & 1 deletion tests/run/tasty-macro-assert/quoted_1.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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._
Expand Down
3 changes: 1 addition & 2 deletions tests/run/tasty-positioned/quoted_1.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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 => _, _}
Expand Down
4 changes: 2 additions & 2 deletions tests/run/tasty-subtyping/quoted_1.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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._
Expand Down