Skip to content

Commit 0fba875

Browse files
committed
Merge pull request #677 from alexander-myltsev/am-579-implement_class_of
Closes #579 Implement mini-phase for classOf[T]
2 parents d2c96d0 + 12caa2f commit 0fba875

File tree

5 files changed

+72
-1
lines changed

5 files changed

+72
-1
lines changed

src/dotty/tools/dotc/Compiler.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,8 @@ class Compiler {
4646
new NormalizeFlags,
4747
new ExtensionMethods,
4848
new ExpandSAMs,
49-
new TailRec),
49+
new TailRec,
50+
new ClassOf),
5051
List(new PatternMatcher,
5152
new ExplicitOuter,
5253
new Splitter),

src/dotty/tools/dotc/core/Definitions.scala

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,16 @@ class Definitions {
271271
lazy val BoxedFloatClass = ctx.requiredClass("java.lang.Float")
272272
lazy val BoxedDoubleClass = ctx.requiredClass("java.lang.Double")
273273

274+
lazy val BoxedBooleanModule = ctx.requiredModule("java.lang.Boolean")
275+
lazy val BoxedByteModule = ctx.requiredModule("java.lang.Byte")
276+
lazy val BoxedShortModule = ctx.requiredModule("java.lang.Short")
277+
lazy val BoxedCharModule = ctx.requiredModule("java.lang.Character")
278+
lazy val BoxedIntModule = ctx.requiredModule("java.lang.Integer")
279+
lazy val BoxedLongModule = ctx.requiredModule("java.lang.Long")
280+
lazy val BoxedFloatModule = ctx.requiredModule("java.lang.Float")
281+
lazy val BoxedDoubleModule = ctx.requiredModule("java.lang.Double")
282+
lazy val BoxedVoidModule = ctx.requiredModule("java.lang.Void")
283+
274284
lazy val ByNameParamClass2x = specialPolyClass(tpnme.BYNAME_PARAM_CLASS, Covariant, AnyType)
275285
lazy val EqualsPatternClass = specialPolyClass(tpnme.EQUALS_PATTERN, EmptyFlags, AnyType)
276286

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
package dotty.tools.dotc
2+
package transform
3+
4+
import ast.tpd
5+
import core.Constants.Constant
6+
import core.Contexts.Context
7+
import core.StdNames.nme
8+
import core.Symbols.TermSymbol
9+
import core.TypeErasure
10+
import TreeTransforms.{MiniPhaseTransform, TransformerInfo, TreeTransform}
11+
12+
/** Performs rewritings as follows for `classOf` calls:
13+
* classOf[CustomValueClass] ~> CustomValueClass class
14+
* classOf[ValueClass] ~> ValueClass class, where ValueClass is Boolean, Byte, Short, etc.
15+
* classOf[AnyOtherClass] ~> erasure(AnyOtherClass)
16+
*/
17+
class ClassOf extends MiniPhaseTransform {
18+
import tpd._
19+
20+
override def phaseName: String = "classOf"
21+
22+
private var classOfMethod: TermSymbol = _
23+
24+
override def prepareForUnit(tree: tpd.Tree)(implicit ctx: Context): TreeTransform = {
25+
val predefModule = ctx.definitions.ScalaPredefModule
26+
classOfMethod = ctx.requiredMethod(predefModule.moduleClass.asClass, nme.classOf)
27+
this
28+
}
29+
30+
override def transformTypeApply(tree: TypeApply)(implicit ctx: Context, info: TransformerInfo): Tree = {
31+
if (tree.symbol eq classOfMethod) {
32+
val tp = tree.args.head.tpe
33+
val defn = ctx.definitions
34+
val claz = tp.classSymbol
35+
if (ValueClasses.isDerivedValueClass(claz)) {
36+
Literal(Constant(ref(claz).tpe))
37+
} else {
38+
def TYPE(module: TermSymbol) = ref(module).select(nme.TYPE_).ensureConforms(tree.tpe)
39+
claz match {
40+
case defn.BooleanClass => TYPE(defn.BoxedBooleanModule)
41+
case defn.ByteClass => TYPE(defn.BoxedByteModule)
42+
case defn.ShortClass => TYPE(defn.BoxedShortModule)
43+
case defn.CharClass => TYPE(defn.BoxedCharModule)
44+
case defn.IntClass => TYPE(defn.BoxedIntModule)
45+
case defn.LongClass => TYPE(defn.BoxedLongModule)
46+
case defn.FloatClass => TYPE(defn.BoxedFloatModule)
47+
case defn.DoubleClass => TYPE(defn.BoxedDoubleModule)
48+
case defn.UnitClass => TYPE(defn.BoxedVoidModule)
49+
case _ => Literal(Constant(TypeErasure.erasure(tp)))
50+
}
51+
}
52+
} else tree
53+
}
54+
}

tests/pending/run/classof.check renamed to tests/run/classof.check

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ float
1010
double
1111
Class types
1212
class SomeClass
13+
class ValueClass
1314
class scala.collection.immutable.List
1415
class scala.Tuple2
1516
Arrays:

tests/pending/run/classof.scala renamed to tests/run/classof.scala

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
1+
class ValueClass(val i: Integer) extends AnyVal
12
class SomeClass
23

34
object Test {
45
def main(args: Array[String]): Unit = {
56
val cls: Predef.Class[SomeClass] = classOf[SomeClass]
7+
val valCls: Predef.Class[ValueClass] = classOf[ValueClass]
8+
val iCls: Class[Int] = classOf[Int]
9+
610
println("Value types:")
711
println(classOf[Unit])
812
println(classOf[Boolean])
@@ -16,6 +20,7 @@ object Test {
1620

1721
println("Class types")
1822
println(classOf[SomeClass])
23+
println(classOf[ValueClass])
1924
println(classOf[List[Array[Float]]])
2025
println(classOf[(String, Map[Int, String])])
2126

0 commit comments

Comments
 (0)