summaryrefslogtreecommitdiff
path: root/sources/scalac/typechecker
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2003-10-08 19:05:14 +0000
committerMartin Odersky <odersky@gmail.com>2003-10-08 19:05:14 +0000
commit55e40e1fdf166bcc0a5048523af955bf22f24a79 (patch)
treeb31e1f6c3642ac2af63c5812499123561362b453 /sources/scalac/typechecker
parent9c45685549a490f73dbd9d9ce0ec5189a75c6453 (diff)
downloadscala-55e40e1fdf166bcc0a5048523af955bf22f24a79.tar.gz
scala-55e40e1fdf166bcc0a5048523af955bf22f24a79.tar.bz2
scala-55e40e1fdf166bcc0a5048523af955bf22f24a79.zip
*** empty log message ***
Diffstat (limited to 'sources/scalac/typechecker')
-rw-r--r--sources/scalac/typechecker/Analyzer.java10
-rw-r--r--sources/scalac/typechecker/RefCheck.java48
2 files changed, 42 insertions, 16 deletions
diff --git a/sources/scalac/typechecker/Analyzer.java b/sources/scalac/typechecker/Analyzer.java
index 3bec1700e2..fb5ef34201 100644
--- a/sources/scalac/typechecker/Analyzer.java
+++ b/sources/scalac/typechecker/Analyzer.java
@@ -297,7 +297,8 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
* - symbols with `override' modifier override some other symbol.
*/
void validate(Symbol sym) {
- if ((sym.flags & ABSTRACTCLASS) != 0 && sym.kind != CLASS) {
+ if ((sym.flags & (ABSTRACT | OVERRIDE)) == ABSTRACT &&
+ sym.kind != CLASS) {
error(sym.pos, "`abstract' modifier can be used only for classes; " +
"\nit should be omitted for abstract members");
}
@@ -340,6 +341,7 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
* statement sequence.
* - self-type of current class is a subtype of self-type of each parent class.
* - parent constructors do not refer to value parameters of class.
+ * - no two parents define same symbol.
*/
void validateParentClasses(Tree[] constrs, Type[] parents, Type selfType) {
for (int i = 0; i < parents.length; i++) {
@@ -379,6 +381,10 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
selfType + " does not conform to " + parents[i] +
"'s selftype " + parents[i].instanceType());
}
+ for (int j = 0; j < i; j++) {
+ if (parents[i].symbol() == parents[j].symbol())
+ error(constrs[i].pos, parents[i].symbol() + " is inherited twice");
+ }
}
}
@@ -721,7 +727,7 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
if (!clazz.primaryConstructor().isInitialized())
clazz.primaryConstructor().setInfo(new LazyTreeType(tree));
if ((mods & CASE) != 0) {
- if ((mods & ABSTRACTCLASS) == 0) {
+ if ((mods & ABSTRACT) == 0) {
// enter case constructor method.
Symbol cf = TermSymbol.define(
tree.pos, name.toTermName(), owner,
diff --git a/sources/scalac/typechecker/RefCheck.java b/sources/scalac/typechecker/RefCheck.java
index 799de7a290..8c87e28a3c 100644
--- a/sources/scalac/typechecker/RefCheck.java
+++ b/sources/scalac/typechecker/RefCheck.java
@@ -57,6 +57,12 @@ public class RefCheck extends Transformer implements Modifiers, Kinds {
// Override checking ------------------------------------------------------------
+ static boolean isIncomplete(Symbol sym) {
+ return sym.isDeferred() ||
+ sym.isAbstractOverride() &&
+ isIncomplete(sym.overriddenSymbol(sym.owner().parents()[0]));
+ }
+
/** 1. Check all members of class `clazz' for overriding conditions.
* 2. Check that only abstract classes have deferred members*
* 3. Check that every member with an `override' modifier
@@ -82,13 +88,16 @@ public class RefCheck extends Transformer implements Modifiers, Kinds {
if (i < 0) {
unit.error(sym.pos, sym + " overrides nothing");
sym.flags &= ~OVERRIDE;
- } else if (clazz.kind == CLASS &&
- (clazz.flags & ABSTRACTCLASS) == 0) {
+ } else if (sym.isAbstractOverride()) {
Symbol sup = sym.overriddenSymbol(parents[0]);
- if (sup.kind != NONE && (sup.flags & DEFERRED) != 0) {
+ if (sup.kind == NONE) {
+ unit.error(sym.pos, sym + " does not override a superclass member");
+ } else if (clazz.kind == CLASS &&
+ (clazz.flags & ABSTRACT) == 0 &&
+ isIncomplete(sup)) {
abstractClassError(
clazz, sym + sym.locationString() +
- " is marked `override', but overrides an abstract member of the superclass " + parents[0]);
+ " is marked `abstract' and `override' and overrides an incomplete superclass member in " + parents[0]);
}
}
}
@@ -134,7 +143,7 @@ public class RefCheck extends Transformer implements Modifiers, Kinds {
checkOverride(pos, clazz, member, other);
}
}
- if (clazz.kind == CLASS && (clazz.flags & ABSTRACTCLASS) == 0) {
+ if (clazz.kind == CLASS && (clazz.flags & ABSTRACT) == 0) {
if ((member.flags & DEFERRED) != 0) {
abstractClassError(
clazz,
@@ -160,7 +169,7 @@ public class RefCheck extends Transformer implements Modifiers, Kinds {
unit.error(clazz.pos, "object creation impossible, since " + msg);
else
unit.error(clazz.pos, clazz + " needs to be abstract, since " + msg);
- clazz.flags |= ABSTRACTCLASS;
+ clazz.flags |= ABSTRACT;
}
@@ -177,6 +186,9 @@ public class RefCheck extends Transformer implements Modifiers, Kinds {
* or M is a type alias or class which conforms to O's bounds.
* 7. If O and M are values, then M's type is a subtype of O's type.
* 8. If O is an immutable value, then so is M.
+ * 9. If O is a member of the static superclass of the class in which
+ * M is defined, and O is labelled `abstract override', then
+ * M must be labelled `abstract override'.
*/
void checkOverride(int pos, Symbol clazz, Symbol member, Symbol other) {
if (member.owner() == clazz)
@@ -190,8 +202,15 @@ public class RefCheck extends Transformer implements Modifiers, Kinds {
overrideError(pos, member, other, "has weaker access privileges; it should not be protected");
} else if ((other.flags & FINAL) != 0) {
overrideError(pos, member, other, "cannot override final member");
+ } else if (other.kind == CLASS) {
+ overrideError(pos, member, other, "cannot override a class");
} else if ((other.flags & DEFERRED) == 0 && ((member.flags & OVERRIDE) == 0)) {
overrideError(pos, member, other, "needs `override' modifier");
+ } else if (other.isAbstractOverride() &&
+ !member.isAbstractOverride() &&
+ member.owner() == clazz &&
+ clazz.parents()[0].symbol().isSubClass(other.owner())) {
+ overrideError(pos, member, other, "needs `abstract' and `override' modifiers");
} else if (other.isStable() && !member.isStable()) {
overrideError(pos, member, other, "needs to be an immutable value");
} else if ((member.flags & DEFERRED) == 0 && (other.flags & DEFERRED) == 0 &&
@@ -206,9 +225,6 @@ public class RefCheck extends Transformer implements Modifiers, Kinds {
Type self = clazz.thisType();
switch (other.kind) {
- case CLASS:
- overrideError(pos, member, other, "cannot override a class");
- break;
case ALIAS:
if (member.typeParams().length != 0)
overrideError(pos, member, other, "may not be parameterized");
@@ -994,11 +1010,15 @@ public class RefCheck extends Transformer implements Modifiers, Kinds {
sym.flags |= ACCESSED;
if (!TreeInfo.isSelf(qual, enclClass))
sym.flags |= SELECTOR;
- if (qual instanceof Tree.Super && (sym.flags & DEFERRED) != 0) {
- Symbol sym1 = enclClass.thisSym().info().lookup(sym.name);
- if ((sym1.flags & OVERRIDE) == 0 || (sym1.flags & DEFERRED) != 0)
- unit.error(tree.pos,
- "symbol accessed from super may not be abstract");
+ if ((sym.flags & DEFERRED) != 0) {
+ switch (qual) {
+ case Super(Name qualifier, Name mixin):
+ Symbol sym1 = enclClass.thisSym().info().lookup(sym.name);
+ if (mixin != TypeNames.EMPTY || !isIncomplete(sym1))
+ unit.error(
+ tree.pos,
+ "symbol accessed from super may not be abstract");
+ }
}
return elimTypeNode(super.transform(tree));