diff options
-rw-r--r-- | src/dotty/tools/dotc/Compiler.scala | 3 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/Definitions.scala | 10 | ||||
-rw-r--r-- | src/dotty/tools/dotc/transform/ClassOf.scala | 54 | ||||
-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])]) |