summaryrefslogtreecommitdiff
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
parent9c45685549a490f73dbd9d9ce0ec5189a75c6453 (diff)
downloadscala-55e40e1fdf166bcc0a5048523af955bf22f24a79.tar.gz
scala-55e40e1fdf166bcc0a5048523af955bf22f24a79.tar.bz2
scala-55e40e1fdf166bcc0a5048523af955bf22f24a79.zip
*** empty log message ***
-rw-r--r--doc/reference/ScalaReference.tex77
-rw-r--r--sources/scala/collection/mutable/ObservableMap.scala6
-rw-r--r--sources/scala/collection/mutable/ObservableSet.scala6
-rw-r--r--sources/scala/collection/mutable/SynchronizedMap.scala8
-rw-r--r--sources/scala/collection/mutable/SynchronizedSet.scala10
-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
13 files changed, 126 insertions, 70 deletions
diff --git a/doc/reference/ScalaReference.tex b/doc/reference/ScalaReference.tex
index 109e8cb8d8..caec1424e7 100644
--- a/doc/reference/ScalaReference.tex
+++ b/doc/reference/ScalaReference.tex
@@ -1459,17 +1459,18 @@ Classes (\sref{sec:classes}) and objects
A template defines the type signature, behavior and initial state of a
class of objects or of a single object. Templates form part of
instance creation expressions, class definitions, and object
-definitions. A template
-~\lstinline@$sc$ with $mc_1$ with $\ldots$ with $mc_n$ {$stats\,$}@~ consists of a
-constructor invocation $sc$ which defines the template's {\em
-superclass}, constructor invocations ~\lstinline@$mc_1 \commadots mc_n$@~
-$(n \geq 0)$, which define the template's {\em mixin classes}, and a
-statement sequence $stats$ which contains additional member
-definitions for the template. Superclass and mixin classes together
-are called the {\em parent classes} of a template. The superclass of
-a template must be a subtype of the superclass of each mixin class.
-The {\em least proper supertype} of a template is the class type or
-compound type (\sref{sec:compound-types}) consisting of the its parent classes.
+definitions. A template ~\lstinline@$sc$ with $mc_1$ with $\ldots$
+with $mc_n$ {$stats\,$}@~ consists of a constructor invocation $sc$
+which defines the template's {\em superclass}, constructor invocations
+~\lstinline@$mc_1 \commadots mc_n$@~ $(n \geq 0)$, which define the
+template's {\em mixin classes}, and a statement sequence $stats$ which
+contains additional member definitions for the template. Superclass
+and mixin classes together are called the {\em parent classes} of a
+template. They must be pairwise different. The superclass of a
+template must be a subtype of the superclass of each mixin class. The
+{\em least proper supertype} of a template is the class type or
+compound type (\sref{sec:compound-types}) consisting of the its parent
+classes.
Member definitions define new members or overwrite members in the
parent classes. If the template forms part of a class definition,
@@ -1696,6 +1697,11 @@ labeled \code{protected}.
\item
If $M'$ is not an abstract member, then
$M$ must be labeled \code{override}.
+\item
+If $M'$ is labelled \code{abstract} and \code{override}, and $M'$ is a
+member of the static superclass of the class containing the definition
+of $M$, then $M$ must also be labelled \code{abstract} and
+\code{override}.
\end{itemize}
\example\label{ex:compound-a}
@@ -1766,18 +1772,34 @@ The \code{override} modifier applies to class member definitions. It
is mandatory for member definitions that override some other concrete
member definition in a super- or mixin-class. If an \code{override}
modifier is given, there must be at least one overridden member
-definition. Furthermore, if the class containing the overriding
-member is not abstract, and one of the overridden definitions is a
-member of its superclass, that definition must be concrete
-(\sref{sec:members}).
+definition.
+
+The \code{override} modifier has an additional significance when
+combined with the \code{abstract} modifier. That modifier combination
+is only allowed in abstract classes. A member
+labelled \code{abstract} and \code{override} must override some
+member of the superclass of the class containing the definition.
+
+We call a member of a template {\em incomplete} if it is either
+abstract (i.e.\ defined by a declaration), or it is labelled
+\code{abstract} and \code{override} and it overrides an incomplete
+member of the template's superclass.
+
+Note that the \code{abstract override} modifier combination does not
+influence the concept whether a member is concrete or
+abstract. A member for which only a declaration is given is abstract,
+whereas a member for which a full definition is given is concrete.
+
\item
The \code{abstract} modifier is used in class definitions. It is
-mandatory if the class has abstract members, or if the class has
-members labeled \code{override} which override only abstract members
-in a parent class. Classes with \code{abstract} members
+mandatory if the class has incomplete members. Abstract classes
cannot be instantiated (\sref{sec:inst-creation}) with a constructor
invocation unless followed by mixin constructors or statements which
override all abstract members of the class.
+
+The \code{abstract} modifier can also be used in conjunction with
+\code{override} for class member definitions. In that case the meaning
+of the previous discussion applies.
\item
The \code{final} modifier applies to class member definitions and to
class definitions. A \code{final} class member definition may not be
@@ -2345,21 +2367,20 @@ If the expression's expected type is a singleton type, or
\lstinline@$C$.this@ occurs as the prefix of a selection, its type is
\lstinline@$C$.this.type@, otherwise it is the self type of class $C$.
-A reference \lstinline@super.$m$@ in a template refers to the definition of
-$m$ in the actual superclass (\sref{sec:base-classes}) of the
-template. A reference \lstinline@$C$.super.$m$@ refers to the definition of
-$m$ in the actual superclass of the innermost enclosing class or
-object definition named $C$ which encloses the reference. The
-definition referred to by \code{super} or \lstinline@$C$.super@ must be
-concrete, or the template containing the reference must contain a
-definition which has an \code{override} modifier and which overrides
-$m$.
+A reference \lstinline@super.$m$@ in a template refers to the
+definition of $m$ in the actual superclass (\sref{sec:base-classes})
+of the template. A reference \lstinline@$C$.super.$m$@ refers to the
+definition of $m$ in the actual superclass of the innermost enclosing
+class or object definition named $C$ which encloses the reference. The
+definition $m$ referred to via \code{super} or \lstinline@$C$.super@
+must be concrete, or the template containing the reference must have an
+incomplete (\sref{sec:modifiers}) member $m'$ which overrides $m$.
The \code{super} prefix may be followed by a mixin qualifier
\lstinline@[$M\,$]@, as in \lstinline@$C$.super[$M\,$].$x$@. This is called a {\em mixin
super reference}. In this case, the reference is to the member of
$x$ in the (first) mixin class of $C$ whose simple name
-is $M$.
+is $M$. That member may not be abstract.
\example\label{ex:super}
Consider the following class definitions
diff --git a/sources/scala/collection/mutable/ObservableMap.scala b/sources/scala/collection/mutable/ObservableMap.scala
index 0739a53062..52de275828 100644
--- a/sources/scala/collection/mutable/ObservableMap.scala
+++ b/sources/scala/collection/mutable/ObservableMap.scala
@@ -22,7 +22,7 @@ abstract class ObservableMap[A, B, This <: ObservableMap[A, B, This]]: This
extends scala.collection.mutable.Map[A, B]
with Publisher[ObservableUpdate[Pair[A, B]] with Undo, This] {
- override def update(key: A, value: B): Unit = get(key) match {
+ abstract override def update(key: A, value: B): Unit = get(key) match {
case None => super.update(key, value);
publish(new Inclusion(Pair(key, value)) with Undo {
def undo = -=(key);
@@ -33,7 +33,7 @@ abstract class ObservableMap[A, B, This <: ObservableMap[A, B, This]]: This
});
}
- override def -=(key: A): Unit = get(key) match {
+ abstract override def -=(key: A): Unit = get(key) match {
case None =>
case Some(old) => super.-=(key);
publish(new Removal(Pair(key, old)) with Undo {
@@ -41,7 +41,7 @@ abstract class ObservableMap[A, B, This <: ObservableMap[A, B, This]]: This
});
}
- override def clear: Unit = {
+ abstract override def clear: Unit = {
super.clear;
publish(new Reset() with Undo { def undo = error("cannot undo"); });
}
diff --git a/sources/scala/collection/mutable/ObservableSet.scala b/sources/scala/collection/mutable/ObservableSet.scala
index 7b09759b6e..e3ec93ad05 100644
--- a/sources/scala/collection/mutable/ObservableSet.scala
+++ b/sources/scala/collection/mutable/ObservableSet.scala
@@ -21,17 +21,17 @@ abstract class ObservableSet[A, This <: ObservableSet[A, This]]: This
extends scala.collection.mutable.Set[A]
with Publisher[ObservableUpdate[A] with Undo, This] {
- override def +=(elem: A): Unit = if (!contains(elem)) {
+ abstract override def +=(elem: A): Unit = if (!contains(elem)) {
super.+=(elem);
publish(new Inclusion(elem) with Undo { def undo = -=(elem); });
}
- override def -=(elem: A): Unit = if (contains(elem)) {
+ abstract override def -=(elem: A): Unit = if (contains(elem)) {
super.-=(elem);
publish(new Removal(elem) with Undo { def undo = +=(elem); });
}
- override def clear: Unit = {
+ abstract override def clear: Unit = {
super.clear;
publish(new Reset() with Undo { def undo = error("cannot undo"); });
}
diff --git a/sources/scala/collection/mutable/SynchronizedMap.scala b/sources/scala/collection/mutable/SynchronizedMap.scala
index 435caa0526..28e9f1707c 100644
--- a/sources/scala/collection/mutable/SynchronizedMap.scala
+++ b/sources/scala/collection/mutable/SynchronizedMap.scala
@@ -18,11 +18,11 @@ package scala.collection.mutable;
*/
trait SynchronizedMap[A, B] extends scala.collection.mutable.Map[A, B] with Monitor {
- override def size: Int = synchronized {
+ abstract override def size: Int = synchronized {
super.size;
}
- override def get(key: A): Option[B] = synchronized {
+ abstract override def get(key: A): Option[B] = synchronized {
super.get(key);
}
@@ -58,11 +58,11 @@ trait SynchronizedMap[A, B] extends scala.collection.mutable.Map[A, B] with Moni
super.toList;
}
- override def update(key: A, value: B): Unit = synchronized {
+ abstract override def update(key: A, value: B): Unit = synchronized {
super.update(key, value);
}
- override def -=(key: A): Unit = synchronized {
+ abstract override def -=(key: A): Unit = synchronized {
super.-=(key);
}
diff --git a/sources/scala/collection/mutable/SynchronizedSet.scala b/sources/scala/collection/mutable/SynchronizedSet.scala
index 37344a2020..26a1c68fec 100644
--- a/sources/scala/collection/mutable/SynchronizedSet.scala
+++ b/sources/scala/collection/mutable/SynchronizedSet.scala
@@ -18,7 +18,7 @@ package scala.collection.mutable;
*/
trait SynchronizedSet[A] extends scala.collection.mutable.Set[A] with Monitor {
- override def size: Int = synchronized {
+ abstract override def size: Int = synchronized {
super.size
}
@@ -26,11 +26,11 @@ trait SynchronizedSet[A] extends scala.collection.mutable.Set[A] with Monitor {
super.isEmpty
}
- override def contains(elem: A) = synchronized {
+ abstract override def contains(elem: A) = synchronized {
super.contains(elem);
}
- override def +=(elem: A): Unit = synchronized {
+ abstract override def +=(elem: A): Unit = synchronized {
super.+=(elem);
}
@@ -42,7 +42,7 @@ trait SynchronizedSet[A] extends scala.collection.mutable.Set[A] with Monitor {
super.incl(that);
}
- override def -=(elem: A): Unit = synchronized {
+ abstract override def -=(elem: A): Unit = synchronized {
super.-=(elem);
}
@@ -58,7 +58,7 @@ trait SynchronizedSet[A] extends scala.collection.mutable.Set[A] with Monitor {
super.intersect(that);
}
- override def clear: Unit = synchronized {
+ abstract override def clear: Unit = synchronized {
super.clear;
}
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));