Skip to content

Commit 7e60221

Browse files
committed
Roll InstChecks into PostTyper
Move InstChecks functionality into PostTyper in order to save a separate traversal.
1 parent 158c963 commit 7e60221

File tree

5 files changed

+80
-108
lines changed

5 files changed

+80
-108
lines changed

src/dotty/tools/dotc/Compiler.scala

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@ class Compiler {
3939
List(
4040
List(new FrontEnd),
4141
List(new PostTyper),
42-
List(new InstChecks),
4342
List(new FirstTransform,
4443
new SyntheticMethods),
4544
List(new Pickler), // Pickler needs to come last in a group since it should not pickle trees generated later

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,10 @@ object SymDenotations {
210210
/** Does this denotation have an annotation matching the given class symbol? */
211211
final def hasAnnotation(cls: Symbol)(implicit ctx: Context) =
212212
dropOtherAnnotations(annotations, cls).nonEmpty
213+
214+
/** Apply transform `f` to all annotations of this denotation */
215+
final def transformAnnotations(f: Annotation => Annotation)(implicit ctx: Context): Unit =
216+
annotations = annotations.mapConserve(f)
213217

214218
/** Optionally, the annotation matching the given class symbol */
215219
final def getAnnotation(cls: Symbol)(implicit ctx: Context): Option[Annotation] =

src/dotty/tools/dotc/transform/FirstTransform.scala

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,6 @@ class FirstTransform extends MiniPhaseTransform with IdentityDenotTransformer wi
3535
import ast.tpd._
3636

3737
override def phaseName = "firstTransform"
38-
39-
override def runsAfter = Set(classOf[typer.InstChecks])
40-
// This phase makes annotations disappear in types, so InstChecks should
41-
// run before so that it can get at all annotations.
4238

4339
def transformInfo(tp: Type, sym: Symbol)(implicit ctx: Context): Type = tp
4440

src/dotty/tools/dotc/transform/PostTyper.scala

Lines changed: 76 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import scala.collection.{ mutable, immutable }
77
import ValueClasses._
88
import scala.annotation.tailrec
99
import core._
10-
import typer.InstChecks
10+
import typer.ErrorReporting._
1111
import Types._, Contexts._, Constants._, Names._, NameOps._, Flags._, DenotTransformers._
1212
import SymDenotations._, Symbols._, StdNames._, Annotations._, Trees._, Scopes._, Denotations._
1313
import util.Positions._
@@ -22,6 +22,8 @@ import Symbols._, TypeUtils._
2222
* public parameter field in a superclass to a forwarder to the superclass
2323
* field (corresponding = super class field is initialized with subclass field)
2424
* (@see ForwardParamAccessors)
25+
*
26+
* (3) Check that `New` nodes can be instantiated, and that annotations are valid
2527
*
2628
* The reason for making this a macro transform is that some functions (in particular
2729
* super and protected accessors and instantiation checks) are naturally top-down and
@@ -44,28 +46,89 @@ class PostTyper extends MacroTransform with IdentityDenotTransformer { thisTran
4446

4547
val superAcc = new SuperAccessors(thisTransformer)
4648
val paramFwd = new ParamForwarding(thisTransformer)
47-
// val instChecks = new InstChecks
49+
50+
/** Check that `tp` refers to a nonAbstract class
51+
* and that the instance conforms to the self type of the created class.
52+
*/
53+
private def checkInstantiable(tp: Type, pos: Position)(implicit ctx: Context): Unit =
54+
tp.underlyingClassRef(refinementOK = false) match {
55+
case tref: TypeRef =>
56+
val cls = tref.symbol
57+
if (cls.is(AbstractOrTrait))
58+
ctx.error(d"$cls is abstract; cannot be instantiated", pos)
59+
if (!cls.is(Module)) {
60+
val selfType = tp.givenSelfType.asSeenFrom(tref.prefix, cls.owner)
61+
if (selfType.exists && !(tp <:< selfType))
62+
ctx.error(d"$tp does not conform to its self type $selfType; cannot be instantiated")
63+
}
64+
case _ =>
65+
}
66+
67+
private def newPart(tree: Tree): Option[New] = methPart(tree) match {
68+
case Select(nu: New, _) => Some(nu)
69+
case _ => None
70+
}
71+
72+
private def checkValidJavaAnnotation(annot: Tree)(implicit ctx: Context): Unit = {
73+
// TODO fill in
74+
}
4875

4976
class PostTyperTransformer extends Transformer {
77+
78+
private var inJavaAnnot: Boolean = false
79+
80+
private var parentNews: Set[New] = Set()
81+
82+
private def transformAnnot(annot: Tree)(implicit ctx: Context): Tree = {
83+
val saved = inJavaAnnot
84+
inJavaAnnot = annot.symbol is JavaDefined
85+
if (inJavaAnnot) checkValidJavaAnnotation(annot)
86+
try transform(annot)
87+
finally inJavaAnnot = saved
88+
}
89+
90+
private def transformAnnot(annot: Annotation)(implicit ctx: Context): Annotation =
91+
annot.derivedAnnotation(transformAnnot(annot.tree))
92+
93+
private def transformAnnots(tree: MemberDef)(implicit ctx: Context): Unit =
94+
tree.symbol.transformAnnotations(transformAnnot)
5095

5196
override def transform(tree: Tree)(implicit ctx: Context): Tree =
5297
try tree match {
5398
case impl: Template =>
54-
def trans(impl: Template) =
55-
cpy.Template(impl)(body = transformStats(impl.body, impl.symbol))
56-
paramFwd.forwardParamAccessors(superAcc.wrapTemplate(impl)(trans))
99+
val saved = parentNews
100+
parentNews ++= impl.parents.flatMap(newPart)
101+
try
102+
paramFwd.forwardParamAccessors(
103+
superAcc.wrapTemplate(impl)(
104+
super.transform(_).asInstanceOf[Template]))
105+
finally parentNews = saved
57106
case tree @ TypeApply(sel: Select, args) =>
58-
val sel1 = superAcc.transformSelect(super.transform(sel), args)
59-
if (superAcc.isProtectedAccessor(sel1)) sel1 else cpy.TypeApply(tree)(sel1, args)
107+
val args1 = transform(args)
108+
val sel1 = superAcc.transformSelect(super.transform(sel), args1)
109+
if (superAcc.isProtectedAccessor(sel1)) sel1 else cpy.TypeApply(tree)(sel1, args1)
60110
case sel: Select =>
61111
superAcc.transformSelect(super.transform(sel), Nil)
62-
case tree: DefDef =>
63-
superAcc.wrapDefDef(tree)(cpy.DefDef(tree)(rhs = transform(tree.rhs)))
64-
case tree: Assign =>
112+
case tree @ Assign(sel: Select, _) =>
65113
superAcc.transformAssign(super.transform(tree))
66-
// case tree: Apply if tree.symbol.isConstructor =>
67-
// instChecks.checkInstantiable(tree)
68-
// super.transform(tree)
114+
case tree: DefDef =>
115+
transformAnnots(tree)
116+
superAcc.wrapDefDef(tree)(super.transform(tree).asInstanceOf[DefDef])
117+
case tree: MemberDef =>
118+
transformAnnots(tree)
119+
super.transform(tree)
120+
case tree: New if !inJavaAnnot && !parentNews.contains(tree) =>
121+
checkInstantiable(tree.tpe, tree.pos)
122+
super.transform(tree)
123+
case Annotated(annot, annotated) =>
124+
cpy.Annotated(tree)(transformAnnot(annot), transform(annotated))
125+
case tree: TypeTree =>
126+
tree.withType(
127+
tree.tpe match {
128+
case AnnotatedType(annot, tpe) => AnnotatedType(transformAnnot(annot), tpe)
129+
case tpe => tpe
130+
}
131+
)
69132
case _ =>
70133
super.transform(tree)
71134
}

src/dotty/tools/dotc/typer/InstChecks.scala

Lines changed: 0 additions & 90 deletions
This file was deleted.

0 commit comments

Comments
 (0)