aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc/transform/PostTyper.scala
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2015-04-22 13:15:11 +0200
committerMartin Odersky <odersky@gmail.com>2015-04-22 17:19:35 +0200
commit7e60221120015be2607947f2de55ca4984db7077 (patch)
treeec04ad69cb812a9fe3ceb29eb2f1bbc55d2491b9 /src/dotty/tools/dotc/transform/PostTyper.scala
parent158c9632e9138a91a47ce13386bce0ab41db434b (diff)
downloaddotty-7e60221120015be2607947f2de55ca4984db7077.tar.gz
dotty-7e60221120015be2607947f2de55ca4984db7077.tar.bz2
dotty-7e60221120015be2607947f2de55ca4984db7077.zip
Roll InstChecks into PostTyper
Move InstChecks functionality into PostTyper in order to save a separate traversal.
Diffstat (limited to 'src/dotty/tools/dotc/transform/PostTyper.scala')
-rw-r--r--src/dotty/tools/dotc/transform/PostTyper.scala89
1 files changed, 76 insertions, 13 deletions
diff --git a/src/dotty/tools/dotc/transform/PostTyper.scala b/src/dotty/tools/dotc/transform/PostTyper.scala
index 4ad2cef01..98c110e11 100644
--- a/src/dotty/tools/dotc/transform/PostTyper.scala
+++ b/src/dotty/tools/dotc/transform/PostTyper.scala
@@ -7,7 +7,7 @@ import scala.collection.{ mutable, immutable }
import ValueClasses._
import scala.annotation.tailrec
import core._
-import typer.InstChecks
+import typer.ErrorReporting._
import Types._, Contexts._, Constants._, Names._, NameOps._, Flags._, DenotTransformers._
import SymDenotations._, Symbols._, StdNames._, Annotations._, Trees._, Scopes._, Denotations._
import util.Positions._
@@ -22,6 +22,8 @@ import Symbols._, TypeUtils._
* public parameter field in a superclass to a forwarder to the superclass
* field (corresponding = super class field is initialized with subclass field)
* (@see ForwardParamAccessors)
+ *
+ * (3) Check that `New` nodes can be instantiated, and that annotations are valid
*
* The reason for making this a macro transform is that some functions (in particular
* super and protected accessors and instantiation checks) are naturally top-down and
@@ -44,28 +46,89 @@ class PostTyper extends MacroTransform with IdentityDenotTransformer { thisTran
val superAcc = new SuperAccessors(thisTransformer)
val paramFwd = new ParamForwarding(thisTransformer)
-// val instChecks = new InstChecks
+
+ /** Check that `tp` refers to a nonAbstract class
+ * and that the instance conforms to the self type of the created class.
+ */
+ private def checkInstantiable(tp: Type, pos: Position)(implicit ctx: Context): Unit =
+ tp.underlyingClassRef(refinementOK = false) match {
+ case tref: TypeRef =>
+ val cls = tref.symbol
+ if (cls.is(AbstractOrTrait))
+ ctx.error(d"$cls is abstract; cannot be instantiated", pos)
+ if (!cls.is(Module)) {
+ val selfType = tp.givenSelfType.asSeenFrom(tref.prefix, cls.owner)
+ if (selfType.exists && !(tp <:< selfType))
+ ctx.error(d"$tp does not conform to its self type $selfType; cannot be instantiated")
+ }
+ case _ =>
+ }
+
+ private def newPart(tree: Tree): Option[New] = methPart(tree) match {
+ case Select(nu: New, _) => Some(nu)
+ case _ => None
+ }
+
+ private def checkValidJavaAnnotation(annot: Tree)(implicit ctx: Context): Unit = {
+ // TODO fill in
+ }
class PostTyperTransformer extends Transformer {
+
+ private var inJavaAnnot: Boolean = false
+
+ private var parentNews: Set[New] = Set()
+
+ private def transformAnnot(annot: Tree)(implicit ctx: Context): Tree = {
+ val saved = inJavaAnnot
+ inJavaAnnot = annot.symbol is JavaDefined
+ if (inJavaAnnot) checkValidJavaAnnotation(annot)
+ try transform(annot)
+ finally inJavaAnnot = saved
+ }
+
+ private def transformAnnot(annot: Annotation)(implicit ctx: Context): Annotation =
+ annot.derivedAnnotation(transformAnnot(annot.tree))
+
+ private def transformAnnots(tree: MemberDef)(implicit ctx: Context): Unit =
+ tree.symbol.transformAnnotations(transformAnnot)
override def transform(tree: Tree)(implicit ctx: Context): Tree =
try tree match {
case impl: Template =>
- def trans(impl: Template) =
- cpy.Template(impl)(body = transformStats(impl.body, impl.symbol))
- paramFwd.forwardParamAccessors(superAcc.wrapTemplate(impl)(trans))
+ val saved = parentNews
+ parentNews ++= impl.parents.flatMap(newPart)
+ try
+ paramFwd.forwardParamAccessors(
+ superAcc.wrapTemplate(impl)(
+ super.transform(_).asInstanceOf[Template]))
+ finally parentNews = saved
case tree @ TypeApply(sel: Select, args) =>
- val sel1 = superAcc.transformSelect(super.transform(sel), args)
- if (superAcc.isProtectedAccessor(sel1)) sel1 else cpy.TypeApply(tree)(sel1, args)
+ val args1 = transform(args)
+ val sel1 = superAcc.transformSelect(super.transform(sel), args1)
+ if (superAcc.isProtectedAccessor(sel1)) sel1 else cpy.TypeApply(tree)(sel1, args1)
case sel: Select =>
superAcc.transformSelect(super.transform(sel), Nil)
- case tree: DefDef =>
- superAcc.wrapDefDef(tree)(cpy.DefDef(tree)(rhs = transform(tree.rhs)))
- case tree: Assign =>
+ case tree @ Assign(sel: Select, _) =>
superAcc.transformAssign(super.transform(tree))
-// case tree: Apply if tree.symbol.isConstructor =>
-// instChecks.checkInstantiable(tree)
-// super.transform(tree)
+ case tree: DefDef =>
+ transformAnnots(tree)
+ superAcc.wrapDefDef(tree)(super.transform(tree).asInstanceOf[DefDef])
+ case tree: MemberDef =>
+ transformAnnots(tree)
+ super.transform(tree)
+ case tree: New if !inJavaAnnot && !parentNews.contains(tree) =>
+ checkInstantiable(tree.tpe, tree.pos)
+ super.transform(tree)
+ case Annotated(annot, annotated) =>
+ cpy.Annotated(tree)(transformAnnot(annot), transform(annotated))
+ case tree: TypeTree =>
+ tree.withType(
+ tree.tpe match {
+ case AnnotatedType(annot, tpe) => AnnotatedType(transformAnnot(annot), tpe)
+ case tpe => tpe
+ }
+ )
case _ =>
super.transform(tree)
}