@@ -18,6 +18,7 @@ import config.{ScalaVersion, NoScalaVersion}
1818import Decorators ._
1919import typer .ErrorReporting ._
2020import config .Feature .{warnOnMigration , migrateTo3 }
21+ import config .Printers .refcheck
2122import reporting ._
2223import scala .util .matching .Regex ._
2324import Constants .Constant
@@ -236,6 +237,26 @@ object RefChecks {
236237 i " ${if (showLocation) sym1.showLocated else sym1}$infoStr"
237238 }
238239
240+ def compatibleTypes (member : Symbol , memberTp : Type , other : Symbol , otherTp : Type , fallBack : => Boolean = false ): Boolean =
241+ try
242+ if (member.isType) // intersection of bounds to refined types must be nonempty
243+ memberTp.bounds.hi.hasSameKindAs(otherTp.bounds.hi) &&
244+ ((memberTp frozen_<:< otherTp) ||
245+ ! member.owner.derivesFrom(other.owner) && {
246+ // if member and other come from independent classes or traits, their
247+ // bounds must have non-empty-intersection
248+ val jointBounds = (memberTp.bounds & otherTp.bounds).bounds
249+ jointBounds.lo frozen_<:< jointBounds.hi
250+ })
251+ else
252+ member.name.is(DefaultGetterName ) || // default getters are not checked for compatibility
253+ memberTp.overrides(otherTp,
254+ member.matchNullaryLoosely || other.matchNullaryLoosely || fallBack)
255+ catch case ex : MissingType =>
256+ // can happen when called with upwardsSelf as qualifier of memberTp and otherTp,
257+ // because in that case we might access types that are not members of the qualifier.
258+ false
259+
239260 /* Check that all conditions for overriding `other` by `member`
240261 * of class `clazz` are met.
241262 */
@@ -245,7 +266,7 @@ object RefChecks {
245266 else self.memberInfo(member)
246267 def otherTp (self : Type ) = self.memberInfo(other)
247268
248- report.debuglog( " Checking validity of %s overriding %s " .format(member.showLocated, other.showLocated) )
269+ refcheck.println( i " check override ${infoString(member)} overriding ${infoString( other)} " )
249270
250271 def noErrorType = ! memberTp(self).isErroneous && ! otherTp(self).isErroneous
251272
@@ -265,6 +286,12 @@ object RefChecks {
265286 infoStringWithLocation(other), infoString(member), msg, addendum)
266287 }
267288
289+ def compatTypes (memberTp : Type , otherTp : Type ): Boolean =
290+ compatibleTypes(member, memberTp, other, otherTp,
291+ fallBack = warnOnMigration(
292+ overrideErrorMsg(" no longer has compatible type" ),
293+ (if (member.owner == clazz) member else clazz).srcPos))
294+
268295 def emitOverrideError (fullmsg : String ) =
269296 if (! (hasErrors && member.is(Synthetic ) && member.is(Module ))) {
270297 // suppress errors relating toi synthetic companion objects if other override
@@ -291,29 +318,14 @@ object RefChecks {
291318 (if (otherAccess == " " ) " public" else " at least " + otherAccess))
292319 }
293320
294- def compatibleTypes (memberTp : Type , otherTp : Type ): Boolean =
295- try
296- if (member.isType) // intersection of bounds to refined types must be nonempty
297- memberTp.bounds.hi.hasSameKindAs(otherTp.bounds.hi) &&
298- ((memberTp frozen_<:< otherTp) ||
299- ! member.owner.derivesFrom(other.owner) && {
300- // if member and other come from independent classes or traits, their
301- // bounds must have non-empty-intersection
302- val jointBounds = (memberTp.bounds & otherTp.bounds).bounds
303- jointBounds.lo frozen_<:< jointBounds.hi
304- })
305- else
306- member.name.is(DefaultGetterName ) || // default getters are not checked for compatibility
307- memberTp.overrides(otherTp,
308- member.matchNullaryLoosely || other.matchNullaryLoosely ||
309- warnOnMigration(overrideErrorMsg(" no longer has compatible type" ),
310- (if (member.owner == clazz) member else clazz).srcPos))
311- catch {
312- case ex : MissingType =>
313- // can happen when called with upwardsSelf as qualifier of memberTp and otherTp,
314- // because in that case we might access types that are not members of the qualifier.
315- false
316- }
321+ def overrideTargetNameError () =
322+ val otherTargetName = i " @targetName( ${other.targetName}) "
323+ if member.hasTargetName(member.name) then
324+ overrideError(i " misses a target name annotation $otherTargetName" )
325+ else if other.hasTargetName(other.name) then
326+ overrideError(i " should not have a @targetName annotation since the overridden member hasn't one either " )
327+ else
328+ overrideError(i " has a different target name annotation; it should be $otherTargetName" )
317329
318330 // Console.println(infoString(member) + " overrides " + infoString(other) + " in " + clazz);//DEBUG
319331
@@ -359,7 +371,9 @@ object RefChecks {
359371 && (ob.isContainedIn(mb) || other.isAllOf(JavaProtected ))
360372 // m relaxes o's access boundary,
361373 // or o is Java defined and protected (see #3946)
362- if (! isOverrideAccessOK)
374+ if ! member.hasTargetName(other.targetName) then
375+ overrideTargetNameError()
376+ else if (! isOverrideAccessOK)
363377 overrideAccessError()
364378 else if (other.isClass)
365379 // direct overrides were already checked on completion (see Checking.chckWellFormed)
@@ -428,8 +442,8 @@ object RefChecks {
428442 overrideError(" is not inline, cannot implement an inline method" )
429443 else if (other.isScala2Macro && ! member.isScala2Macro) // (1.11)
430444 overrideError(" cannot be used here - only Scala-2 macros can override Scala-2 macros" )
431- else if (! compatibleTypes (memberTp(self), otherTp(self)) &&
432- ! compatibleTypes (memberTp(upwardsSelf), otherTp(upwardsSelf)))
445+ else if (! compatTypes (memberTp(self), otherTp(self)) &&
446+ ! compatTypes (memberTp(upwardsSelf), otherTp(upwardsSelf)))
433447 overrideError(" has incompatible type" + err.whyNoMatchStr(memberTp(self), otherTp(self)))
434448 else if (member.targetName != other.targetName)
435449 if (other.targetName != other.name)
@@ -451,7 +465,27 @@ object RefChecks {
451465 }*/
452466 }
453467
454- val opc = new OverridingPairs .Cursor (clazz)
468+ val opc = new OverridingPairs .Cursor (clazz):
469+
470+ /** We declare a match if either we have a full match including matching names
471+ * or we have a loose match with different target name but the types are the same.
472+ * This leaves two possible sorts of discrepancies to be reported as errors
473+ * in `checkOveride`:
474+ *
475+ * - matching names, target names, and signatures but different types
476+ * - matching names and types, but different target names
477+ */
478+ override def matches (sym1 : Symbol , sym2 : Symbol ): Boolean =
479+ sym1.isType
480+ || {
481+ val sd1 = sym1.asSeenFrom(clazz.thisType)
482+ val sd2 = sym2.asSeenFrom(clazz.thisType)
483+ sd1.matchesLoosely(sd2)
484+ && (sym1.hasTargetName(sym2.targetName)
485+ || compatibleTypes(sym1, sd1.info, sym2, sd2.info))
486+ }
487+ end opc
488+
455489 while opc.hasNext do
456490 checkOverride(opc.overriding, opc.overridden)
457491 opc.next()
0 commit comments