@@ -7,7 +7,7 @@ import scala.collection.{ mutable, immutable }
7
7
import ValueClasses ._
8
8
import scala .annotation .tailrec
9
9
import core ._
10
- import typer .InstChecks
10
+ import typer .ErrorReporting . _
11
11
import Types ._ , Contexts ._ , Constants ._ , Names ._ , NameOps ._ , Flags ._ , DenotTransformers ._
12
12
import SymDenotations ._ , Symbols ._ , StdNames ._ , Annotations ._ , Trees ._ , Scopes ._ , Denotations ._
13
13
import util .Positions ._
@@ -22,6 +22,8 @@ import Symbols._, TypeUtils._
22
22
* public parameter field in a superclass to a forwarder to the superclass
23
23
* field (corresponding = super class field is initialized with subclass field)
24
24
* (@see ForwardParamAccessors)
25
+ *
26
+ * (3) Check that `New` nodes can be instantiated, and that annotations are valid
25
27
*
26
28
* The reason for making this a macro transform is that some functions (in particular
27
29
* super and protected accessors and instantiation checks) are naturally top-down and
@@ -44,28 +46,89 @@ class PostTyper extends MacroTransform with IdentityDenotTransformer { thisTran
44
46
45
47
val superAcc = new SuperAccessors (thisTransformer)
46
48
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
+ }
48
75
49
76
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)
50
95
51
96
override def transform (tree : Tree )(implicit ctx : Context ): Tree =
52
97
try tree match {
53
98
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
57
106
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)
60
110
case sel : Select =>
61
111
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 , _) =>
65
113
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
+ )
69
132
case _ =>
70
133
super .transform(tree)
71
134
}
0 commit comments