Skip to content

Replaced TaggedType using QuoteContext #6950

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
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
16 changes: 0 additions & 16 deletions compiler/src/dotty/tools/dotc/core/quoted/PickledQuotes.scala
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,6 @@ object PickledQuotes {
tpt
case tpt => tpt
}
case expr: TaggedType[_] => classTagToTypeTree(expr.ct)
case expr: TreeType[Tree] @unchecked => healOwner(expr.typeTree)
}

Expand Down Expand Up @@ -127,21 +126,6 @@ object PickledQuotes {
tree
}

private def classTagToTypeTree(ct: ClassTag[_])(implicit ctx: Context): TypeTree = {
val tpe = ct match {
case ClassTag.Unit => defn.UnitType
case ClassTag.Boolean => defn.BooleanType
case ClassTag.Byte => defn.ByteType
case ClassTag.Char => defn.CharType
case ClassTag.Short => defn.ShortType
case ClassTag.Int => defn.IntType
case ClassTag.Long => defn.LongType
case ClassTag.Float => defn.FloatType
case ClassTag.Double => defn.DoubleType
}
TypeTree(tpe)
}

private def functionAppliedTo(fn: Tree, args: List[Tree])(implicit ctx: Context): Tree = {
val (argVals, argRefs) = args.map(arg => arg.tpe match {
case tpe: SingletonType if isIdempotentExpr(arg) => (Nil, arg)
Expand Down
37 changes: 19 additions & 18 deletions compiler/src/dotty/tools/dotc/transform/ReifyQuotes.scala
Original file line number Diff line number Diff line change
Expand Up @@ -202,27 +202,28 @@ class ReifyQuotes extends MacroTransform {
}

private def pickledQuote(body: Tree, splices: List[Tree], originalTp: Type, isType: Boolean)(implicit ctx: Context) = {
def qctx: Tree = {
val qctx = ctx.typer.inferImplicitArg(defn.QuoteContextClass.typeRef, body.span)
if (qctx.tpe.isInstanceOf[SearchFailureType])
ctx.error(ctx.typer.missingArgMsg(qctx, defn.QuoteContextClass.typeRef, ""), ctx.source.atSpan(body.span))
qctx
}

def liftedValue[T](value: T, name: TermName, qctx: Tree) =
ref(defn.LiftableModule).select(name).select("toExpr".toTermName).appliedTo(Literal(Constant(value))).select(nme.apply).appliedTo(qctx)

def pickleAsValue[T](value: T) = {
val qctx = ctx.typer.inferImplicitArg(defn.QuoteContextClass.typeRef, body.span)
if (qctx.tpe.isInstanceOf[SearchFailureType])
ctx.error(ctx.typer.missingArgMsg(qctx, defn.QuoteContextClass.typeRef, ""), ctx.source.atSpan(body.span))
value match {
case null => ref(defn.QuotedExprModule).select("nullExpr".toTermName).appliedTo(qctx)
case _: Unit => ref(defn.QuotedExprModule).select("unitExpr".toTermName).appliedTo(qctx)
case _: Boolean => liftedValue(value, "Liftable_Boolean_delegate".toTermName, qctx)
case _: Byte => liftedValue(value, "Liftable_Byte_delegate".toTermName, qctx)
case _: Short => liftedValue(value, "Liftable_Short_delegate".toTermName, qctx)
case _: Int => liftedValue(value, "Liftable_Int_delegate".toTermName, qctx)
case _: Long => liftedValue(value, "Liftable_Long_delegate".toTermName, qctx)
case _: Float => liftedValue(value, "Liftable_Float_delegate".toTermName, qctx)
case _: Double => liftedValue(value, "Liftable_Double_delegate".toTermName, qctx)
case _: Char => liftedValue(value, "Liftable_Char_delegate".toTermName, qctx)
case _: String => liftedValue(value, "Liftable_String_delegate".toTermName, qctx)
}
def pickleAsValue[T](value: T) = value match {
case null => ref(defn.QuotedExprModule).select("nullExpr".toTermName).appliedTo(qctx)
case _: Unit => ref(defn.QuotedExprModule).select("unitExpr".toTermName).appliedTo(qctx)
case _: Boolean => liftedValue(value, "Liftable_Boolean_delegate".toTermName, qctx)
case _: Byte => liftedValue(value, "Liftable_Byte_delegate".toTermName, qctx)
case _: Short => liftedValue(value, "Liftable_Short_delegate".toTermName, qctx)
case _: Int => liftedValue(value, "Liftable_Int_delegate".toTermName, qctx)
case _: Long => liftedValue(value, "Liftable_Long_delegate".toTermName, qctx)
case _: Float => liftedValue(value, "Liftable_Float_delegate".toTermName, qctx)
case _: Double => liftedValue(value, "Liftable_Double_delegate".toTermName, qctx)
case _: Char => liftedValue(value, "Liftable_Char_delegate".toTermName, qctx)
case _: String => liftedValue(value, "Liftable_String_delegate".toTermName, qctx)
}

def pickleAsTasty() = {
Expand All @@ -239,7 +240,7 @@ class ReifyQuotes extends MacroTransform {
}
if (splices.nonEmpty) pickleAsTasty()
else if (isType) {
def tag(tagName: String) = ref(defn.QuotedTypeModule).select(tagName.toTermName)
def tag(tagName: String) = ref(defn.QuotedTypeModule).select(tagName.toTermName).appliedTo(qctx)
if (body.symbol.isPrimitiveValueClass) tag(s"${body.symbol.name}Tag")
else pickleAsTasty()
}
Expand Down
15 changes: 15 additions & 0 deletions compiler/test-resources/repl-macros/i6263
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
scala> import quoted._
scala> implicit def toolbox: scala.quoted.Toolbox = scala.quoted.Toolbox.make(getClass.getClassLoader)
def toolbox: quoted.Toolbox
scala> def fn[T : Type](v : T) = println("ok")
def fn[T](v: T)(implicit evidence$1: quoted.Type[T]): Unit
scala> withQuoteContext { fn("foo") }
ok
scala> withQuoteContext { fn((1,2)) }
ok
scala> object O
// defined object O
scala> withQuoteContext { fn(O) }
ok
scala> withQuoteContext { fn(1) }
ok
13 changes: 0 additions & 13 deletions compiler/test-resources/repl/i6263

This file was deleted.

62 changes: 46 additions & 16 deletions library/src/scala/quoted/Type.scala
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package scala

package quoted {
import scala.internal.quoted.TaggedType
import scala.quoted.show.SyntaxHighlight

sealed trait Type[T <: AnyKind] {
Expand All @@ -17,35 +16,66 @@ package quoted {

/** Some basic type tags, currently incomplete */
object Type {
given UnitTag as Type[Unit] = new TaggedType[Unit]
given BooleanTag as Type[Boolean] = new TaggedType[Boolean]
given ByteTag as Type[Byte] = new TaggedType[Byte]
given CharTag as Type[Char] = new TaggedType[Char]
given ShortTag as Type[Short] = new TaggedType[Short]
given IntTag as Type[Int] = new TaggedType[Int]
given LongTag as Type[Long] = new TaggedType[Long]
given FloatTag as Type[Float] = new TaggedType[Float]
given DoubleTag as Type[Double] = new TaggedType[Double]

given UnitTag as Type[Unit] given (qctx: QuoteContext) = {
import qctx.tasty._
definitions.UnitType.seal.asInstanceOf[quoted.Type[Unit]]
}

given BooleanTag as Type[Boolean] given (qctx: QuoteContext) = {
import qctx.tasty._
definitions.BooleanType.seal.asInstanceOf[quoted.Type[Boolean]]
}

given ByteTag as Type[Byte] given (qctx: QuoteContext) = {
import qctx.tasty._
definitions.ByteType.seal.asInstanceOf[quoted.Type[Byte]]
}

given CharTag as Type[Char] given (qctx: QuoteContext) = {
import qctx.tasty._
definitions.CharType.seal.asInstanceOf[quoted.Type[Char]]
}

given ShortTag as Type[Short] given (qctx: QuoteContext) = {
import qctx.tasty._
definitions.ShortType.seal.asInstanceOf[quoted.Type[Short]]
}

given IntTag as Type[Int] given (qctx: QuoteContext) = {
import qctx.tasty._
definitions.IntType.seal.asInstanceOf[quoted.Type[Int]]
}

given LongTag as Type[Long] given (qctx: QuoteContext) = {
import qctx.tasty._
definitions.LongType.seal.asInstanceOf[quoted.Type[Long]]
}

given FloatTag as Type[Float] given (qctx: QuoteContext) = {
import qctx.tasty._
definitions.FloatType.seal.asInstanceOf[quoted.Type[Float]]
}

given DoubleTag as Type[Double] given (qctx: QuoteContext) = {
import qctx.tasty._
definitions.DoubleType.seal.asInstanceOf[quoted.Type[Double]]
}

}

}

package internal {
package quoted {
import scala.quoted.Type
import scala.reflect.ClassTag
import scala.runtime.quoted.Unpickler.Pickled

/** A Type backed by a pickled TASTY tree */
final class TastyType[T](val tasty: Pickled, val args: Seq[Any]) extends Type[T] {
override def toString(): String = s"Type(<pickled tasty>)"
}

/** An Type backed by a value */
final class TaggedType[T](implicit val ct: ClassTag[T]) extends Type[T] {
override def toString: String = s"Type($ct)"
}

/** An Type backed by a tree */
final class TreeType[Tree](val typeTree: Tree) extends Type[Any] {
override def toString: String = s"Type(<tasty tree>)"
Expand Down
2 changes: 1 addition & 1 deletion tests/pos/typetags.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import scala.quoted._

object Test {

def f[T: Type] = {
def f[T: Type] given QuoteContext = {
implicitly[Type[Int]]
implicitly[Type[List[Int]]]
implicitly[Type[T]]
Expand Down
4 changes: 2 additions & 2 deletions tests/run-with-compiler/i3947b.check
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@

scala.Predef.classOf[scala.Boolean].getCanonicalName()
boolean

scala.Predef.classOf[scala.Byte].getCanonicalName()
byte

scala.Predef.classOf[scala.Char].getCanonicalName()
boolean
byte
char
15 changes: 9 additions & 6 deletions tests/run-with-compiler/i3947b.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@ import scala.quoted._

object Test {

def main(args: Array[String]): Unit = {
implicit val toolbox: scala.quoted.Toolbox = scala.quoted.Toolbox.make(getClass.getClassLoader)
def test[T: Type](clazz: java.lang.Class[T]): Unit = run {
implicit val toolbox: scala.quoted.Toolbox = scala.quoted.Toolbox.make(getClass.getClassLoader)

def main(args: Array[String]): Unit = run {
def test[T: Type](clazz: java.lang.Class[T]) = {
val lclazz = clazz.toExpr
val name = '{ ($lclazz).getCanonicalName }
println()
Expand All @@ -14,9 +15,11 @@ object Test {
}

// primitives
test(classOf[Boolean])
test(classOf[Byte])
test(classOf[Char])
'{
${test(classOf[Boolean])}
${test(classOf[Byte])}
${test(classOf[Char])}
}
}

}
4 changes: 2 additions & 2 deletions tests/run-with-compiler/i3947b2.check
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@

scala.Predef.classOf[scala.Short].getCanonicalName()
short

scala.Predef.classOf[scala.Int].getCanonicalName()
int

scala.Predef.classOf[scala.Long].getCanonicalName()
short
int
long
15 changes: 9 additions & 6 deletions tests/run-with-compiler/i3947b2.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@ import scala.quoted._

object Test {

def main(args: Array[String]): Unit = {
implicit val toolbox: scala.quoted.Toolbox = scala.quoted.Toolbox.make(getClass.getClassLoader)
def test[T: Type](clazz: java.lang.Class[T]): Unit = run {
implicit val toolbox: scala.quoted.Toolbox = scala.quoted.Toolbox.make(getClass.getClassLoader)

def main(args: Array[String]): Unit = run {
def test[T: Type](clazz: given QuoteContext => java.lang.Class[T]) = {
val lclazz = clazz.toExpr
val name = '{ ($lclazz).getCanonicalName }
println()
Expand All @@ -14,9 +15,11 @@ object Test {
}

// primitives
test(classOf[Short])
test(classOf[Int])
test(classOf[Long])
'{
${test(classOf[Short])}
${test(classOf[Int])}
${test(classOf[Long])}
}
}

}
7 changes: 2 additions & 5 deletions tests/run-with-compiler/i3947b3.check
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@

scala.Predef.classOf[scala.Float].getCanonicalName()
float

scala.Predef.classOf[scala.Double].getCanonicalName()
double

scala.Predef.classOf[scala.Unit].getCanonicalName()
float
double
void
17 changes: 9 additions & 8 deletions tests/run-with-compiler/i3947b3.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,21 @@ import scala.quoted._

object Test {

def main(args: Array[String]): Unit = {
implicit val toolbox: scala.quoted.Toolbox = scala.quoted.Toolbox.make(getClass.getClassLoader)
def test[T: Type](clazz: java.lang.Class[T]): Unit = run {
implicit val toolbox: scala.quoted.Toolbox = scala.quoted.Toolbox.make(getClass.getClassLoader)

def main(args: Array[String]): Unit = run {
def test[T: Type](clazz: java.lang.Class[T]) = {
val lclazz = clazz.toExpr
val name = '{ ($lclazz).getCanonicalName }
println()
println(name.show)
'{ println($name) }
}

// primitives
test(classOf[Float])
test(classOf[Double])
test(classOf[Unit])
'{
${test(classOf[Float])}
${test(classOf[Double])}
${test(classOf[Unit])}
}
}

}
4 changes: 3 additions & 1 deletion tests/run-with-compiler/i6263.scala
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import quoted._
object Test {

def main(args: Array[String]): Unit = {
implicit val toolbox: scala.quoted.Toolbox = scala.quoted.Toolbox.make(getClass.getClassLoader)

def main(args: Array[String]): Unit = withQuoteContext {
fn("foo")
fn((1,2))
fn(O)
Expand Down