diff options
author | Som Snytt <som.snytt@gmail.com> | 2012-04-05 02:58:40 -0700 |
---|---|---|
committer | Paul Phillips <paulp@improving.org> | 2012-04-06 11:57:41 -0700 |
commit | 72f6f0e57ca490b36cef62a3be2a8b3261476cd2 (patch) | |
tree | e140ee692080bed185ba99122b5890b736c1e573 /src | |
parent | 581a2e1a9653b06b6d2c431070e6b1d21383285d (diff) | |
download | scala-72f6f0e57ca490b36cef62a3be2a8b3261476cd2.tar.gz scala-72f6f0e57ca490b36cef62a3be2a8b3261476cd2.tar.bz2 scala-72f6f0e57ca490b36cef62a3be2a8b3261476cd2.zip |
SI-4134: abstract override crasher if lacking super impl
The example from the ticket is committed as a neg test.
The problem is that a super.m on an abstract override
member m has no concrete implementation, that is, the
trait T is not mixed in after a class C with a concrete m.
The error is noticed at phase mixin when the super accessor
is added to the concrete mixer. (Pun alert?) When super.m
is rebound, no concrete matching symbol is found up the
linearization.
Previously, it was asserted that such a symbol should
be found, but since this is our first opportunity to
detect that there is none, an error should be emitted
instead. The new message is of the form:
Member method f of mixin trait T2 is missing a concrete super implementation.
Additionally, a couple of flag tests were changed to use isAbstractOverride.
Diffstat (limited to 'src')
3 files changed, 10 insertions, 10 deletions
diff --git a/src/compiler/scala/tools/nsc/transform/Mixin.scala b/src/compiler/scala/tools/nsc/transform/Mixin.scala index adbb7d43d0..d0bba1d3c6 100644 --- a/src/compiler/scala/tools/nsc/transform/Mixin.scala +++ b/src/compiler/scala/tools/nsc/transform/Mixin.scala @@ -121,7 +121,7 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL { * @param member The symbol statically referred to by the superaccessor in the trait * @param mixinClass The mixin class that produced the superaccessor */ - private def rebindSuper(base: Symbol, member: Symbol, mixinClass: Symbol): Symbol = + private def rebindSuper(base: Symbol, member: Symbol, mixinClass: Symbol): Option[Symbol] = afterPickler { var bcs = base.info.baseClasses.dropWhile(mixinClass !=).tail var sym: Symbol = NoSymbol @@ -136,8 +136,7 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL { sym = member.matchingSymbol(bcs.head, base.thisType).suchThat(sym => !sym.hasFlag(DEFERRED | BRIDGE)) bcs = bcs.tail } - assert(sym != NoSymbol, member) - sym + if (sym != NoSymbol) Some(sym) else None } // --------- type transformation ----------------------------------------------- @@ -339,8 +338,10 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL { else if (mixinMember.isSuperAccessor) { // mixin super accessors val superAccessor = addMember(clazz, mixinMember.cloneSymbol(clazz)) setPos clazz.pos assert(superAccessor.alias != NoSymbol, superAccessor) - val alias1 = rebindSuper(clazz, mixinMember.alias, mixinClass) - superAccessor.asInstanceOf[TermSymbol] setAlias alias1 + rebindSuper(clazz, mixinMember.alias, mixinClass) match { + case Some(alias1) => superAccessor.asInstanceOf[TermSymbol] setAlias alias1 + case None => unit.error(clazz.pos, "Member "+ mixinMember.alias +" of mixin "+ mixinClass +" is missing a concrete super implementation.") + } } else if (mixinMember.isMethod && mixinMember.isModule && mixinMember.hasNoFlags(LIFTED | BRIDGE)) { // mixin objects: todo what happens with abstract objects? diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala index 5a7c015f09..68a722aab4 100644 --- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala +++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala @@ -662,7 +662,7 @@ abstract class RefChecks extends InfoTransform with reflect.internal.transform.R } // Check the remainder for invalid absoverride. - for (member <- rest ; if ((member hasFlag ABSOVERRIDE) && member.isIncompleteIn(clazz))) { + for (member <- rest ; if (member.isAbstractOverride && member.isIncompleteIn(clazz))) { val other = member.superSymbol(clazz) val explanation = if (other != NoSymbol) " and overrides incomplete superclass member " + infoString(other) @@ -756,11 +756,10 @@ abstract class RefChecks extends InfoTransform with reflect.internal.transform.R // 4. Check that every defined member with an `override` modifier overrides some other member. for (member <- clazz.info.decls) - if ((member hasFlag (OVERRIDE | ABSOVERRIDE)) && - !(clazz.thisType.baseClasses exists (hasMatchingSym(_, member)))) { + if (member.isAnyOverride && !(clazz.thisType.baseClasses exists (hasMatchingSym(_, member)))) { // for (bc <- clazz.info.baseClasses.tail) Console.println("" + bc + " has " + bc.info.decl(member.name) + ":" + bc.info.decl(member.name).tpe);//DEBUG unit.error(member.pos, member.toString() + " overrides nothing"); - member resetFlag OVERRIDE + member resetFlag (OVERRIDE | ABSOVERRIDE) // Any Override } } diff --git a/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala b/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala index 94733369a8..43cbea83ff 100644 --- a/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala +++ b/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala @@ -121,7 +121,7 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT if (sym.isDeferred) { val member = sym.overridingSymbol(clazz); if (mix != tpnme.EMPTY || member == NoSymbol || - !((member hasFlag ABSOVERRIDE) && member.isIncompleteIn(clazz))) + !(member.isAbstractOverride && member.isIncompleteIn(clazz))) unit.error(sel.pos, ""+sym.fullLocationString+" is accessed from super. It may not be abstract "+ "unless it is overridden by a member declared `abstract' and `override'"); } |