diff options
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/RefChecks.scala | 30 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala | 13 | ||||
-rw-r--r-- | test/files/pos/bug700.scala | 10 |
3 files changed, 23 insertions, 30 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala index 3bc224cc98..8e798b31c1 100644 --- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala +++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala @@ -593,35 +593,9 @@ abstract class RefChecks extends InfoTransform { result = toConstructor else qual match { case Super(qualifier, mix) => - val base = currentOwner.enclClass; - if (sym hasFlag DEFERRED) { - val member = sym.overridingSymbol(base);//??? - if (mix != nme.EMPTY.toTypeName || member == NoSymbol || - !((member hasFlag ABSOVERRIDE) && member.isIncompleteIn(base))) - unit.error(tree.pos, "symbol accessed from super may not be abstract"); - } + val base = qual.symbol; //System.out.println("super: " + tree + " in " + base);//DEBUG - if (base.isTrait && sym.isTerm && mix == nme.EMPTY.toTypeName) { - val superAccName = nme.superName(sym.name); - val superAcc = base.info.decl(superAccName) suchThat (.alias.==(sym)); - val tree1 = Select(This(base), superAcc); - if (settings.debug.value) log("super-replacement: " + tree + "=>" + tree1); - result = atPos(tree.pos) { - Select(gen.mkAttributedThis(base), superAcc) setType superAcc.tpe - } - } -/* - case This(_) => - if ((sym hasFlag PARAMACCESSOR) && (sym.alias != NoSymbol)) { - result = typed { - Select( - Super(qual.symbol, qual.symbol.info.parents.head.symbol.name) setPos qual.pos, - sym.alias) setPos tree.pos - } - if (settings.debug.value) - System.out.println("alias replacement: " + tree + " ==> " + result);//debug - } -*/ + assert(!(base.isTrait && sym.isTerm && mix == nme.EMPTY.toTypeName)) // term should have been eliminated by super accessors case _ => } case _ => diff --git a/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala b/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala index 59dad92a0d..37163a18d8 100644 --- a/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala +++ b/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala @@ -12,6 +12,8 @@ import nsc.symtab.Flags._; * either appear in a trait or have as a target a member of some outer class. * It also replaces references to parameter accessors with aliases by super * references to these aliases. + * The phase also checks that symbols accessed from super are not abstract, + * or are overridden by an abstract override. */ abstract class SuperAccessors extends transform.Transform { // inherits abstract value `global' and class `Phase' from Transform @@ -23,9 +25,9 @@ abstract class SuperAccessors extends transform.Transform { /** the following two members override abstract members in Transform */ val phaseName: String = "superaccessors"; - protected def newTransformer(unit: CompilationUnit): Transformer = new SuperAccTransformer; + protected def newTransformer(unit: CompilationUnit): Transformer = new SuperAccTransformer(unit); - class SuperAccTransformer extends Transformer { + class SuperAccTransformer(unit: CompilationUnit) extends Transformer { private var validCurrentOwner = true; private var accDefs: List[Pair[Symbol, ListBuffer[Tree]]] = List(); @@ -61,6 +63,13 @@ abstract class SuperAccessors extends transform.Transform { case Select(sup @ Super(_, mix), name) => val sym = tree.symbol; val clazz = sup.symbol; + if (sym hasFlag DEFERRED) { + val member = sym.overridingSymbol(clazz); + if (mix != nme.EMPTY.toTypeName || member == NoSymbol || + !((member hasFlag ABSOVERRIDE) && member.isIncompleteIn(clazz))) + unit.error(tree.pos, ""+member+member.locationString+" is accessed from super. It may not be abstract "+ + "unless it is overridden by a member declared `abstract' and `override'"); + } if (tree.isTerm && mix == nme.EMPTY.toTypeName && (clazz.isTrait || clazz != currentOwner.enclClass || !validCurrentOwner)) { val supername = nme.superName(sym.name); diff --git a/test/files/pos/bug700.scala b/test/files/pos/bug700.scala new file mode 100644 index 0000000000..7477bb54f6 --- /dev/null +++ b/test/files/pos/bug700.scala @@ -0,0 +1,10 @@ +trait Foo { + def foobar: Unit; +} + +trait Bar extends Foo { + def foobar: unit = super.foobar +} + +// the following definition breaks the compiler +abstract class Foobar extends Bar |