@@ -323,6 +323,14 @@ object RefChecks {
323323 overrideErrorMsg(" no longer has compatible type" ),
324324 (if (member.owner == clazz) member else clazz).srcPos))
325325
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+
326334 def emitOverrideError (fullmsg : Message ) =
327335 if (! (hasErrors && member.is(Synthetic ) && member.is(Module ))) {
328336 // suppress errors relating toi synthetic companion objects if other override
@@ -333,7 +341,7 @@ object RefChecks {
333341 }
334342
335343 def overrideError (msg : String , compareTypes : Boolean = false ) =
336- if ( noErrorType)
344+ if trueMatch && noErrorType then
337345 emitOverrideError(overrideErrorMsg(msg, compareTypes))
338346
339347 def autoOverride (sym : Symbol ) =
@@ -360,24 +368,6 @@ object RefChecks {
360368
361369 // Console.println(infoString(member) + " overrides " + infoString(other) + " in " + clazz);//DEBUG
362370
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-
381371 /* Is the intersection between given two lists of overridden symbols empty? */
382372 def intersectionIsEmpty (syms1 : Iterator [Symbol ], syms2 : Iterator [Symbol ]) = {
383373 val set2 = syms2.toSet
@@ -412,7 +402,7 @@ object RefChecks {
412402 overrideError(" cannot be used here - class definitions cannot be overridden" )
413403 else if (! other.is(Deferred ) && member.isClass)
414404 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)
416406 overrideError(i " cannot override final member ${other.showLocated}" )
417407 else if (member.is(ExtensionMethod ) && ! other.is(ExtensionMethod )) // (1.3)
418408 overrideError(" is an extension method, cannot override a normal method" )
@@ -433,9 +423,11 @@ object RefChecks {
433423 member.setFlag(Override )
434424 else if (member.isType && self.memberInfo(member) =:= self.memberInfo(other))
435425 () // 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(
439431 s " $clazz inherits conflicting members: \n "
440432 + infoStringWithLocation(other) + " and\n " + infoStringWithLocation(member)
441433 + " \n (Note: this can be resolved by declaring an override in " + clazz + " .)" )
@@ -496,25 +488,51 @@ object RefChecks {
496488 }*/
497489 }
498490
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)
515508 && (sym1.hasTargetName(sym2.targetName)
516509 || 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)
518536 end opc
519537
520538 while opc.hasNext do
@@ -528,13 +546,11 @@ object RefChecks {
528546 //
529547 // class A { type T = B }
530548 // 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)
538554
539555 printMixinOverrideErrors()
540556
@@ -578,7 +594,8 @@ object RefChecks {
578594 def isConcrete (sym : Symbol ) = sym.exists && ! sym.isOneOf(NotConcrete )
579595 clazz.nonPrivateMembersNamed(mbr.name)
580596 .filterWithPredicate(
581- impl => isConcrete(impl.symbol) && mbrDenot.matchesLoosely(impl))
597+ impl => isConcrete(impl.symbol)
598+ && mbrDenot.matchesLoosely(impl, alwaysCompareTypes = true ))
582599 .exists
583600
584601 /** The term symbols in this class and its baseclasses that are
0 commit comments