@@ -152,6 +152,54 @@ object Checking {
152
152
else info
153
153
}
154
154
}
155
+
156
+ /** Check that refinement satisfies the following two conditions
157
+ * 1. No part of it refers to a symbol that's defined in the same refinement
158
+ * at a textually later point.
159
+ * 2. All references to the refinement itself via `this` are followed by
160
+ * selections.
161
+ * Note: It's not yet clear what exactly we want to allow and what we want to rule out.
162
+ * This depends also on firming up the DOT calculus. For the moment we only issue
163
+ * deprecated warnings, not errors.
164
+ */
165
+ def checkRefinementNonCyclic (refinement : Tree , refineCls : ClassSymbol )(implicit ctx : Context ): Unit = {
166
+ def flag (what : String , tree : Tree ) =
167
+ ctx.deprecationWarning(i " $what reference in refinement is deprecated " , tree.pos)
168
+ def forwardRef (tree : Tree ) = flag(" forward" , tree)
169
+ def selfRef (tree : Tree ) = flag(" self" , tree)
170
+ val checkTree = new TreeAccumulator [Unit ] {
171
+ def checkRef (tree : Tree , sym : Symbol ) =
172
+ if (sym.maybeOwner == refineCls && tree.pos.start <= sym.pos.end) forwardRef(tree)
173
+ def apply (x : Unit , tree : Tree ) = tree match {
174
+ case tree @ Select (This (_), _) =>
175
+ checkRef(tree, tree.symbol)
176
+ case tree : RefTree =>
177
+ checkRef(tree, tree.symbol)
178
+ foldOver(x, tree)
179
+ case tree : This =>
180
+ selfRef(tree)
181
+ case tree : TypeTree =>
182
+ val checkType = new TypeAccumulator [Unit ] {
183
+ def apply (x : Unit , tp : Type ): Unit = tp match {
184
+ case tp : NamedType =>
185
+ checkRef(tree, tp.symbol)
186
+ tp.prefix match {
187
+ case pre : ThisType =>
188
+ case pre => foldOver(x, pre)
189
+ }
190
+ case tp : ThisType if tp.cls == refineCls =>
191
+ selfRef(tree)
192
+ case _ =>
193
+ foldOver(x, tp)
194
+ }
195
+ }
196
+ checkType((), tree.tpe)
197
+ case _ =>
198
+ foldOver(x, tree)
199
+ }
200
+ }
201
+ checkTree((), refinement)
202
+ }
155
203
}
156
204
157
205
trait Checking {
0 commit comments