diff options
-rw-r--r-- | src/compiler/scala/tools/nsc/transform/Mixin.scala | 11 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/RefChecks.scala | 7 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala | 2 | ||||
-rw-r--r-- | test/files/neg/t4134.check | 4 | ||||
-rw-r--r-- | test/files/neg/t4134.scala | 30 |
5 files changed, 44 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'"); } diff --git a/test/files/neg/t4134.check b/test/files/neg/t4134.check new file mode 100644 index 0000000000..35a1820b0a --- /dev/null +++ b/test/files/neg/t4134.check @@ -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 diff --git a/test/files/neg/t4134.scala b/test/files/neg/t4134.scala new file mode 100644 index 0000000000..678e4806ef --- /dev/null +++ b/test/files/neg/t4134.scala @@ -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) + } +} |