aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/dotty/DottyPredef.scala34
-rw-r--r--src/dotty/tools/dotc/Compiler.scala1
-rw-r--r--src/dotty/tools/dotc/ast/tpd.scala38
-rw-r--r--src/dotty/tools/dotc/core/Definitions.scala3
-rw-r--r--src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala2
-rw-r--r--src/dotty/tools/dotc/transform/ClassOf.scala2
-rw-r--r--src/dotty/tools/dotc/transform/GetClass.scala4
-rw-r--r--src/dotty/tools/dotc/typer/Typer.scala25
8 files changed, 55 insertions, 54 deletions
diff --git a/src/dotty/DottyPredef.scala b/src/dotty/DottyPredef.scala
index 0c2492c94..007493fcb 100644
--- a/src/dotty/DottyPredef.scala
+++ b/src/dotty/DottyPredef.scala
@@ -1,37 +1,13 @@
package dotty
-import scala.reflect.ClassTag
import scala.reflect.runtime.universe.TypeTag
import scala.Predef.???
-abstract class I1 {
- implicit def classTag[T]: ClassTag[T] = ???
+/** unimplemented implicit for TypeTag */
+object DottyPredef {
implicit def typeTag[T]: TypeTag[T] = ???
- implicit val DoubleClassTag: ClassTag[Double] = ClassTag.Double
-}
-abstract class I2 extends I1 {
- implicit val FloatClassTag: ClassTag[Double] = ClassTag.Double
-}
-abstract class I3 extends I2 {
- implicit val LongClassTag: ClassTag[Long] = ClassTag.Long
-}
-abstract class I4 extends I3 {
- implicit val IntClassTag: ClassTag[Int] = ClassTag.Int
-}
-abstract class I5 extends I4 {
- implicit val ShortClassTag: ClassTag[Short] = ClassTag.Short
-}
-abstract class I6 extends I5 {
- implicit val ByteClassTag: ClassTag[Byte] = ClassTag.Byte
- implicit val CharClassTag: ClassTag[Char] = ClassTag.Char
- implicit val BooleanClassTag: ClassTag[Boolean] = ClassTag.Boolean
- implicit val UnitClassTag: ClassTag[Unit] = ClassTag.Unit
- implicit val NullClassTag: ClassTag[Null] = ClassTag.Null
-}
-
-/** implicits for ClassTag and TypeTag. Should be implemented with macros */
-object DottyPredef extends I6 {
- /** ClassTags for final classes */
- implicit val NothingClassTag: ClassTag[Nothing] = ClassTag.Nothing
+// not yet:
+// def classOf[T](implicit ctag: ClassTag[T]): Class[T] =
+// ctag.runtimeClass
}
diff --git a/src/dotty/tools/dotc/Compiler.scala b/src/dotty/tools/dotc/Compiler.scala
index 99b7bd880..7c7648657 100644
--- a/src/dotty/tools/dotc/Compiler.scala
+++ b/src/dotty/tools/dotc/Compiler.scala
@@ -59,7 +59,6 @@ class Compiler {
new SeqLiterals,
new InterceptedMethods,
new Getters,
- new ClassTags,
new ElimByName,
new AugmentScala2Traits,
new ResolveSuper),
diff --git a/src/dotty/tools/dotc/ast/tpd.scala b/src/dotty/tools/dotc/ast/tpd.scala
index 8e52d695b..7cd469d7a 100644
--- a/src/dotty/tools/dotc/ast/tpd.scala
+++ b/src/dotty/tools/dotc/ast/tpd.scala
@@ -777,27 +777,6 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
}
else Assign(tree, rhs)
- /** A tree in place of this tree that represents the class of type `tp`.
- * Contains special handling if the class is a primitive value class
- * and invokes a `default` method otherwise.
- */
- def clsOf(tp: Type, default: => Tree)(implicit ctx: Context): Tree = {
- def TYPE(module: TermSymbol) =
- ref(module).select(nme.TYPE_).ensureConforms(tree.tpe).withPos(tree.pos)
- defn.scalaClassName(tp) match {
- case tpnme.Boolean => TYPE(defn.BoxedBooleanModule)
- case tpnme.Byte => TYPE(defn.BoxedByteModule)
- case tpnme.Short => TYPE(defn.BoxedShortModule)
- case tpnme.Char => TYPE(defn.BoxedCharModule)
- case tpnme.Int => TYPE(defn.BoxedIntModule)
- case tpnme.Long => TYPE(defn.BoxedLongModule)
- case tpnme.Float => TYPE(defn.BoxedFloatModule)
- case tpnme.Double => TYPE(defn.BoxedDoubleModule)
- case tpnme.Unit => TYPE(defn.BoxedUnitModule)
- case _ => default
- }
- }
-
// --- Higher order traversal methods -------------------------------
/** Apply `f` to each subtree of this tree */
@@ -842,6 +821,23 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
}
}
+ /** A tree that represents the class of the erasure of type `tp`. */
+ def clsOf(tp: Type)(implicit ctx: Context): Tree = {
+ def TYPE(module: TermSymbol) = ref(module).select(nme.TYPE_)
+ defn.scalaClassName(tp) match {
+ case tpnme.Boolean => TYPE(defn.BoxedBooleanModule)
+ case tpnme.Byte => TYPE(defn.BoxedByteModule)
+ case tpnme.Short => TYPE(defn.BoxedShortModule)
+ case tpnme.Char => TYPE(defn.BoxedCharModule)
+ case tpnme.Int => TYPE(defn.BoxedIntModule)
+ case tpnme.Long => TYPE(defn.BoxedLongModule)
+ case tpnme.Float => TYPE(defn.BoxedFloatModule)
+ case tpnme.Double => TYPE(defn.BoxedDoubleModule)
+ case tpnme.Unit => TYPE(defn.BoxedUnitModule)
+ case _ => Literal(Constant(TypeErasure.erasure(tp)))
+ }
+ }
+
def applyOverloaded(receiver: Tree, method: TermName, args: List[Tree], targs: List[Type], expectedType: Type, isAnnotConstructor: Boolean = false)(implicit ctx: Context): Tree = {
val typer = ctx.typer
val proto = new FunProtoTyped(args, expectedType, typer)
diff --git a/src/dotty/tools/dotc/core/Definitions.scala b/src/dotty/tools/dotc/core/Definitions.scala
index c5d42a472..188a00fc2 100644
--- a/src/dotty/tools/dotc/core/Definitions.scala
+++ b/src/dotty/tools/dotc/core/Definitions.scala
@@ -419,6 +419,9 @@ class Definitions {
lazy val LanguageModuleRef = ctx.requiredModule("dotty.language")
def LanguageModuleClass(implicit ctx: Context) = LanguageModuleRef.symbol.moduleClass.asClass
lazy val NonLocalReturnControlType: TypeRef = ctx.requiredClassRef("scala.runtime.NonLocalReturnControl")
+ lazy val ClassTagType = ctx.requiredClassRef("scala.reflect.ClassTag")
+ def ClassTagClass(implicit ctx: Context) = ClassTagType.symbol.asClass
+ def ClassTagModule(implicit ctx: Context) = ClassTagClass.companionModule
// Annotation base classes
lazy val AnnotationType = ctx.requiredClassRef("scala.annotation.Annotation")
diff --git a/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala b/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala
index 81d19f7e4..16caac02e 100644
--- a/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala
+++ b/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala
@@ -290,6 +290,8 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table) {
ConstantType(Constant(readName().toString))
case NULLconst =>
ConstantType(Constant(null))
+ case CLASSconst =>
+ ConstantType(Constant(readType()))
case BYNAMEtype =>
ExprType(readType())
}
diff --git a/src/dotty/tools/dotc/transform/ClassOf.scala b/src/dotty/tools/dotc/transform/ClassOf.scala
index 51a68f903..f8f4991c8 100644
--- a/src/dotty/tools/dotc/transform/ClassOf.scala
+++ b/src/dotty/tools/dotc/transform/ClassOf.scala
@@ -31,7 +31,7 @@ class ClassOf extends MiniPhaseTransform {
override def transformTypeApply(tree: TypeApply)(implicit ctx: Context, info: TransformerInfo): Tree =
if (tree.symbol eq classOfMethod) {
val targ = tree.args.head.tpe
- tree.clsOf(targ, Literal(Constant(TypeErasure.erasure(targ))))
+ clsOf(targ).ensureConforms(tree.tpe).withPos(tree.pos)
}
else tree
}
diff --git a/src/dotty/tools/dotc/transform/GetClass.scala b/src/dotty/tools/dotc/transform/GetClass.scala
index 9d182382d..f25fd6f64 100644
--- a/src/dotty/tools/dotc/transform/GetClass.scala
+++ b/src/dotty/tools/dotc/transform/GetClass.scala
@@ -5,6 +5,7 @@ import ast.tpd
import core.Contexts.Context
import core.StdNames.nme
import core.Phases.Phase
+import TypeUtils._
import TreeTransforms.{MiniPhaseTransform, TransformerInfo}
/** Rewrite `getClass` calls as follow:
@@ -24,7 +25,8 @@ class GetClass extends MiniPhaseTransform {
override def transformApply(tree: Apply)(implicit ctx: Context, info: TransformerInfo): Tree = {
import ast.Trees._
tree match {
- case Apply(Select(qual, nme.getClass_), Nil) => tree.clsOf(qual.tpe.widen, tree)
+ case Apply(Select(qual, nme.getClass_), Nil) if qual.tpe.widen.isPrimitiveValueType =>
+ clsOf(qual.tpe.widen).withPos(tree.pos)
case _ => tree
}
}
diff --git a/src/dotty/tools/dotc/typer/Typer.scala b/src/dotty/tools/dotc/typer/Typer.scala
index fc2bf2381..445037228 100644
--- a/src/dotty/tools/dotc/typer/Typer.scala
+++ b/src/dotty/tools/dotc/typer/Typer.scala
@@ -1477,7 +1477,9 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
case ambi: AmbiguousImplicits =>
implicitArgError(s"ambiguous implicits: ${ambi.explanation} of $where")
case failure: SearchFailure =>
- implicitArgError(d"no implicit argument of type $formal found for $where" + failure.postscript)
+ val arg = synthesizedClassTag(formal)
+ if (!arg.isEmpty) arg
+ else implicitArgError(d"no implicit argument of type $formal found for $where" + failure.postscript)
}
}
if (errors.nonEmpty) {
@@ -1538,6 +1540,27 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
}
}
+ /** If `formal` is of the form ClassTag[T], where `T` is a class type,
+ * synthesize a class tag for `T`.
+ */
+ def synthesizedClassTag(formal: Type): Tree = {
+ if (formal.isRef(defn.ClassTagClass))
+ formal.argTypes match {
+ case arg :: Nil =>
+ arg.underlyingClassRef(refinementOK = false) match {
+ case tref: TypeRef =>
+ return ref(defn.ClassTagModule)
+ .select(nme.apply)
+ .appliedToType(arg)
+ .appliedTo(clsOf(tref))
+ .withPos(tree.pos.endPos)
+ case _ =>
+ }
+ case _ =>
+ }
+ EmptyTree
+ }
+
/** Adapt an expression of constant type to a different constant type `tpe`. */
def adaptConstant(tree: Tree, tpe: ConstantType): Tree = {
def lit = Literal(tpe.value).withPos(tree.pos)