@@ -192,6 +192,54 @@ object RefChecks {
192192
193193 // Override checking ------------------------------------------------------------
194194
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+
195243 /** 1. Check all members of class `clazz` for overriding conditions.
196244 * That is for overriding member M and overridden member O:
197245 *
@@ -469,50 +517,7 @@ object RefChecks {
469517 }*/
470518 }
471519
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)
516521 printMixinOverrideErrors()
517522
518523 // Verifying a concrete class has nothing unimplemented.
0 commit comments