aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/dotty/tools/dotc/Compiler.scala3
-rw-r--r--src/dotty/tools/dotc/core/Definitions.scala10
-rw-r--r--src/dotty/tools/dotc/transform/ClassOf.scala54
-rw-r--r--tests/run/classof.check (renamed from tests/pending/run/classof.check)1
-rw-r--r--tests/run/classof.scala (renamed from tests/pending/run/classof.scala)5
5 files changed, 72 insertions, 1 deletions
diff --git a/src/dotty/tools/dotc/Compiler.scala b/src/dotty/tools/dotc/Compiler.scala
index 386f976cf..a10201bd0 100644
--- a/src/dotty/tools/dotc/Compiler.scala
+++ b/src/dotty/tools/dotc/Compiler.scala
@@ -46,7 +46,8 @@ class Compiler {
new NormalizeFlags,
new ExtensionMethods,
new ExpandSAMs,
- new TailRec),
+ new TailRec,
+ new ClassOf),
List(new PatternMatcher,
new ExplicitOuter,
new Splitter),
diff --git a/src/dotty/tools/dotc/core/Definitions.scala b/src/dotty/tools/dotc/core/Definitions.scala
index fdeee82de..e3348d4f3 100644
--- a/src/dotty/tools/dotc/core/Definitions.scala
+++ b/src/dotty/tools/dotc/core/Definitions.scala
@@ -271,6 +271,16 @@ class Definitions {
lazy val BoxedFloatClass = ctx.requiredClass("java.lang.Float")
lazy val BoxedDoubleClass = ctx.requiredClass("java.lang.Double")
+ lazy val BoxedBooleanModule = ctx.requiredModule("java.lang.Boolean")
+ lazy val BoxedByteModule = ctx.requiredModule("java.lang.Byte")
+ lazy val BoxedShortModule = ctx.requiredModule("java.lang.Short")
+ lazy val BoxedCharModule = ctx.requiredModule("java.lang.Character")
+ lazy val BoxedIntModule = ctx.requiredModule("java.lang.Integer")
+ lazy val BoxedLongModule = ctx.requiredModule("java.lang.Long")
+ lazy val BoxedFloatModule = ctx.requiredModule("java.lang.Float")
+ lazy val BoxedDoubleModule = ctx.requiredModule("java.lang.Double")
+ lazy val BoxedVoidModule = ctx.requiredModule("java.lang.Void")
+
lazy val ByNameParamClass2x = specialPolyClass(tpnme.BYNAME_PARAM_CLASS, Covariant, AnyType)
lazy val EqualsPatternClass = specialPolyClass(tpnme.EQUALS_PATTERN, EmptyFlags, AnyType)
diff --git a/src/dotty/tools/dotc/transform/ClassOf.scala b/src/dotty/tools/dotc/transform/ClassOf.scala
new file mode 100644
index 000000000..948e0117b
--- /dev/null
+++ b/src/dotty/tools/dotc/transform/ClassOf.scala
@@ -0,0 +1,54 @@
+package dotty.tools.dotc
+package transform
+
+import ast.tpd
+import core.Constants.Constant
+import core.Contexts.Context
+import core.StdNames.nme
+import core.Symbols.TermSymbol
+import core.TypeErasure
+import TreeTransforms.{MiniPhaseTransform, TransformerInfo, TreeTransform}
+
+/** Performs rewritings as follows for `classOf` calls:
+ * classOf[CustomValueClass] ~> CustomValueClass class
+ * classOf[ValueClass] ~> ValueClass class, where ValueClass is Boolean, Byte, Short, etc.
+ * classOf[AnyOtherClass] ~> erasure(AnyOtherClass)
+ */
+class ClassOf extends MiniPhaseTransform {
+ import tpd._
+
+ override def phaseName: String = "classOf"
+
+ private var classOfMethod: TermSymbol = _
+
+ override def prepareForUnit(tree: tpd.Tree)(implicit ctx: Context): TreeTransform = {
+ val predefModule = ctx.definitions.ScalaPredefModule
+ classOfMethod = ctx.requiredMethod(predefModule.moduleClass.asClass, nme.classOf)
+ this
+ }
+
+ override def transformTypeApply(tree: TypeApply)(implicit ctx: Context, info: TransformerInfo): Tree = {
+ if (tree.symbol eq classOfMethod) {
+ val tp = tree.args.head.tpe
+ val defn = ctx.definitions
+ val claz = tp.classSymbol
+ if (ValueClasses.isDerivedValueClass(claz)) {
+ Literal(Constant(ref(claz).tpe))
+ } else {
+ def TYPE(module: TermSymbol) = ref(module).select(nme.TYPE_).ensureConforms(tree.tpe)
+ claz match {
+ case defn.BooleanClass => TYPE(defn.BoxedBooleanModule)
+ case defn.ByteClass => TYPE(defn.BoxedByteModule)
+ case defn.ShortClass => TYPE(defn.BoxedShortModule)
+ case defn.CharClass => TYPE(defn.BoxedCharModule)
+ case defn.IntClass => TYPE(defn.BoxedIntModule)
+ case defn.LongClass => TYPE(defn.BoxedLongModule)
+ case defn.FloatClass => TYPE(defn.BoxedFloatModule)
+ case defn.DoubleClass => TYPE(defn.BoxedDoubleModule)
+ case defn.UnitClass => TYPE(defn.BoxedVoidModule)
+ case _ => Literal(Constant(TypeErasure.erasure(tp)))
+ }
+ }
+ } else tree
+ }
+}
diff --git a/tests/pending/run/classof.check b/tests/run/classof.check
index 83e292352..9476c014d 100644
--- a/tests/pending/run/classof.check
+++ b/tests/run/classof.check
@@ -10,6 +10,7 @@ float
double
Class types
class SomeClass
+class ValueClass
class scala.collection.immutable.List
class scala.Tuple2
Arrays:
diff --git a/tests/pending/run/classof.scala b/tests/run/classof.scala
index 257829e97..bdbcef4a1 100644
--- a/tests/pending/run/classof.scala
+++ b/tests/run/classof.scala
@@ -1,8 +1,12 @@
+class ValueClass(val i: Integer) extends AnyVal
class SomeClass
object Test {
def main(args: Array[String]): Unit = {
val cls: Predef.Class[SomeClass] = classOf[SomeClass]
+ val valCls: Predef.Class[ValueClass] = classOf[ValueClass]
+ val iCls: Class[Int] = classOf[Int]
+
println("Value types:")
println(classOf[Unit])
println(classOf[Boolean])
@@ -16,6 +20,7 @@ object Test {
println("Class types")
println(classOf[SomeClass])
+ println(classOf[ValueClass])
println(classOf[List[Array[Float]]])
println(classOf[(String, Map[Int, String])])