@@ -18,6 +18,7 @@ import config.{ScalaVersion, NoScalaVersion}
18
18
import Decorators ._
19
19
import typer .ErrorReporting ._
20
20
import config .Feature .{warnOnMigration , migrateTo3 }
21
+ import config .Printers .refcheck
21
22
import reporting ._
22
23
import scala .util .matching .Regex ._
23
24
import Constants .Constant
@@ -236,6 +237,26 @@ object RefChecks {
236
237
i " ${if (showLocation) sym1.showLocated else sym1}$infoStr"
237
238
}
238
239
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
+
239
260
/* Check that all conditions for overriding `other` by `member`
240
261
* of class `clazz` are met.
241
262
*/
@@ -245,7 +266,7 @@ object RefChecks {
245
266
else self.memberInfo(member)
246
267
def otherTp (self : Type ) = self.memberInfo(other)
247
268
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)} " )
249
270
250
271
def noErrorType = ! memberTp(self).isErroneous && ! otherTp(self).isErroneous
251
272
@@ -265,6 +286,12 @@ object RefChecks {
265
286
infoStringWithLocation(other), infoString(member), msg, addendum)
266
287
}
267
288
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
+
268
295
def emitOverrideError (fullmsg : String ) =
269
296
if (! (hasErrors && member.is(Synthetic ) && member.is(Module ))) {
270
297
// suppress errors relating toi synthetic companion objects if other override
@@ -291,29 +318,14 @@ object RefChecks {
291
318
(if (otherAccess == " " ) " public" else " at least " + otherAccess))
292
319
}
293
320
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" )
317
329
318
330
// Console.println(infoString(member) + " overrides " + infoString(other) + " in " + clazz);//DEBUG
319
331
@@ -359,7 +371,9 @@ object RefChecks {
359
371
&& (ob.isContainedIn(mb) || other.isAllOf(JavaProtected ))
360
372
// m relaxes o's access boundary,
361
373
// 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)
363
377
overrideAccessError()
364
378
else if (other.isClass)
365
379
// direct overrides were already checked on completion (see Checking.chckWellFormed)
@@ -428,8 +442,8 @@ object RefChecks {
428
442
overrideError(" is not inline, cannot implement an inline method" )
429
443
else if (other.isScala2Macro && ! member.isScala2Macro) // (1.11)
430
444
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)))
433
447
overrideError(" has incompatible type" + err.whyNoMatchStr(memberTp(self), otherTp(self)))
434
448
else if (member.targetName != other.targetName)
435
449
if (other.targetName != other.name)
@@ -451,7 +465,27 @@ object RefChecks {
451
465
}*/
452
466
}
453
467
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
+
455
489
while opc.hasNext do
456
490
checkOverride(opc.overriding, opc.overridden)
457
491
opc.next()
0 commit comments