From 84af8bf38da09da1a4fe183696739d045a72ac79 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Fri, 13 Jun 2003 11:34:44 +0000 Subject: *** empty log message *** --- sources/scalac/symtab/Symbol.java | 10 ++++-- sources/scalac/symtab/Type.java | 5 +-- sources/scalac/typechecker/Analyzer.java | 7 +++- sources/scalac/typechecker/RefCheck.java | 59 ++++++++++++++++++++++++-------- test/files/pos/stable.scala | 6 ++-- test/files/pos/valdefs.scala | 4 +-- test/pos/stable.scala | 6 ++-- test/pos/valdefs.scala | 4 +-- 8 files changed, 72 insertions(+), 29 deletions(-) diff --git a/sources/scalac/symtab/Symbol.java b/sources/scalac/symtab/Symbol.java index f69506fc6d..7ab12576da 100644 --- a/sources/scalac/symtab/Symbol.java +++ b/sources/scalac/symtab/Symbol.java @@ -195,8 +195,14 @@ public abstract class Symbol implements Modifiers, Kinds { if (infos.limit < 0) return false; switch (rawInfo()) { case MethodType(_, _): - case PolyType(_, _): return true; - default: return false; + case PolyType(_, _): + return true; + case OverloadedType(Symbol[] alts, _): + for (int i = 0; i < alts.length; i++) + if (alts[i].isMethod()) return true; + return false; + default: + return false; } } diff --git a/sources/scalac/symtab/Type.java b/sources/scalac/symtab/Type.java index 7fa877dc82..36e7431fdf 100644 --- a/sources/scalac/symtab/Type.java +++ b/sources/scalac/symtab/Type.java @@ -1320,7 +1320,7 @@ public class Type implements Modifiers, Kinds, TypeTags { if (!isSubType(alttypes1[i])) return false; } - break; + return true; case UnboxedType(int tag1): switch (this) { @@ -1948,13 +1948,14 @@ public class Type implements Modifiers, Kinds, TypeTags { e = e.next) { Name name = e.sym.name; if ((e.sym.flags & PRIVATE) == 0 && lubType.lookup(name) == e.sym) { - //todo: not info? Type symType = memberTp(lubThisType, e.sym); Type symLoBound = lubThisType.memberLoBound(e.sym); int j = 0; while (j < tps.length) { rsyms[j] = tps[j].lookupNonPrivate(name); if (rsyms[j] == e.sym) break; + if (rsyms[j].isMethod()) break; // since methods cannot + // appear in refinements. rtps[j] = memberTp(tps[j], rsyms[j]) .substThis(tps[j].symbol(), lubThisType); rlbs[j] = tps[j].memberLoBound(rsyms[j]) diff --git a/sources/scalac/typechecker/Analyzer.java b/sources/scalac/typechecker/Analyzer.java index c4b404cc9a..b4b9d078d0 100644 --- a/sources/scalac/typechecker/Analyzer.java +++ b/sources/scalac/typechecker/Analyzer.java @@ -133,7 +133,7 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { // expressions may be packages and // Java statics modules. - static final int SUPERmode = 0x080; // orthogonal to above. When set + static final int SUPERmode = 0x080; // Goes with CONSTRmode. When set // we are checking a superclass // constructor invocation. @@ -192,6 +192,11 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { if (!isAccessible(sym, site)) { error(pos, sym + " cannot be accessed in " + site.type); } + if (site instanceof Tree.Super && (sym.flags & DEFERRED) != 0) { + Symbol sym1 = context.enclClass.owner.thisSym().info().lookup(sym.name); + if ((sym1.flags & OVERRIDE) == 0 || (sym1.flags & DEFERRED) != 0) + error(pos, "symbol accessed from super may not be abstract"); + } } /** Is `sym' accessible as a member of tree `site' in current context? diff --git a/sources/scalac/typechecker/RefCheck.java b/sources/scalac/typechecker/RefCheck.java index 3719fe0664..dc6cfe73f2 100644 --- a/sources/scalac/typechecker/RefCheck.java +++ b/sources/scalac/typechecker/RefCheck.java @@ -55,7 +55,10 @@ public class RefCheck extends Transformer implements Modifiers, Kinds { // Override checking ------------------------------------------------------------ - /** Check all members of class `clazz' for overriding conditions. + /** 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 + * overrides a concrete member. */ void checkAllOverrides(int pos, Symbol clazz) { Type[] closure = clazz.closure(); @@ -67,28 +70,56 @@ public class RefCheck extends Transformer implements Modifiers, Kinds { if (other != member && (other.flags & PRIVATE) == 0 && member.kind != NONE) checkOverride(pos, clazz, member, other); - if ((member.flags & DEFERRED) != 0 && - clazz.kind == CLASS && - (clazz.flags & ABSTRACTCLASS) == 0) { - if (clazz.isAnonymousClass()) - unit.error( - clazz.pos, "object creation impossible, since " + + if (clazz.kind == CLASS && (clazz.flags & ABSTRACTCLASS) == 0) { + if ((member.flags & DEFERRED) != 0) { + abstractClassError( + clazz, member + member.locationString() + " is not defined" + (((member.flags & MUTABLE) == 0) ? "" : "\n(Note that variables need to be initialized to be defined)")); - else - unit.error(clazz.pos, - clazz + " needs to be abstract; it does not define " + - member + member.locationString() + - (((member.flags & MUTABLE) == 0) ? "" - : "\n(Note that variables need to be initialized to be defined)")); - clazz.flags |= ABSTRACTCLASS; + } + if ((other.flags & OVERRIDE) != 0) { + Type[] clparents = closure[i].parents(); + Symbol sym1 = null; + for (int j = clparents.length - 1; sym1 == null && j > 0; j--) + sym1 = clparents[j].lookup(other.name); + if (sym1 == null) { + Symbol superclazz = clazz.info().parents()[0].symbol(); + if (superclazz.isSubClass(closure[i].symbol())) + superclazz = clparents[0].symbol(); + sym1 = superclazz.lookup(other.name); + } + if (sym1 != null && (sym1.flags & DEFERRED) != 0) + abstractClassError( + clazz, other + other.locationString() + + " is marked `override' and overrides an abstract member" + sym1.locationString()); + } } } } } + //where + private void abstractClassError(Symbol clazz, String msg) { + if (clazz.isAnonymousClass()) + unit.error(clazz.pos, "object creation impossible, since " + msg); + else + unit.error(clazz.pos, clazz + " needs to be abstract, since " + msg); + clazz.flags |= ABSTRACTCLASS; + } /** Check that all conditions for overriding `other' by `member' are met. + * That is for overriding member M and overridden member O: + * + * 1. M must have the same or stronger access priviliges as O. + * 2. O must not be final. + * 3. O is deferred, or M has `override' modifier. + * 4. O is not a class, nor a class constructor. + * 5. If O is a type alias, then M is an alias of O. + * 6. If O is an abstract type then + * either M is an abstract type, and M's bounds are sharper than O's bounds. + * 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. */ void checkOverride(int pos, Symbol clazz, Symbol member, Symbol other) { if (member.owner() == clazz) pos = member.pos; diff --git a/test/files/pos/stable.scala b/test/files/pos/stable.scala index 2ae6e2dcec..267a36fe5c 100644 --- a/test/files/pos/stable.scala +++ b/test/files/pos/stable.scala @@ -5,7 +5,7 @@ trait Base { } class Sub() extends Base { - override val x: Int = 1; - override val y: Int = 2; - override var z: Int = 3; + val x: Int = 1; + val y: Int = 2; + var z: Int = 3; } diff --git a/test/files/pos/valdefs.scala b/test/files/pos/valdefs.scala index f9150ea509..6e91b020b5 100644 --- a/test/files/pos/valdefs.scala +++ b/test/files/pos/valdefs.scala @@ -10,7 +10,7 @@ object test { override val y = 1; } - class Sub2() extends Base() { + abstract class Sub2() extends Base() { override val Pair(x, y) = Pair("abc", 1); } -} \ No newline at end of file +} diff --git a/test/pos/stable.scala b/test/pos/stable.scala index 2ae6e2dcec..267a36fe5c 100644 --- a/test/pos/stable.scala +++ b/test/pos/stable.scala @@ -5,7 +5,7 @@ trait Base { } class Sub() extends Base { - override val x: Int = 1; - override val y: Int = 2; - override var z: Int = 3; + val x: Int = 1; + val y: Int = 2; + var z: Int = 3; } diff --git a/test/pos/valdefs.scala b/test/pos/valdefs.scala index f9150ea509..6e91b020b5 100644 --- a/test/pos/valdefs.scala +++ b/test/pos/valdefs.scala @@ -10,7 +10,7 @@ object test { override val y = 1; } - class Sub2() extends Base() { + abstract class Sub2() extends Base() { override val Pair(x, y) = Pair("abc", 1); } -} \ No newline at end of file +} -- cgit v1.2.3