@@ -169,7 +169,7 @@ object RefChecks {
169
169
* TODO This still needs to be cleaned up; the current version is a straight port of what was there
170
170
* before, but it looks too complicated and method bodies are far too large.
171
171
*/
172
- private def checkAllOverrides (clazz : Symbol )(implicit ctx : Context ): Unit = {
172
+ private def checkAllOverrides (clazz : ClassSymbol )(implicit ctx : Context ): Unit = {
173
173
val self = clazz.thisType
174
174
val upwardsSelf = upwardsThisType(clazz)
175
175
var hasErrors = false
@@ -470,33 +470,52 @@ object RefChecks {
470
470
}
471
471
}
472
472
473
- def ignoreDeferred (member : SingleDenotation ) =
474
- member.isType || {
475
- val mbr = member.symbol
476
- mbr.isSuperAccessor || // not yet synthesized
477
- ShortcutImplicits .isImplicitShortcut(mbr) || // only synthesized when referenced, see Note in ShortcutImplicits
478
- mbr.is(JavaDefined ) && hasJavaErasedOverriding(mbr)
479
- }
473
+ def ignoreDeferred (mbr : Symbol ) =
474
+ mbr.isType
475
+ || mbr.isSuperAccessor // not yet synthesized
476
+ || ShortcutImplicits .isImplicitShortcut(mbr) // only synthesized when referenced, see Note in ShortcutImplicits
477
+ || mbr.is(JavaDefined ) && hasJavaErasedOverriding(mbr)
478
+
479
+ def isImplemented (mbr : Symbol ) =
480
+ val mbrType = clazz.thisType.memberInfo(mbr)
481
+ def (sym : Symbol ).isConcrete = sym.exists && ! sym.is(Deferred )
482
+ clazz.nonPrivateMembersNamed(mbr.name)
483
+ .filterWithPredicate(
484
+ impl => impl.symbol.isConcrete && mbrType.matchesLoosely(impl.info))
485
+ .exists
486
+
487
+ /** The term symbols in this class and its baseclasses that are
488
+ * abstract in this class. We can't use memberNames for that since
489
+ * a concrete member might have the same signature as an abstract
490
+ * member in a base class, yet might not override it.
491
+ */
492
+ def missingTermSymbols : List [Symbol ] =
493
+ val buf = new mutable.ListBuffer [Symbol ]
494
+ for bc <- clazz.baseClasses
495
+ sym <- bc.info.decls.toList
496
+ if sym.is(DeferredTerm ) && ! isImplemented(sym) && ! ignoreDeferred(sym)
497
+ do buf += sym
498
+ buf.toList
480
499
481
500
// 2. Check that only abstract classes have deferred members
482
501
def checkNoAbstractMembers (): Unit = {
483
502
// Avoid spurious duplicates: first gather any missing members.
484
- val missing = clazz.thisType.abstractTermMembers.filterNot(ignoreDeferred)
503
+ val missing = missingTermSymbols
485
504
// Group missing members by the name of the underlying symbol,
486
505
// to consolidate getters and setters.
487
- val grouped = missing.groupBy(_.symbol. underlyingSymbol.name)
506
+ val grouped = missing.groupBy(_.underlyingSymbol.name)
488
507
489
508
val missingMethods = grouped.toList flatMap {
490
509
case (name, syms) =>
491
- val withoutSetters = syms filterNot (_.symbol. isSetter)
510
+ val withoutSetters = syms filterNot (_.isSetter)
492
511
if (withoutSetters.nonEmpty) withoutSetters else syms
493
512
}
494
513
495
514
def stubImplementations : List [String ] = {
496
515
// Grouping missing methods by the declaring class
497
- val regrouped = missingMethods.groupBy(_.symbol. owner).toList
498
- def membersStrings (members : List [SingleDenotation ]) =
499
- members.sortBy(_.symbol. name.toString).map(_.showDcl + " = ???" )
516
+ val regrouped = missingMethods.groupBy(_.owner).toList
517
+ def membersStrings (members : List [Symbol ]) =
518
+ members.sortBy(_.name.toString).map(_.showDcl + " = ???" )
500
519
501
520
if (regrouped.tail.isEmpty)
502
521
membersStrings(regrouped.head._2)
@@ -520,22 +539,21 @@ object RefChecks {
520
539
}
521
540
522
541
for (member <- missing) {
523
- val memberSym = member.symbol
524
542
def undefined (msg : String ) =
525
543
abstractClassError(false , s " ${member.showDcl} is not defined $msg" )
526
- val underlying = memberSym .underlyingSymbol
544
+ val underlying = member .underlyingSymbol
527
545
528
546
// Give a specific error message for abstract vars based on why it fails:
529
547
// It could be unimplemented, have only one accessor, or be uninitialized.
530
548
if (underlying.is(Mutable )) {
531
549
val isMultiple = grouped.getOrElse(underlying.name(ctx), Nil ).size > 1
532
550
533
551
// If both getter and setter are missing, squelch the setter error.
534
- if (memberSym .isSetter && isMultiple) ()
552
+ if (member .isSetter && isMultiple) ()
535
553
else undefined(
536
- if (memberSym .isSetter) " \n (Note that an abstract var requires a setter in addition to the getter)"
537
- else if (memberSym .isGetter && ! isMultiple) " \n (Note that an abstract var requires a getter in addition to the setter)"
538
- else err.abstractVarMessage(memberSym ))
554
+ if (member .isSetter) " \n (Note that an abstract var requires a setter in addition to the getter)"
555
+ else if (member .isGetter && ! isMultiple) " \n (Note that an abstract var requires a getter in addition to the setter)"
556
+ else err.abstractVarMessage(member ))
539
557
}
540
558
else if (underlying.is(Method )) {
541
559
// If there is a concrete method whose name matches the unimplemented
@@ -961,7 +979,7 @@ class RefChecks extends MiniPhase { thisPhase =>
961
979
}
962
980
963
981
override def transformTemplate (tree : Template )(implicit ctx : Context ): Tree = try {
964
- val cls = ctx.owner
982
+ val cls = ctx.owner.asClass
965
983
checkOverloadedRestrictions(cls)
966
984
checkParents(cls)
967
985
if (cls.is(Trait )) tree.parents.foreach(checkParentPrefix(cls, _))
0 commit comments