summaryrefslogtreecommitdiff
path: root/sources/scalac/typechecker/RefCheck.java
diff options
context:
space:
mode:
Diffstat (limited to 'sources/scalac/typechecker/RefCheck.java')
-rw-r--r--sources/scalac/typechecker/RefCheck.java58
1 files changed, 56 insertions, 2 deletions
diff --git a/sources/scalac/typechecker/RefCheck.java b/sources/scalac/typechecker/RefCheck.java
index dc6cfe73f2..e9d2a2f205 100644
--- a/sources/scalac/typechecker/RefCheck.java
+++ b/sources/scalac/typechecker/RefCheck.java
@@ -209,6 +209,56 @@ public class RefCheck extends Transformer implements Modifiers, Kinds {
: name;
}
+// Basetype Checking --------------------------------------------------------
+
+ /** 1. Check that only traits are inherited several times (except if the
+ * inheriting instance is a compund type).
+ * 2. Check that later type instances in the base-type sequence
+ * of a class are subtypes of earlier type instances of the same trait.
+ * 3. Check that case classes do not inherit from case classes.
+ */
+ void validateBaseTypes(Symbol clazz) {
+ validateBaseTypes(clazz, clazz.type().parents(),
+ new Type[clazz.closure().length], 0);
+ }
+ //where
+ void validateBaseTypes(Symbol clazz, Type[] tps, Type[] seen, int start) {
+ for (int i = tps.length - 1; i >= start; i--) {
+ validateBaseTypes(clazz, tps[i].unalias(), seen, i == 0 ? 0 : 1);
+ }
+ }
+
+ void validateBaseTypes(Symbol clazz, Type tp, Type[] seen, int start) {
+ Symbol baseclazz = tp.symbol();
+ if (baseclazz.kind == CLASS) {
+ int index = clazz.closurePos(baseclazz);
+ if (index < 0) return;
+ if (seen[index] != null) {
+ // check that only uniform classes are inherited several times.
+ if (!clazz.isCompoundSym() && !baseclazz.isTrait()) {
+ unit.error(clazz.pos, "illegal inheritance;\n" + clazz +
+ " inherits " + baseclazz + " twice");
+ }
+ // if there are two different type instances of same class
+ // check that second is a subtype of first.
+ if (!seen[index].isSubType(tp)) {
+ String msg = (clazz.isCompoundSym())
+ ? "illegal combination;\n compound type combines"
+ : "illegal inheritance;\n " + clazz + " inherits";
+ unit.error(clazz.pos, msg + " different type instances of " +
+ baseclazz + ":\n" + tp + " and " + seen[index]);
+ }
+ }
+ // check that case classes do not inherit from case classes
+ if (clazz.isCaseClass() && baseclazz.isCaseClass())
+ unit.error(clazz.pos, "illegal inheritance;\n " + "case " + clazz +
+ " inherits from other case " + baseclazz);
+
+ seen[index] = tp;
+ validateBaseTypes(clazz, tp.parents(), seen, start);
+ }
+ }
+
// Variance Checking --------------------------------------------------------
private final int
@@ -784,7 +834,9 @@ public class RefCheck extends Transformer implements Modifiers, Kinds {
Tree[] bases1 = transform(bases);
Tree[] body1 = transformStats(body);
if (sym.kind == VAL) {
- checkAllOverrides(tree.pos, tree.symbol().owner());
+ Symbol owner = tree.symbol().owner();
+ validateBaseTypes(owner);
+ checkAllOverrides(tree.pos, owner);
}
return copy.Template(tree, bases1, body1);
@@ -826,7 +878,9 @@ public class RefCheck extends Transformer implements Modifiers, Kinds {
return elimTypeNode(super.transform(tree));
case CompoundType(_, _):
- checkAllOverrides(tree.pos, tree.type.symbol());
+ Symbol clazz = tree.type.symbol();
+ validateBaseTypes(clazz);
+ checkAllOverrides(tree.pos, clazz);
return elimTypeNode(super.transform(tree));
case Ident(Name name):