Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

SI-4134: abstract override crasher if lacking super impl #359

Closed
wants to merge 1 commit into from

2 participants

som-snytt Paul Phillips
som-snytt

This commit just changes the assert on a bad abstract super.m
to a compiler error. Probably it's the not that simple, right?
In this case, review is easy; but if it weren't, should I ask
on scala-internals or on the jira ticket? By way of not
wasting people's time? I was just looking for small bugs as
an excuse to look at code.

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.

som-snytt som-snytt 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.
b28ece2
Paul Phillips

I had to rebase unfortunately, but this is committed.

Paul Phillips paulp closed this
som-snytt som-snytt deleted the branch
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Apr 5, 2012
  1. som-snytt

    SI-4134: abstract override crasher if lacking super impl

    som-snytt authored
    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.
This page is out of date. Refresh to see the latest.
11 src/compiler/scala/tools/nsc/transform/Mixin.scala
View
@@ -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?
7 src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
View
@@ -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
}
}
2  src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala
View
@@ -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'");
}
4 test/files/neg/t4134.check
View
@@ -0,0 +1,4 @@
+t4134.scala:22: error: Member method f of mixin trait T2 is missing a concrete super implementation.
+class Konkret extends T3
+ ^
+one error found
30 test/files/neg/t4134.scala
View
@@ -0,0 +1,30 @@
+
+
+
+trait T1 {
+ def f: String
+}
+
+trait T2 extends T1 {
+ abstract override def f: String = "goo"
+ def something = super.f // So the "abstract override" is needed
+}
+
+trait Q1 {
+ def f: String = "bippy"
+}
+
+//trait T3 extends Q1 with T2 {
+trait T3 extends T2 with Q1 {
+ abstract override def f: String = super[Q1].f + " " + super[T2].f + " hoo"
+}
+
+class Konkret extends T3
+
+object Test {
+ def main(args: Array[String]): Unit = {
+ val k = new Konkret
+ println(k.f)
+ println(k.something)
+ }
+}
Something went wrong with that request. Please try again.