@@ -234,9 +234,16 @@ object RefChecks {
234234 && inLinearizationOrder(sym1, sym2, parent)
235235 && ! sym2.is(AbsOverride )
236236
237- def checkAll (checkOverride : (Symbol , Symbol ) => Unit ) =
237+ // Checks the subtype relationship tp1 <:< tp2.
238+ // It is passed to the `checkOverride` operation in `checkAll`, to be used for
239+ // compatibility checking.
240+ def checkSubType (tp1 : Type , tp2 : Type )(using Context ): Boolean = tp1 frozen_<:< tp2
241+
242+ private val subtypeChecker : (Type , Type ) => Context ?=> Boolean = this .checkSubType
243+
244+ def checkAll (checkOverride : ((Type , Type ) => Context ?=> Boolean , Symbol , Symbol ) => Unit ) =
238245 while hasNext do
239- checkOverride(overriding, overridden)
246+ checkOverride(subtypeChecker, overriding, overridden)
240247 next()
241248
242249 // The OverridingPairs cursor does assume that concrete overrides abstract
@@ -250,7 +257,7 @@ object RefChecks {
250257 if dcl.is(Deferred ) then
251258 for other <- dcl.allOverriddenSymbols do
252259 if ! other.is(Deferred ) then
253- checkOverride(dcl, other)
260+ checkOverride(checkSubType, dcl, other)
254261 end checkAll
255262 end OverridingPairsChecker
256263
@@ -287,8 +294,11 @@ object RefChecks {
287294 * TODO check that classes are not overridden
288295 * TODO This still needs to be cleaned up; the current version is a straight port of what was there
289296 * before, but it looks too complicated and method bodies are far too large.
297+ *
298+ * @param makeOverridePairsChecker A function for creating a OverridePairsChecker instance
299+ * from the class symbol and the self type
290300 */
291- def checkAllOverrides (clazz : ClassSymbol )(using Context ): Unit = {
301+ def checkAllOverrides (clazz : ClassSymbol , makeOverridingPairsChecker : (( ClassSymbol , Type ) => Context ?=> OverridingPairsChecker ) | Null = null )(using Context ): Unit = {
292302 val self = clazz.thisType
293303 val upwardsSelf = upwardsThisType(clazz)
294304 var hasErrors = false
@@ -319,10 +329,17 @@ object RefChecks {
319329 def infoStringWithLocation (sym : Symbol ) =
320330 err.infoString(sym, self, showLocation = true )
321331
332+ def isInheritedAccessor (mbr : Symbol , other : Symbol ): Boolean =
333+ mbr.is(ParamAccessor )
334+ && {
335+ val next = ParamForwarding .inheritedAccessor(mbr)
336+ next == other || isInheritedAccessor(next, other)
337+ }
338+
322339 /* Check that all conditions for overriding `other` by `member`
323- * of class `clazz` are met.
324- */
325- def checkOverride (member : Symbol , other : Symbol ): Unit =
340+ * of class `clazz` are met.
341+ */
342+ def checkOverride (checkSubType : ( Type , Type ) => Context ?=> Boolean , member : Symbol , other : Symbol ): Unit =
326343 def memberTp (self : Type ) =
327344 if (member.isClass) TypeAlias (member.typeRef.EtaExpand (member.typeParams))
328345 else self.memberInfo(member)
@@ -341,7 +358,8 @@ object RefChecks {
341358 isOverridingPair(member, memberTp, other, otherTp,
342359 fallBack = warnOnMigration(
343360 overrideErrorMsg(" no longer has compatible type" ),
344- (if (member.owner == clazz) member else clazz).srcPos, version = `3.0`))
361+ (if (member.owner == clazz) member else clazz).srcPos, version = `3.0`),
362+ isSubType = checkSubType)
345363 catch case ex : MissingType =>
346364 // can happen when called with upwardsSelf as qualifier of memberTp and otherTp,
347365 // because in that case we might access types that are not members of the qualifier.
@@ -353,7 +371,16 @@ object RefChecks {
353371 * Type members are always assumed to match.
354372 */
355373 def trueMatch : Boolean =
356- member.isType || memberTp(self).matches(otherTp(self))
374+ member.isType || withMode(Mode .IgnoreCaptures ) {
375+ // `matches` does not perform box adaptation so the result here would be
376+ // spurious during capture checking.
377+ //
378+ // Instead of parameterizing `matches` with the function for subtype checking
379+ // with box adaptation, we simply ignore capture annotations here.
380+ // This should be safe since the compatibility under box adaptation is already
381+ // checked.
382+ memberTp(self).matches(otherTp(self))
383+ }
357384
358385 def emitOverrideError (fullmsg : Message ) =
359386 if (! (hasErrors && member.is(Synthetic ) && member.is(Module ))) {
@@ -488,7 +515,7 @@ object RefChecks {
488515 else if (member.is(ModuleVal ) && ! other.isRealMethod && ! other.isOneOf(DeferredOrLazy ))
489516 overrideError(" may not override a concrete non-lazy value" )
490517 else if (member.is(Lazy , butNot = Module ) && ! other.isRealMethod && ! other.is(Lazy ) &&
491- ! warnOnMigration(overrideErrorMsg(" may not override a non-lazy value" ), member.srcPos, version = `3.0`))
518+ ! warnOnMigration(overrideErrorMsg(" may not override a non-lazy value" ), member.srcPos, version = `3.0`))
492519 overrideError(" may not override a non-lazy value" )
493520 else if (other.is(Lazy ) && ! other.isRealMethod && ! member.is(Lazy ))
494521 overrideError(" must be declared lazy to override a lazy value" )
@@ -521,14 +548,8 @@ object RefChecks {
521548 overrideDeprecation(" " , member, other, " removed or renamed" )
522549 end checkOverride
523550
524- def isInheritedAccessor (mbr : Symbol , other : Symbol ): Boolean =
525- mbr.is(ParamAccessor )
526- && {
527- val next = ParamForwarding .inheritedAccessor(mbr)
528- next == other || isInheritedAccessor(next, other)
529- }
530-
531- OverridingPairsChecker (clazz, self).checkAll(checkOverride)
551+ val checker = if makeOverridingPairsChecker == null then OverridingPairsChecker (clazz, self) else makeOverridingPairsChecker(clazz, self)
552+ checker.checkAll(checkOverride)
532553 printMixinOverrideErrors()
533554
534555 // Verifying a concrete class has nothing unimplemented.
@@ -572,7 +593,7 @@ object RefChecks {
572593 clazz.nonPrivateMembersNamed(mbr.name)
573594 .filterWithPredicate(
574595 impl => isConcrete(impl.symbol)
575- && mbrDenot.matchesLoosely(impl, alwaysCompareTypes = true ))
596+ && withMode( Mode . IgnoreCaptures )( mbrDenot.matchesLoosely(impl, alwaysCompareTypes = true ) ))
576597 .exists
577598
578599 /** The term symbols in this class and its baseclasses that are
@@ -719,7 +740,7 @@ object RefChecks {
719740 def checkNoAbstractDecls (bc : Symbol ): Unit = {
720741 for (decl <- bc.info.decls)
721742 if (decl.is(Deferred )) {
722- val impl = decl.matchingMember(clazz.thisType)
743+ val impl = withMode( Mode . IgnoreCaptures )( decl.matchingMember(clazz.thisType) )
723744 if (impl == NoSymbol || decl.owner.isSubClass(impl.owner))
724745 && ! ignoreDeferred(decl)
725746 then
0 commit comments