Skip to content

Commit baedc50

Browse files
Merge pull request #4204 from dotty-staging/fix-quoted-type-tags
Fix quoted type tags and use them instead of pickling
2 parents c756919 + 6080d06 commit baedc50

File tree

7 files changed

+93
-6
lines changed

7 files changed

+93
-6
lines changed

compiler/src/dotty/tools/dotc/core/quoted/PickledQuotes.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,13 +128,14 @@ object PickledQuotes {
128128
private def classTagToTypeTree(ct: ClassTag[_])(implicit ctx: Context): TypeTree = {
129129
val tpe = ct match {
130130
case ClassTag.Unit => defn.UnitType
131+
case ClassTag.Boolean => defn.BooleanType
131132
case ClassTag.Byte => defn.ByteType
132133
case ClassTag.Char => defn.CharType
133134
case ClassTag.Short => defn.ShortType
134135
case ClassTag.Int => defn.IntType
135136
case ClassTag.Long => defn.LongType
136137
case ClassTag.Float => defn.FloatType
137-
case ClassTag.Double => defn.FloatType
138+
case ClassTag.Double => defn.DoubleType
138139
}
139140
TypeTree(tpe)
140141
}

compiler/src/dotty/tools/dotc/transform/ReifyQuotes.scala

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -395,6 +395,19 @@ class ReifyQuotes extends MacroTransformWithImplicits with InfoTransformer {
395395
liftList(splices, defn.AnyType))
396396
}
397397
if (splices.nonEmpty) pickleAsTasty()
398+
else if (isType) {
399+
def tag(tagName: String) = ref(defn.QuotedTypeModule).select(tagName.toTermName)
400+
if (body.symbol == defn.UnitClass) tag("UnitTag")
401+
else if (body.symbol == defn.BooleanClass) tag("BooleanTag")
402+
else if (body.symbol == defn.ByteClass) tag("ByteTag")
403+
else if (body.symbol == defn.CharClass) tag("CharTag")
404+
else if (body.symbol == defn.ShortClass) tag("ShortTag")
405+
else if (body.symbol == defn.IntClass) tag("IntTag")
406+
else if (body.symbol == defn.LongClass) tag("LongTag")
407+
else if (body.symbol == defn.FloatClass) tag("FloatTag")
408+
else if (body.symbol == defn.DoubleClass) tag("DoubleTag")
409+
else pickleAsTasty()
410+
}
398411
else ReifyQuotes.toValue(body) match {
399412
case Some(value) => pickleAsValue(value)
400413
case _ => pickleAsTasty()

compiler/src/dotty/tools/dotc/typer/Implicits.scala

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -554,11 +554,15 @@ trait Implicits { self: Typer =>
554554
val etag = inferImplicitArg(defn.ClassTagType.appliedTo(elemTp), pos)
555555
if (etag.tpe.isError) EmptyTree else etag.select(nme.wrap)
556556
case tp if hasStableErasure(tp) && !defn.isBottomClass(tp.typeSymbol) =>
557-
ref(defn.ClassTagModule)
558-
.select(nme.apply)
559-
.appliedToType(tp)
560-
.appliedTo(clsOf(erasure(tp)))
561-
.withPos(pos)
557+
val sym = tp.typeSymbol
558+
if (sym == defn.UnitClass || sym == defn.AnyClass || sym == defn.AnyValClass)
559+
ref(defn.ClassTagModule).select(sym.name.toTermName).withPos(pos)
560+
else
561+
ref(defn.ClassTagModule)
562+
.select(nme.apply)
563+
.appliedToType(tp)
564+
.appliedTo(clsOf(erasure(tp)))
565+
.withPos(pos)
562566
case tp =>
563567
EmptyTree
564568
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
().asInstanceOf[Unit]
2+
true.asInstanceOf[Boolean]
3+
0.toByte.asInstanceOf[Byte]
4+
'a'.asInstanceOf[Char]
5+
1.toShort.asInstanceOf[Short]
6+
2.asInstanceOf[Int]
7+
3L.asInstanceOf[Long]
8+
4.0.asInstanceOf[Float]
9+
5.0.asInstanceOf[Double]
10+
5.0.asInstanceOf[Boolean]
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
2+
import dotty.tools.dotc.quoted.Toolbox._
3+
4+
import scala.quoted._
5+
6+
object Test {
7+
def main(args: Array[String]): Unit = {
8+
def asof[T, U](x: Expr[T], t: Type[U]): Expr[U] =
9+
'((~x).asInstanceOf[~t])
10+
11+
println(asof('(), '[Unit]).show)
12+
println(asof('(true), '[Boolean]).show)
13+
println(asof('(0.toByte), '[Byte]).show)
14+
println(asof('( 'a' ), '[Char]).show)
15+
println(asof('(1.toShort), '[Short]).show)
16+
println(asof('(2), '[Int]).show)
17+
println(asof('(3L), '[Long]).show)
18+
println(asof('(4f), '[Float]).show)
19+
println(asof('(5d), '[Double]).show)
20+
21+
println(asof('(5d), '[Boolean]).show) // Will clearly fail at runtime but the code can be generated
22+
}
23+
}

tests/run/i4205.check

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
true
2+
true
3+
true
4+
true
5+
true
6+
true
7+
true
8+
true
9+
true
10+
true
11+
true
12+
true
13+
true
14+
true

tests/run/i4205.scala

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import scala.reflect.ClassTag
2+
import scala.runtime.BoxedUnit
3+
4+
object Test {
5+
def main(args: Array[String]): Unit = {
6+
println(implicitly[ClassTag[Unit]] == ClassTag.Unit)
7+
println(implicitly[ClassTag[Boolean]] == ClassTag.Boolean)
8+
println(implicitly[ClassTag[Byte]] == ClassTag.Byte)
9+
println(implicitly[ClassTag[Char]] == ClassTag.Char)
10+
println(implicitly[ClassTag[Short]] == ClassTag.Short)
11+
println(implicitly[ClassTag[Int]] == ClassTag.Int)
12+
println(implicitly[ClassTag[Long]] == ClassTag.Long)
13+
println(implicitly[ClassTag[Float]] == ClassTag.Float)
14+
println(implicitly[ClassTag[Double]] == ClassTag.Double)
15+
println(implicitly[ClassTag[Object]] == ClassTag.Object)
16+
println(implicitly[ClassTag[Any]] == ClassTag.Any)
17+
println(implicitly[ClassTag[AnyRef]] == ClassTag.AnyRef)
18+
println(implicitly[ClassTag[AnyVal]] == ClassTag.AnyVal)
19+
20+
println(implicitly[ClassTag[BoxedUnit]] != ClassTag.Unit)
21+
}
22+
}

0 commit comments

Comments
 (0)