summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/RefChecks.scala30
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala13
-rw-r--r--test/files/pos/bug700.scala10
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