aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2016-02-18 14:07:03 +0100
committerMartin Odersky <odersky@gmail.com>2016-02-20 10:19:56 +0100
commite4989b3cc13f70d8316790e309b5d3b27317d80e (patch)
treef0e2492607d221323585924a003cb57ab665c54e /src/dotty/tools
parentf6391c780ce7472352b60da9fdd7ec8d7496a0ea (diff)
downloaddotty-e4989b3cc13f70d8316790e309b5d3b27317d80e.tar.gz
dotty-e4989b3cc13f70d8316790e309b5d3b27317d80e.tar.bz2
dotty-e4989b3cc13f70d8316790e309b5d3b27317d80e.zip
Synthesize classTags in Typer.
Now diagnoses missing ClassTags of abstract types as implicit failures. Also: Simpler API of tpd.clsOf.
Diffstat (limited to 'src/dotty/tools')
-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
7 files changed, 50 insertions, 25 deletions
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)