@@ -192,6 +192,54 @@ object RefChecks {
192
192
193
193
// Override checking ------------------------------------------------------------
194
194
195
+ /** A class for checking all overriding pairs of `class` with a given check function */
196
+ class OverridingPairsChecker (clazz : ClassSymbol , self : Type )(using Context ) extends OverridingPairs .Cursor (clazz):
197
+
198
+ override def matches (sym1 : Symbol , sym2 : Symbol ): Boolean =
199
+ isOverridingPair(sym1, sym2, self)
200
+
201
+ private def inLinearizationOrder (sym1 : Symbol , sym2 : Symbol , parent : Symbol ): Boolean =
202
+ val owner1 = sym1.owner
203
+ val owner2 = sym2.owner
204
+ def precedesIn (bcs : List [ClassSymbol ]): Boolean = (bcs : @ unchecked) match
205
+ case bc :: bcs1 =>
206
+ if owner1 eq bc then true
207
+ else if owner2 eq bc then false
208
+ else precedesIn(bcs1)
209
+ case _ =>
210
+ false
211
+ precedesIn(parent.asClass.baseClasses)
212
+
213
+ // We can exclude pairs safely from checking only under two additional conditions
214
+ // - their signatures also match in the parent class.
215
+ // See neg/i12828.scala for an example where this matters.
216
+ // - They overriding/overridden appear in linearization order.
217
+ // See neg/i5094.scala for an example where this matters.
218
+ override def canBeHandledByParent (sym1 : Symbol , sym2 : Symbol , parent : Symbol ): Boolean =
219
+ isOverridingPair(sym1, sym2, parent.thisType)
220
+ .showing(i " already handled ${sym1.showLocated}: ${sym1.asSeenFrom(parent.thisType).signature}, ${sym2.showLocated}: ${sym2.asSeenFrom(parent.thisType).signature} = $result" , refcheck)
221
+ && inLinearizationOrder(sym1, sym2, parent)
222
+
223
+ def checkAll (checkOverride : (Symbol , Symbol ) => Unit ) =
224
+ while hasNext do
225
+ checkOverride(overriding, overridden)
226
+ next()
227
+
228
+ // The OverridingPairs cursor does assume that concrete overrides abstract
229
+ // We have to check separately for an abstract definition in a subclass that
230
+ // overrides a concrete definition in a superclass. E.g. the following (inspired
231
+ // from neg/i11130.scala) needs to be rejected as well:
232
+ //
233
+ // class A { type T = B }
234
+ // class B extends A { override type T }
235
+ for dcl <- clazz.info.decls.iterator do
236
+ if dcl.is(Deferred ) then
237
+ for other <- dcl.allOverriddenSymbols do
238
+ if ! other.is(Deferred ) then
239
+ checkOverride(dcl, other)
240
+ end checkAll
241
+ end OverridingPairsChecker
242
+
195
243
/** 1. Check all members of class `clazz` for overriding conditions.
196
244
* That is for overriding member M and overridden member O:
197
245
*
@@ -469,50 +517,7 @@ object RefChecks {
469
517
}*/
470
518
}
471
519
472
- val opc = new OverridingPairs .Cursor (clazz):
473
- override def matches (sym1 : Symbol , sym2 : Symbol ): Boolean =
474
- isOverridingPair(sym1, sym2, self)
475
-
476
- private def inLinearizationOrder (sym1 : Symbol , sym2 : Symbol , parent : Symbol ): Boolean =
477
- val owner1 = sym1.owner
478
- val owner2 = sym2.owner
479
- def precedesIn (bcs : List [ClassSymbol ]): Boolean = (bcs : @ unchecked) match
480
- case bc :: bcs1 =>
481
- if owner1 eq bc then true
482
- else if owner2 eq bc then false
483
- else precedesIn(bcs1)
484
- case _ =>
485
- false
486
- precedesIn(parent.asClass.baseClasses)
487
-
488
- // We can exclude pairs safely from checking only under two additional conditions
489
- // - their signatures also match in the parent class.
490
- // See neg/i12828.scala for an example where this matters.
491
- // - They overriding/overridden appear in linearization order.
492
- // See neg/i5094.scala for an example where this matters.
493
- override def canBeHandledByParent (sym1 : Symbol , sym2 : Symbol , parent : Symbol ): Boolean =
494
- isOverridingPair(sym1, sym2, parent.thisType)
495
- .showing(i " already handled ${sym1.showLocated}: ${sym1.asSeenFrom(parent.thisType).signature}, ${sym2.showLocated}: ${sym2.asSeenFrom(parent.thisType).signature} = $result" , refcheck)
496
- && inLinearizationOrder(sym1, sym2, parent)
497
- end opc
498
-
499
- while opc.hasNext do
500
- checkOverride(opc.overriding, opc.overridden)
501
- opc.next()
502
-
503
- // The OverridingPairs cursor does assume that concrete overrides abstract
504
- // We have to check separately for an abstract definition in a subclass that
505
- // overrides a concrete definition in a superclass. E.g. the following (inspired
506
- // from neg/i11130.scala) needs to be rejected as well:
507
- //
508
- // class A { type T = B }
509
- // class B extends A { override type T }
510
- for dcl <- clazz.info.decls.iterator do
511
- if dcl.is(Deferred ) then
512
- for other <- dcl.allOverriddenSymbols do
513
- if ! other.is(Deferred ) then
514
- checkOverride(dcl, other)
515
-
520
+ OverridingPairsChecker (clazz, self).checkAll(checkOverride)
516
521
printMixinOverrideErrors()
517
522
518
523
// Verifying a concrete class has nothing unimplemented.
0 commit comments