@@ -323,6 +323,14 @@ object RefChecks {
323
323
overrideErrorMsg(" no longer has compatible type" ),
324
324
(if (member.owner == clazz) member else clazz).srcPos))
325
325
326
+ /** Do types of term members `member` and `other` as seen from `self` match?
327
+ * If not we treat them as not a real override and don't issue override
328
+ * error messages. Also, bridges are not generated in this case.
329
+ * Type members are always assumed to match.
330
+ */
331
+ def trueMatch : Boolean =
332
+ member.isType || memberTp(self).matches(otherTp(self))
333
+
326
334
def emitOverrideError (fullmsg : Message ) =
327
335
if (! (hasErrors && member.is(Synthetic ) && member.is(Module ))) {
328
336
// suppress errors relating toi synthetic companion objects if other override
@@ -333,7 +341,7 @@ object RefChecks {
333
341
}
334
342
335
343
def overrideError (msg : String , compareTypes : Boolean = false ) =
336
- if ( noErrorType)
344
+ if trueMatch && noErrorType then
337
345
emitOverrideError(overrideErrorMsg(msg, compareTypes))
338
346
339
347
def autoOverride (sym : Symbol ) =
@@ -360,24 +368,6 @@ object RefChecks {
360
368
361
369
// Console.println(infoString(member) + " overrides " + infoString(other) + " in " + clazz);//DEBUG
362
370
363
- // return if we already checked this combination elsewhere
364
- if (member.owner != clazz) {
365
- def deferredCheck = member.is(Deferred ) || ! other.is(Deferred )
366
- def subOther (s : Symbol ) = s derivesFrom other.owner
367
- def subMember (s : Symbol ) = s derivesFrom member.owner
368
-
369
- if (subOther(member.owner) && deferredCheck)
370
- // Console.println(infoString(member) + " shadows1 " + infoString(other) " in " + clazz);//DEBUG
371
- return
372
- val parentSymbols = clazz.info.parents.map(_.typeSymbol)
373
- if (parentSymbols exists (p => subOther(p) && subMember(p) && deferredCheck))
374
- // Console.println(infoString(member) + " shadows2 " + infoString(other) + " in " + clazz);//DEBUG
375
- return
376
- if (parentSymbols forall (p => subOther(p) == subMember(p)))
377
- // Console.println(infoString(member) + " shadows " + infoString(other) + " in " + clazz);//DEBUG
378
- return
379
- }
380
-
381
371
/* Is the intersection between given two lists of overridden symbols empty? */
382
372
def intersectionIsEmpty (syms1 : Iterator [Symbol ], syms2 : Iterator [Symbol ]) = {
383
373
val set2 = syms2.toSet
@@ -412,7 +402,7 @@ object RefChecks {
412
402
overrideError(" cannot be used here - class definitions cannot be overridden" )
413
403
else if (! other.is(Deferred ) && member.isClass)
414
404
overrideError(" cannot be used here - classes can only override abstract types" )
415
- else if ( other.isEffectivelyFinal) // (1.2)
405
+ else if other.isEffectivelyFinal then // (1.2)
416
406
overrideError(i " cannot override final member ${other.showLocated}" )
417
407
else if (member.is(ExtensionMethod ) && ! other.is(ExtensionMethod )) // (1.3)
418
408
overrideError(" is an extension method, cannot override a normal method" )
@@ -433,9 +423,11 @@ object RefChecks {
433
423
member.setFlag(Override )
434
424
else if (member.isType && self.memberInfo(member) =:= self.memberInfo(other))
435
425
() // OK, don't complain about type aliases which are equal
436
- else if (member.owner != clazz && other.owner != clazz &&
437
- ! (other.owner derivesFrom member.owner))
438
- emitOverrideError(
426
+ else if member.owner != clazz
427
+ && other.owner != clazz
428
+ && ! other.owner.derivesFrom(member.owner)
429
+ then
430
+ overrideError(
439
431
s " $clazz inherits conflicting members: \n "
440
432
+ infoStringWithLocation(other) + " and\n " + infoStringWithLocation(member)
441
433
+ " \n (Note: this can be resolved by declaring an override in " + clazz + " .)" )
@@ -496,25 +488,51 @@ object RefChecks {
496
488
}*/
497
489
}
498
490
499
- val opc = new OverridingPairs .Cursor (clazz):
500
-
501
- /** We declare a match if either we have a full match including matching names
502
- * or we have a loose match with different target name but the types are the same.
503
- * This leaves two possible sorts of discrepancies to be reported as errors
504
- * in `checkOveride`:
505
- *
506
- * - matching names, target names, and signatures but different types
507
- * - matching names and types, but different target names
508
- */
509
- override def matches (sym1 : Symbol , sym2 : Symbol ): Boolean =
510
- ! (sym1.owner.is(JavaDefined , butNot = Trait ) && sym2.owner.is(JavaDefined , butNot = Trait )) && // javac already handles these checks
511
- (sym1.isType || {
512
- val sd1 = sym1.asSeenFrom(clazz.thisType)
513
- val sd2 = sym2.asSeenFrom(clazz.thisType)
514
- sd1.matchesLoosely(sd2)
491
+ /** We declare a match if either we have a full match including matching names
492
+ * or we have a loose match with different target name but the types are the same.
493
+ * This leaves two possible sorts of discrepancies to be reported as errors
494
+ * in `checkOveride`:
495
+ *
496
+ * - matching names, target names, and signatures but different types
497
+ * - matching names and types, but different target names
498
+ */
499
+ def considerMatching (sym1 : Symbol , sym2 : Symbol , self : Type ): Boolean =
500
+ if sym1.owner.is(JavaDefined , butNot = Trait )
501
+ && sym2.owner.is(JavaDefined , butNot = Trait )
502
+ then false // javac already handles these checks
503
+ else if sym1.isType then true
504
+ else
505
+ val sd1 = sym1.asSeenFrom(self)
506
+ val sd2 = sym2.asSeenFrom(self)
507
+ sd1.matchesLoosely(sd2)
515
508
&& (sym1.hasTargetName(sym2.targetName)
516
509
|| compatibleTypes(sym1, sd1.info, sym2, sd2.info))
517
- })
510
+
511
+ val opc = new OverridingPairs .Cursor (clazz):
512
+ override def matches (sym1 : Symbol , sym2 : Symbol ): Boolean =
513
+ considerMatching(sym1, sym2, self)
514
+
515
+ private def inLinearizationOrder (sym1 : Symbol , sym2 : Symbol , parent : Symbol ): Boolean =
516
+ val owner1 = sym1.owner
517
+ val owner2 = sym2.owner
518
+ def precedesIn (bcs : List [ClassSymbol ]): Boolean = (bcs : @ unchecked) match
519
+ case bc :: bcs1 =>
520
+ if owner1 eq bc then true
521
+ else if owner2 eq bc then false
522
+ else precedesIn(bcs1)
523
+ case _ =>
524
+ false
525
+ precedesIn(parent.asClass.baseClasses)
526
+
527
+ // We can exclude pairs safely from checking only under two additional conditions
528
+ // - their signatures also match in the parent class.
529
+ // See neg/i12828.scala for an example where this matters.
530
+ // - They overriding/overridden appear in linearization order.
531
+ // See neg/i5094.scala for an example where this matters.
532
+ override def canBeHandledByParent (sym1 : Symbol , sym2 : Symbol , parent : Symbol ): Boolean =
533
+ considerMatching(sym1, sym2, parent.thisType)
534
+ .showing(i " already handled ${sym1.showLocated}: ${sym1.asSeenFrom(parent.thisType).signature}, ${sym2.showLocated}: ${sym2.asSeenFrom(parent.thisType).signature} = $result" , refcheck)
535
+ && inLinearizationOrder(sym1, sym2, parent)
518
536
end opc
519
537
520
538
while opc.hasNext do
@@ -528,13 +546,11 @@ object RefChecks {
528
546
//
529
547
// class A { type T = B }
530
548
// class B extends A { override type T }
531
- for
532
- dcl <- clazz.info.decls.iterator
533
- if dcl.is(Deferred )
534
- other <- dcl.allOverriddenSymbols
535
- if ! other.is(Deferred )
536
- do
537
- checkOverride(dcl, other)
549
+ for dcl <- clazz.info.decls.iterator do
550
+ if dcl.is(Deferred ) then
551
+ for other <- dcl.allOverriddenSymbols do
552
+ if ! other.is(Deferred ) then
553
+ checkOverride(dcl, other)
538
554
539
555
printMixinOverrideErrors()
540
556
@@ -578,7 +594,8 @@ object RefChecks {
578
594
def isConcrete (sym : Symbol ) = sym.exists && ! sym.isOneOf(NotConcrete )
579
595
clazz.nonPrivateMembersNamed(mbr.name)
580
596
.filterWithPredicate(
581
- impl => isConcrete(impl.symbol) && mbrDenot.matchesLoosely(impl))
597
+ impl => isConcrete(impl.symbol)
598
+ && mbrDenot.matchesLoosely(impl, alwaysCompareTypes = true ))
582
599
.exists
583
600
584
601
/** The term symbols in this class and its baseclasses that are
0 commit comments