@@ -234,9 +234,16 @@ object RefChecks {
234
234
&& inLinearizationOrder(sym1, sym2, parent)
235
235
&& ! sym2.is(AbsOverride )
236
236
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 ) =
238
245
while hasNext do
239
- checkOverride(overriding, overridden)
246
+ checkOverride(subtypeChecker, overriding, overridden)
240
247
next()
241
248
242
249
// The OverridingPairs cursor does assume that concrete overrides abstract
@@ -250,7 +257,7 @@ object RefChecks {
250
257
if dcl.is(Deferred ) then
251
258
for other <- dcl.allOverriddenSymbols do
252
259
if ! other.is(Deferred ) then
253
- checkOverride(dcl, other)
260
+ checkOverride(checkSubType, dcl, other)
254
261
end checkAll
255
262
end OverridingPairsChecker
256
263
@@ -287,8 +294,11 @@ object RefChecks {
287
294
* TODO check that classes are not overridden
288
295
* TODO This still needs to be cleaned up; the current version is a straight port of what was there
289
296
* 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
290
300
*/
291
- def checkAllOverrides (clazz : ClassSymbol )(using Context ): Unit = {
301
+ def checkAllOverrides (clazz : ClassSymbol , makeOverridingPairsChecker : (( ClassSymbol , Type ) => Context ?=> OverridingPairsChecker ) | Null = null )(using Context ): Unit = {
292
302
val self = clazz.thisType
293
303
val upwardsSelf = upwardsThisType(clazz)
294
304
var hasErrors = false
@@ -319,10 +329,17 @@ object RefChecks {
319
329
def infoStringWithLocation (sym : Symbol ) =
320
330
err.infoString(sym, self, showLocation = true )
321
331
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
+
322
339
/* 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 =
326
343
def memberTp (self : Type ) =
327
344
if (member.isClass) TypeAlias (member.typeRef.EtaExpand (member.typeParams))
328
345
else self.memberInfo(member)
@@ -341,7 +358,8 @@ object RefChecks {
341
358
isOverridingPair(member, memberTp, other, otherTp,
342
359
fallBack = warnOnMigration(
343
360
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)
345
363
catch case ex : MissingType =>
346
364
// can happen when called with upwardsSelf as qualifier of memberTp and otherTp,
347
365
// because in that case we might access types that are not members of the qualifier.
@@ -353,7 +371,16 @@ object RefChecks {
353
371
* Type members are always assumed to match.
354
372
*/
355
373
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
+ }
357
384
358
385
def emitOverrideError (fullmsg : Message ) =
359
386
if (! (hasErrors && member.is(Synthetic ) && member.is(Module ))) {
@@ -488,7 +515,7 @@ object RefChecks {
488
515
else if (member.is(ModuleVal ) && ! other.isRealMethod && ! other.isOneOf(DeferredOrLazy ))
489
516
overrideError(" may not override a concrete non-lazy value" )
490
517
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`))
492
519
overrideError(" may not override a non-lazy value" )
493
520
else if (other.is(Lazy ) && ! other.isRealMethod && ! member.is(Lazy ))
494
521
overrideError(" must be declared lazy to override a lazy value" )
@@ -521,14 +548,8 @@ object RefChecks {
521
548
overrideDeprecation(" " , member, other, " removed or renamed" )
522
549
end checkOverride
523
550
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)
532
553
printMixinOverrideErrors()
533
554
534
555
// Verifying a concrete class has nothing unimplemented.
@@ -572,7 +593,7 @@ object RefChecks {
572
593
clazz.nonPrivateMembersNamed(mbr.name)
573
594
.filterWithPredicate(
574
595
impl => isConcrete(impl.symbol)
575
- && mbrDenot.matchesLoosely(impl, alwaysCompareTypes = true ))
596
+ && withMode( Mode . IgnoreCaptures )( mbrDenot.matchesLoosely(impl, alwaysCompareTypes = true ) ))
576
597
.exists
577
598
578
599
/** The term symbols in this class and its baseclasses that are
@@ -719,7 +740,7 @@ object RefChecks {
719
740
def checkNoAbstractDecls (bc : Symbol ): Unit = {
720
741
for (decl <- bc.info.decls)
721
742
if (decl.is(Deferred )) {
722
- val impl = decl.matchingMember(clazz.thisType)
743
+ val impl = withMode( Mode . IgnoreCaptures )( decl.matchingMember(clazz.thisType) )
723
744
if (impl == NoSymbol || decl.owner.isSubClass(impl.owner))
724
745
&& ! ignoreDeferred(decl)
725
746
then
0 commit comments