summaryrefslogtreecommitdiff
path: root/sources/scalac
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
parent9c45685549a490f73dbd9d9ce0ec5189a75c6453 (diff)
downloadscala-55e40e1fdf166bcc0a5048523af955bf22f24a79.tar.gz
scala-55e40e1fdf166bcc0a5048523af955bf22f24a79.tar.bz2
scala-55e40e1fdf166bcc0a5048523af955bf22f24a79.zip
*** empty log message ***
Diffstat (limited to 'sources/scalac')
-rw-r--r--sources/scalac/ast/parser/Parser.java6
-rw-r--r--sources/scalac/ast/printer/TextTreePrinter.java2
-rw-r--r--sources/scalac/symtab/Modifiers.java8
-rw-r--r--sources/scalac/symtab/Symbol.java7
-rw-r--r--sources/scalac/symtab/Type.java4
-rw-r--r--sources/scalac/symtab/classfile/ClassfileParser.java4
-rw-r--r--sources/scalac/typechecker/Analyzer.java10
-rw-r--r--sources/scalac/typechecker/RefCheck.java48
8 files changed, 62 insertions, 27 deletions
diff --git a/sources/scalac/ast/parser/Parser.java b/sources/scalac/ast/parser/Parser.java
index 00128c52fb..73ca7fc747 100644
--- a/sources/scalac/ast/parser/Parser.java
+++ b/sources/scalac/ast/parser/Parser.java
@@ -1367,7 +1367,7 @@ public class Parser implements Tokens {
int mod;
switch (s.token) {
case ABSTRACT:
- mod = Modifiers.ABSTRACTCLASS;
+ mod = Modifiers.ABSTRACT;
break;
case FINAL:
mod = Modifiers.FINAL;
@@ -1404,7 +1404,7 @@ public class Parser implements Tokens {
int mod;
switch (s.token) {
case ABSTRACT:
- mod = Modifiers.ABSTRACTCLASS;
+ mod = Modifiers.ABSTRACT;
break;
case FINAL:
mod = Modifiers.FINAL;
@@ -1685,7 +1685,7 @@ public class Parser implements Tokens {
case CASECLASS:
case TRAIT:
if (s.token == CASECLASS) mods |= Modifiers.CASE;
- else if (s.token == TRAIT) mods |= Modifiers.TRAIT | Modifiers.ABSTRACTCLASS;
+ else if (s.token == TRAIT) mods |= Modifiers.TRAIT | Modifiers.ABSTRACT;
do {
s.nextToken();
ts.append(classDef(mods));
diff --git a/sources/scalac/ast/printer/TextTreePrinter.java b/sources/scalac/ast/printer/TextTreePrinter.java
index 53b48c8a41..ac461d667d 100644
--- a/sources/scalac/ast/printer/TextTreePrinter.java
+++ b/sources/scalac/ast/printer/TextTreePrinter.java
@@ -674,7 +674,7 @@ public class TextTreePrinter implements TreePrinter {
}
protected void printModifiers(int flags) {
- if ((flags & Modifiers.ABSTRACTCLASS) != 0) {
+ if ((flags & Modifiers.ABSTRACT) != 0) {
print(KW_ABSTRACT);
print(Text.Space);
}
diff --git a/sources/scalac/symtab/Modifiers.java b/sources/scalac/symtab/Modifiers.java
index cc9111887a..292eb28bbc 100644
--- a/sources/scalac/symtab/Modifiers.java
+++ b/sources/scalac/symtab/Modifiers.java
@@ -19,7 +19,9 @@ public interface Modifiers {
int SEALED = 0x00000010;
int OVERRIDE = 0x00000020;
int CASE = 0x00000040;
- int ABSTRACTCLASS = 0x00000080; // abstract class
+ int ABSTRACT = 0x00000080; // abstract class, or used in conjunction
+ // with abstract override.
+ // Note difference to DEFERRED!
int DEF = 0x00000100; // a def parameter
int REPEATED = 0x00000200; // a repeated parameter
@@ -69,7 +71,9 @@ public interface Modifiers {
public static class Helper {
public static boolean isAbstract(int flags) {
- return (flags & (DEFERRED | ABSTRACTCLASS)) != 0;
+ // todo: ABSTRACT and DEFERRED should be separated.
+ return (flags & DEFERRED) != 0 ||
+ (flags & (ABSTRACT | OVERRIDE)) == ABSTRACT;
}
public static boolean isFinal(int flags) {
diff --git a/sources/scalac/symtab/Symbol.java b/sources/scalac/symtab/Symbol.java
index 4b710248c6..3303edac5f 100644
--- a/sources/scalac/symtab/Symbol.java
+++ b/sources/scalac/symtab/Symbol.java
@@ -328,10 +328,15 @@ public abstract class Symbol implements Modifiers, Kinds {
public final boolean isAbstractClass() {
preInitialize();
- return (flags & ABSTRACTCLASS) != 0 &&
+ return kind == CLASS && (flags & ABSTRACT) != 0 &&
this != Global.instance.definitions.ARRAY_CLASS;
}
+ public final boolean isAbstractOverride() {
+ preInitialize();
+ return (flags & (ABSTRACT | OVERRIDE)) == (ABSTRACT | OVERRIDE);
+ }
+
/* Does this symbol denote an anonymous class? */
public final boolean isAnonymousClass() {
return isClass() && name.startsWith(Names.ANON_CLASS_NAME);
diff --git a/sources/scalac/symtab/Type.java b/sources/scalac/symtab/Type.java
index fac8f18f48..1532d9c0e6 100644
--- a/sources/scalac/symtab/Type.java
+++ b/sources/scalac/symtab/Type.java
@@ -157,7 +157,7 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags {
ExtCompoundType res = new ExtCompoundType(parts, members);
res.tsym = new ClassSymbol(
Position.FIRSTPOS, Names.COMPOUND_NAME.toTypeName(), Symbol.NONE,
- SYNTHETIC | ABSTRACTCLASS);
+ SYNTHETIC | ABSTRACT);
res.tsym.setInfo(res);
res.tsym.primaryConstructor().setInfo(
Type.MethodType(Symbol.EMPTY_ARRAY, Type.NoType));
@@ -590,7 +590,7 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags {
case TypeRef(_, Symbol sym, _):
return sym.kind == CLASS &&
((sym.flags & JAVA) != 0 ||
- (sym.flags & (TRAIT | ABSTRACTCLASS)) == 0);
+ (sym.flags & (TRAIT | ABSTRACT)) == 0);
default:
return false;
}
diff --git a/sources/scalac/symtab/classfile/ClassfileParser.java b/sources/scalac/symtab/classfile/ClassfileParser.java
index 28f31c3647..9debd17b0f 100644
--- a/sources/scalac/symtab/classfile/ClassfileParser.java
+++ b/sources/scalac/symtab/classfile/ClassfileParser.java
@@ -86,7 +86,7 @@ public class ClassfileParser implements ClassfileConstants {
// todo: correct flag transition
c.flags = transFlags(flags);
if ((c.flags & Modifiers.DEFERRED) != 0)
- c.flags = c.flags & ~Modifiers.DEFERRED | Modifiers.ABSTRACTCLASS;
+ c.flags = c.flags & ~Modifiers.DEFERRED | Modifiers.ABSTRACT;
Type supertpe = readClassType(in.nextChar());
Type[] basetpes = new Type[in.nextChar() + 1];
this.locals = new Scope();
@@ -145,7 +145,7 @@ public class ClassfileParser implements ClassfileConstants {
if ((flags & 0x0010) != 0)
res |= Modifiers.FINAL;
if ((flags & 0x0200) != 0)
- res |= Modifiers.INTERFACE | Modifiers.TRAIT | Modifiers.ABSTRACTCLASS;
+ res |= Modifiers.INTERFACE | Modifiers.TRAIT | Modifiers.ABSTRACT;
return res | Modifiers.JAVA;
}
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));