diff --git a/compiler/src/dotty/tools/dotc/core/quoted/PickledQuotes.scala b/compiler/src/dotty/tools/dotc/core/quoted/PickledQuotes.scala index b08ee8f961af..53d0f748d6e2 100644 --- a/compiler/src/dotty/tools/dotc/core/quoted/PickledQuotes.scala +++ b/compiler/src/dotty/tools/dotc/core/quoted/PickledQuotes.scala @@ -121,13 +121,14 @@ object PickledQuotes { 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.FloatType + case ClassTag.Double => defn.DoubleType } TypeTree(tpe) } diff --git a/compiler/src/dotty/tools/dotc/transform/ReifyQuotes.scala b/compiler/src/dotty/tools/dotc/transform/ReifyQuotes.scala index 66b4620405bd..600a1041dd81 100644 --- a/compiler/src/dotty/tools/dotc/transform/ReifyQuotes.scala +++ b/compiler/src/dotty/tools/dotc/transform/ReifyQuotes.scala @@ -352,6 +352,19 @@ class ReifyQuotes extends MacroTransformWithImplicits { liftList(splices, defn.AnyType)) } if (splices.nonEmpty) pickleAsTasty() + else if (isType) { + def tag(tagName: String) = ref(defn.QuotedTypeModule).select(tagName.toTermName) + if (body.symbol == defn.UnitClass) tag("UnitTag") + else if (body.symbol == defn.BooleanClass) tag("BooleanTag") + else if (body.symbol == defn.ByteClass) tag("ByteTag") + else if (body.symbol == defn.CharClass) tag("CharTag") + else if (body.symbol == defn.ShortClass) tag("ShortTag") + else if (body.symbol == defn.IntClass) tag("IntTag") + else if (body.symbol == defn.LongClass) tag("LongTag") + else if (body.symbol == defn.FloatClass) tag("FloatTag") + else if (body.symbol == defn.DoubleClass) tag("DoubleTag") + else pickleAsTasty() + } else ReifyQuotes.toValue(body) match { case Some(value) => pickleAsValue(value) case _ => pickleAsTasty() diff --git a/compiler/src/dotty/tools/dotc/typer/Implicits.scala b/compiler/src/dotty/tools/dotc/typer/Implicits.scala index f11f75b704c4..b9bca83a70d9 100644 --- a/compiler/src/dotty/tools/dotc/typer/Implicits.scala +++ b/compiler/src/dotty/tools/dotc/typer/Implicits.scala @@ -554,11 +554,15 @@ trait Implicits { self: Typer => val etag = inferImplicitArg(defn.ClassTagType.appliedTo(elemTp), pos) if (etag.tpe.isError) EmptyTree else etag.select(nme.wrap) case tp if hasStableErasure(tp) && !defn.isBottomClass(tp.typeSymbol) => - ref(defn.ClassTagModule) - .select(nme.apply) - .appliedToType(tp) - .appliedTo(clsOf(erasure(tp))) - .withPos(pos) + val sym = tp.typeSymbol + if (sym == defn.UnitClass || sym == defn.AnyClass || sym == defn.AnyValClass) + ref(defn.ClassTagModule).select(sym.name.toTermName).withPos(pos) + else + ref(defn.ClassTagModule) + .select(nme.apply) + .appliedToType(tp) + .appliedTo(clsOf(erasure(tp))) + .withPos(pos) case tp => EmptyTree } diff --git a/tests/run-with-compiler/quote-type-tags.check b/tests/run-with-compiler/quote-type-tags.check new file mode 100644 index 000000000000..240429f8eb10 --- /dev/null +++ b/tests/run-with-compiler/quote-type-tags.check @@ -0,0 +1,10 @@ +().asInstanceOf[Unit] +true.asInstanceOf[Boolean] +0.toByte.asInstanceOf[Byte] +'a'.asInstanceOf[Char] +1.toShort.asInstanceOf[Short] +2.asInstanceOf[Int] +3L.asInstanceOf[Long] +4.0.asInstanceOf[Float] +5.0.asInstanceOf[Double] +5.0.asInstanceOf[Boolean] diff --git a/tests/run-with-compiler/quote-type-tags.scala b/tests/run-with-compiler/quote-type-tags.scala new file mode 100644 index 000000000000..4a2bb94300de --- /dev/null +++ b/tests/run-with-compiler/quote-type-tags.scala @@ -0,0 +1,23 @@ + +import dotty.tools.dotc.quoted.Toolbox._ + +import scala.quoted._ + +object Test { + def main(args: Array[String]): Unit = { + def asof[T, U](x: Expr[T], t: Type[U]): Expr[U] = + '((~x).asInstanceOf[~t]) + + println(asof('(), '[Unit]).show) + println(asof('(true), '[Boolean]).show) + println(asof('(0.toByte), '[Byte]).show) + println(asof('( 'a' ), '[Char]).show) + println(asof('(1.toShort), '[Short]).show) + println(asof('(2), '[Int]).show) + println(asof('(3L), '[Long]).show) + println(asof('(4f), '[Float]).show) + println(asof('(5d), '[Double]).show) + + println(asof('(5d), '[Boolean]).show) // Will clearly fail at runtime but the code can be generated + } +} diff --git a/tests/run/i4205.check b/tests/run/i4205.check new file mode 100644 index 000000000000..f6ac2ed0f7d1 --- /dev/null +++ b/tests/run/i4205.check @@ -0,0 +1,14 @@ +true +true +true +true +true +true +true +true +true +true +true +true +true +true diff --git a/tests/run/i4205.scala b/tests/run/i4205.scala new file mode 100644 index 000000000000..bb106535ee8c --- /dev/null +++ b/tests/run/i4205.scala @@ -0,0 +1,22 @@ +import scala.reflect.ClassTag +import scala.runtime.BoxedUnit + +object Test { + def main(args: Array[String]): Unit = { + println(implicitly[ClassTag[Unit]] == ClassTag.Unit) + println(implicitly[ClassTag[Boolean]] == ClassTag.Boolean) + println(implicitly[ClassTag[Byte]] == ClassTag.Byte) + println(implicitly[ClassTag[Char]] == ClassTag.Char) + println(implicitly[ClassTag[Short]] == ClassTag.Short) + println(implicitly[ClassTag[Int]] == ClassTag.Int) + println(implicitly[ClassTag[Long]] == ClassTag.Long) + println(implicitly[ClassTag[Float]] == ClassTag.Float) + println(implicitly[ClassTag[Double]] == ClassTag.Double) + println(implicitly[ClassTag[Object]] == ClassTag.Object) + println(implicitly[ClassTag[Any]] == ClassTag.Any) + println(implicitly[ClassTag[AnyRef]] == ClassTag.AnyRef) + println(implicitly[ClassTag[AnyVal]] == ClassTag.AnyVal) + + println(implicitly[ClassTag[BoxedUnit]] != ClassTag.Unit) + } +}