summaryrefslogtreecommitdiff
path: root/sources/scalac
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2003-09-02 12:57:45 +0000
committerMartin Odersky <odersky@gmail.com>2003-09-02 12:57:45 +0000
commitec46a90f5cd17d5ed506201bdc0b0a55324dffae (patch)
treedb322d9b07f1a8ae3417d757a22549039293e9fc /sources/scalac
parent3228df8eafa7a70792615356042b427595999b26 (diff)
downloadscala-ec46a90f5cd17d5ed506201bdc0b0a55324dffae.tar.gz
scala-ec46a90f5cd17d5ed506201bdc0b0a55324dffae.tar.bz2
scala-ec46a90f5cd17d5ed506201bdc0b0a55324dffae.zip
*** empty log message ***
Diffstat (limited to 'sources/scalac')
-rw-r--r--sources/scalac/ast/TreeGen.java2
-rw-r--r--sources/scalac/symtab/Definitions.java4
-rw-r--r--sources/scalac/symtab/Modifiers.java1
-rw-r--r--sources/scalac/symtab/Symbol.java11
-rw-r--r--sources/scalac/symtab/Type.java6
-rw-r--r--sources/scalac/symtab/classfile/JavaTypeCreator.java8
-rw-r--r--sources/scalac/typechecker/Analyzer.java79
-rw-r--r--sources/scalac/typechecker/RefCheck.java71
8 files changed, 125 insertions, 57 deletions
diff --git a/sources/scalac/ast/TreeGen.java b/sources/scalac/ast/TreeGen.java
index 751e78044d..34a334b3e7 100644
--- a/sources/scalac/ast/TreeGen.java
+++ b/sources/scalac/ast/TreeGen.java
@@ -487,6 +487,7 @@ public class TreeGen implements Kinds, Modifiers, TypeTags {
Global.instance.nextPhase();
Type symtype = qual.type.memberType(sym);
Global.instance.prevPhase();
+ sym.flags |= ACCESSED | SELECTOR;
return make.Select(pos, sym, qual).setType(deref(symtype));
}
@@ -506,6 +507,7 @@ public class TreeGen implements Kinds, Modifiers, TypeTags {
Global.instance.nextPhase();
Type symtype = sym.type();
Global.instance.prevPhase();
+ sym.flags |= ACCESSED;
return make.Ident(pos, sym).setType(deref(symtype));
}
diff --git a/sources/scalac/symtab/Definitions.java b/sources/scalac/symtab/Definitions.java
index ac4d38e261..7a33403004 100644
--- a/sources/scalac/symtab/Definitions.java
+++ b/sources/scalac/symtab/Definitions.java
@@ -361,13 +361,13 @@ public class Definitions {
EQUALS = new TermSymbol(
Position.NOPOS, Names.equals, ANY_CLASS, 0);
- EQUALS.setInfo(Type.MethodType(new Symbol[]{newParameter(EQUALS, JAVA_OBJECT_TYPE)},
+ EQUALS.setInfo(Type.MethodType(new Symbol[]{newParameter(EQUALS, ANY_TYPE)},
BOOLEAN_TYPE));
ANY_CLASS.members().enter(EQUALS);
EQ = new TermSymbol(
Position.NOPOS, Names.eq, ANY_CLASS, 0);
- EQ.setInfo(Type.MethodType(new Symbol[]{newParameter(EQ, JAVA_OBJECT_TYPE)},
+ EQ.setInfo(Type.MethodType(new Symbol[]{newParameter(EQ, ANY_TYPE)},
BOOLEAN_TYPE));
ANY_CLASS.members().enter(EQ);
diff --git a/sources/scalac/symtab/Modifiers.java b/sources/scalac/symtab/Modifiers.java
index e53bbd92d4..242e6c64ce 100644
--- a/sources/scalac/symtab/Modifiers.java
+++ b/sources/scalac/symtab/Modifiers.java
@@ -62,7 +62,6 @@ public interface Modifiers {
int SOURCEFLAGS = 0x00000077 | DEF | REPEATED | MODUL | MUTABLE | PACKAGE | PARAM | TRAIT | COVARIANT | CONTRAVARIANT; // these modifiers can be set in source programs.
int ACCESSFLAGS = PRIVATE | PROTECTED;
int VARIANCES = COVARIANT | CONTRAVARIANT;
- int OVERLOADFLAGS = DEFERRED | OVERRIDE | FINAL;
public static class Helper {
diff --git a/sources/scalac/symtab/Symbol.java b/sources/scalac/symtab/Symbol.java
index ca36dfb663..e36dc1489e 100644
--- a/sources/scalac/symtab/Symbol.java
+++ b/sources/scalac/symtab/Symbol.java
@@ -977,13 +977,8 @@ public abstract class Symbol implements Modifiers, Kinds {
assert isTerm() : Debug.show(this);
assert this.name == that.name : Debug.show(this) + " <> " + Debug.show(that);
assert this.owner == that.owner : Debug.show(this) + " != " + Debug.show(that);
- assert (this.flags & that.flags & JAVA) != 0 ||
- (this.flags & OVERLOADFLAGS) == (that.flags & OVERLOADFLAGS)
- : Integer.toHexString(this.flags) + "@" + Debug.show(this) + " <> " + Integer.toHexString(that.flags) + "@" + Debug.show(that);
assert this.isConstructor() == that.isConstructor();
- int overflags =
- ((this.flags | that.flags) & (JAVA | OVERLOADFLAGS)) |
- (this.flags & that.flags & ACCESSFLAGS);
+ int overflags = this.flags & that.flags & (JAVA | ACCESSFLAGS);
TermSymbol overloaded = (this.isConstructor())
? TermSymbol.newConstructor(this.constructorClass(), overflags)
: new TermSymbol(pos, name, owner, overflags);
@@ -1062,8 +1057,8 @@ public abstract class Symbol implements Modifiers, Kinds {
}
}
- /** The symbol which is overridden by this symbol in base class `base'
- * `base' must be a superclass of this.owner().
+ /** The symbol which overrides this symbol in subclass `sub'
+ * `sub' must be a subclass of this.owner().
*/
public Symbol overridingSymbol(Type sub) {
assert !isOverloaded() : this;
diff --git a/sources/scalac/symtab/Type.java b/sources/scalac/symtab/Type.java
index 339c09b38a..21fdf32917 100644
--- a/sources/scalac/symtab/Type.java
+++ b/sources/scalac/symtab/Type.java
@@ -1447,7 +1447,7 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags {
for (int i = 0; i < ps.length; i++) {
Symbol p1 = ps1[i];
Symbol p = ps[i];
- if (!p1.type().isSubType(p.type()) ||
+ if (!p1.type().isSameAs(p.type()) ||
(p1.flags & (Modifiers.DEF | Modifiers.REPEATED)) !=
(p.flags & (Modifiers.DEF | Modifiers.REPEATED)))
return false;
@@ -1461,8 +1461,8 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags {
case PolyType(Symbol[] ps, Type res):
if (ps.length != ps1.length) return false;
for (int i = 0; i < ps.length; i++)
- if (!ps1[i].info().subst(ps1, ps).isSubType(ps[i].info()) ||
- !ps[i].loBound().isSubType(ps1[i].loBound().subst(ps1, ps)))
+ if (!ps1[i].info().subst(ps1, ps).isSameAs(ps[i].info()) ||
+ !ps[i].loBound().isSameAs(ps1[i].loBound().subst(ps1, ps)))
return false;
return res.isSubType(res1.subst(ps1, ps));
}
diff --git a/sources/scalac/symtab/classfile/JavaTypeCreator.java b/sources/scalac/symtab/classfile/JavaTypeCreator.java
index 9ef282ba56..395778adec 100644
--- a/sources/scalac/symtab/classfile/JavaTypeCreator.java
+++ b/sources/scalac/symtab/classfile/JavaTypeCreator.java
@@ -72,10 +72,16 @@ public class JavaTypeCreator implements JavaTypeFactory {
for (int i = 0; i < args.length; i++) {
args[i] = new TermSymbol(
Position.NOPOS, Name.fromString("x" + i), Symbol.NONE, Modifiers.PARAM);
- args[i].setInfo(argtpes[i]);
+ args[i].setInfo(objToAny(argtpes[i]));
}
return new MethodType(args, restpe);
}
+ private Type objToAny(Type tp) {
+ if (tp.isSameAs(global.definitions.JAVA_OBJECT_TYPE))
+ return global.definitions.ANY_TYPE;
+ else
+ return tp;
+ }
public Type packageType(Name packagename) {
return null;
diff --git a/sources/scalac/typechecker/Analyzer.java b/sources/scalac/typechecker/Analyzer.java
index 6d54de146c..55b6324880 100644
--- a/sources/scalac/typechecker/Analyzer.java
+++ b/sources/scalac/typechecker/Analyzer.java
@@ -212,20 +212,44 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
/** Check that `sym' is accessible as a member of tree `site' in current context.
*/
- void checkAccessible(int pos, Symbol sym, Tree site) {
- 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");
+ Type checkAccessible(int pos, Symbol sym, Type symtype, Tree site) {
+ switch (symtype) {
+ case OverloadedType(Symbol[] alts, Type[] alttypes):
+ int nacc = 0;
+ for (int i = 0; i < alts.length; i++) {
+ if (isAccessible(alts[i], site)) {
+ nacc++;
+ }
+ }
+ if (nacc == 0) {
+ error(pos, sym + " cannot be accessed in " + site.type.widen());
+ return Type.ErrorType;
+ } else {
+ Symbol[] alts1 = new Symbol[nacc];
+ Type[] alttypes1 = new Type[nacc];
+ nacc = 0;
+ for (int i = 0; i < alts.length; i++) {
+ if (isAccessible(alts[i], site)) {
+ alts1[nacc] = alts[i];
+ alttypes1[nacc] = alttypes[i];
+ nacc++;
+ }
+ }
+ return Type.OverloadedType(alts1, alttypes1);
+ }
+ default:
+ if (isAccessible(sym, site)) {
+ return symtype;
+ } else {
+ error(pos, sym + " cannot be accessed in " + site.type.widen());
+ return Type.ErrorType;
+ }
}
}
/** Is `sym' accessible as a member of tree `site' in current context?
*/
- boolean isAccessible(Symbol sym, Tree site) {
+ private boolean isAccessible(Symbol sym, Tree site) {
return
(sym.flags & (PRIVATE | PROTECTED)) == 0
||
@@ -783,8 +807,10 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
Symbol owner = sym.owner();
if (sym.kind == VAL && (sym.flags & (PRIVATE | SEALED)) == 0 &&
owner != null && owner.kind == CLASS &&
- (owner.flags & FINAL) != 0)
+ (owner.flags & FINAL) != 0) {
+ System.out.println(sym + " is final");
sym.flags |= FINAL;
+ }
sym = enterInScope(sym);
}
tree.setSymbol(sym);
@@ -835,6 +861,7 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
context.scope.enter(sym);
} else if (sym.kind == VAL && other.kind == VAL) {
// it's an overloaded definition
+ /*
if (((sym.flags ^ other.flags) & SOURCEFLAGS) != 0) {
// todo: refine, DEFERRED, MUTABLE and OVERRIDE should be
// treated specially; maybe only PRIVATE and PROTECTED?
@@ -843,9 +870,8 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
": modifier lists differ in " +
Modifiers.Helper.toString(
(sym.flags ^ other.flags) & SOURCEFLAGS));
- } else {
- e.setSymbol(other.overloadWith(sym));
- }
+ */
+ e.setSymbol(other.overloadWith(sym));
} else {
error(sym.pos,
sym.nameString() + " is already defined as " +
@@ -1247,11 +1273,13 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
if (tree.type.isObjectType()) {
// insert apply method
Symbol applyMeth = tree.type.lookup(Names.apply);
- if (applyMeth != Symbol.NONE && isAccessible(applyMeth, tree)) {
- applyMeth.flags |= (ACCESSED | SELECTOR);
+ if (applyMeth != Symbol.NONE) {
+ Type applyType = checkAccessible(
+ tree.pos, applyMeth, tree.type.memberType(applyMeth),
+ tree);
tree = make.Select(tree.pos, tree, Names.apply)
.setSymbol(applyMeth)
- .setType(tree.type.memberType(applyMeth));
+ .setType(applyType);
return adapt(tree, mode, pt);
}
}
@@ -1362,14 +1390,11 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
//System.out.println(name);//DEBUG
return error(tree.pos, "not found: " + decode(name));
} else {
- sym.flags |= ACCESSED;
if (sym.owner().kind == CLASS) {
pre = nextcontext.enclClass.owner.thisType();
if (!sym.owner().isPackage()) {
Tree qual1 = makeStableId(tree.pos, pre);
tree = make.Select(tree.pos, qual1, name);
- if (context.enclClass != nextcontext.enclClass)
- sym.flags |= SELECTOR;
//System.out.println(name + " :::> " + tree + " " + qual1.symbol());//DEBUG
}
} else {
@@ -1395,15 +1420,15 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
nextimports = nextimports.prev;
}
sym = sym1;
- sym.flags |= (ACCESSED | SELECTOR);
qual = lastimports.importPrefix().duplicate();
pre = qual.type;
//new TextTreePrinter().print(name + " => ").print(lastimports.tree).print("." + name).println().end();//DEBUG
tree = make.Select(tree.pos, qual, name);
}
- if (qual != Tree.Empty) checkAccessible(tree.pos, sym, qual);
Type symtype = (sym.isType() ? sym.typeConstructor() : sym.type())
.asSeenFrom(pre, sym.owner());
+ if (qual != Tree.Empty)
+ symtype = checkAccessible(tree.pos, sym, symtype, qual);
if (symtype == Type.NoType)
return error(tree.pos, "not found: " + decode(name));
if ((pt != null && pt.isStable() || (mode & QUALmode) != 0) && sym.isStable()) {
@@ -1430,14 +1455,12 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
return error(tree.pos,
decode(name) + " is not a member of " + qual.type.widen());
} else {
- checkAccessible(tree.pos, sym, qual);
- sym.flags |= ACCESSED;
- if (!TreeInfo.isSelf(qual, context.enclClass.owner))
- sym.flags |= SELECTOR;
Type symtype = (sym.isType() ? sym.typeConstructor() : sym.type())
.asSeenFrom(qual.type, sym.owner());
if (symtype == Type.NoType)
return error(tree.pos, "not found: " + decode(name));
+ else
+ symtype = checkAccessible(tree.pos, sym, symtype, qual);
//System.out.println(sym.name + ":" + symtype);//DEBUG
if (uninst.length != 0) {
switch (symtype) {
@@ -2144,8 +2167,7 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
Symbol tsym = TreeInfo.methSymbol(fn1);
if (tsym.kind != ERROR) {
assert tsym.isType() : tsym;
- Type tp = fn1.type.unalias();
- switch (tp) {
+ switch (fn1.type.unalias()) {
case TypeRef(Type pre, Symbol c, Type[] argtypes):
if (c.kind == CLASS) {
c.initialize();
@@ -2154,7 +2176,8 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
fn1 = gen.mkRef(fn1.pos, pre, constr);
switch (fn1) {
case Select(Tree fn1qual, _):
- checkAccessible(fn1.pos, constr, fn1qual);
+ fn1.type = checkAccessible(
+ fn1.pos, constr, fn1.type, fn1qual);
}
if (tsym == c) {
switch (fn0) {
diff --git a/sources/scalac/typechecker/RefCheck.java b/sources/scalac/typechecker/RefCheck.java
index d25c547e20..24c452cf70 100644
--- a/sources/scalac/typechecker/RefCheck.java
+++ b/sources/scalac/typechecker/RefCheck.java
@@ -43,6 +43,7 @@ public class RefCheck extends Transformer implements Modifiers, Kinds {
private Unit unit;
private Definitions defs = global.definitions;
private Infer infer = new Infer(this);
+ private Symbol enclClass;
public void apply(Unit unit) {
this.unit = unit;
@@ -65,13 +66,17 @@ public class RefCheck extends Transformer implements Modifiers, Kinds {
Type[] closure = clazz.closure();
HashMap/*<Symbol,Symbol>*/ overrides = null;
for (int i = 0; i < closure.length; i++) {
- for (Scope.SymbolIterator it = closure[i].members().iterator();
+ for (Scope.SymbolIterator it = closure[i].members().iterator(true);
it.hasNext();) {
Symbol other = it.next();
- Symbol member = ((other.flags & PRIVATE) != 0) ? other
+ Symbol members = ((other.flags & PRIVATE) != 0) ? other
: clazz.info().lookup(other.name);
- if (member != other && member.kind != NONE)
- checkOverride(pos, clazz, member, other);
+ Symbol member = Symbol.NONE;
+ if (members.kind != NONE &&
+ members.owner() != other.owner() &&
+ (members.owner() == clazz ||
+ !members.owner().isSubClass(other.owner())))
+ member = checkOverride(pos, clazz, members, other);
if (clazz.kind == CLASS && (clazz.flags & ABSTRACTCLASS) == 0) {
if ((member.flags & DEFERRED) != 0) {
abstractClassError(
@@ -97,7 +102,7 @@ public class RefCheck extends Transformer implements Modifiers, Kinds {
if ((other.flags & DEFERRED) != 0) {
abstractClassError(
clazz, member + member.locationString() +
- " is marked `override' and overrides only abstract members");
+ " is marked `override' and overrides only abstract members" + other + other.locationString());
}
}
}
@@ -125,10 +130,33 @@ public class RefCheck extends Transformer implements Modifiers, Kinds {
* 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) {
+ Symbol checkOverride(int pos, Symbol clazz, Symbol members, Symbol other) {
+ Type self = clazz.thisType();
+ Symbol member = members;
+ Type memberinfo = normalizedInfo(self, member);
+ Type otherinfo = normalizedInfo(self, other);
+ switch (memberinfo) {
+ case OverloadedType(Symbol[] alts, Type[] alttypes):
+ for (int i = 0; i < alts.length; i++) {
+ if (alttypes[i].isSubType(otherinfo)) {
+ if (member == members) {
+ member = alts[i];
+ memberinfo = alttypes[i];
+ } else {
+ unit.error(
+ pos,
+ "ambiguous override: both " +
+ member + ":" + memberinfo +
+ "\n and " + alts[i] + ":" + alttypes[i] +
+ "\n override " + other + ":" + otherinfo +
+ other.locationString());
+ }
+ }
+ }
+ if (member == members) {
+ }
+ }
if (member.owner() == clazz) pos = member.pos;
- else if (member.owner().isSubClass(other.owner()))
- return; // everything was already checked elsewhere
if ((member.flags & PRIVATE) != 0) {
overrideError(pos, member, other, "has weaker access privileges; it should not be private");
@@ -149,7 +177,6 @@ public class RefCheck extends Transformer implements Modifiers, Kinds {
":\n both are inherited from mixin classes; " +
"\n an overriding definition in the current template is required");
} else {
- Type self = clazz.thisType();
switch (other.kind) {
case CLASS:
overrideError(pos, member, other, "cannot override a class");
@@ -162,9 +189,7 @@ public class RefCheck extends Transformer implements Modifiers, Kinds {
if (other.isConstructor())
overrideError(pos, member, other,
"cannot override a class constructor");
- Type selftype = normalizedInfo(self, member);
- Type othertype = normalizedInfo(self, other);
- if (!selftype.isSubType(othertype))
+ if (!memberinfo.isSubType(otherinfo))
overrideTypeError(pos, member, other, self, false);
if (member.kind == TYPE &&
!self.memberLoBound(other).isSubType(
@@ -173,6 +198,7 @@ public class RefCheck extends Transformer implements Modifiers, Kinds {
}
}
+ return member;
}
void overrideError(int pos, Symbol member, Symbol other, String msg) {
@@ -842,10 +868,14 @@ public class RefCheck extends Transformer implements Modifiers, Kinds {
Symbol sym = tree.symbol();
switch (tree) {
case ClassDef(_, _, Tree.AbsTypeDef[] tparams, Tree.ValDef[][] vparams, Tree tpe, Tree.Template templ):
+ Symbol enclClassPrev = enclClass;
+ enclClass = sym;
validateVariance(sym, sym.info(), CoVariance);
validateVariance(sym, sym.typeOfThis(), CoVariance);
- return super.transform(
+ Tree tree1 = super.transform(
copy.ClassDef(tree, tree.symbol(), tparams, vparams, tpe, addCaseMethods(templ, tree.symbol())));
+ enclClass = enclClassPrev;
+ return tree1;
case DefDef(_, _, _, _, _, _):
validateVariance(sym, sym.type(), CoVariance);
@@ -933,10 +963,23 @@ public class RefCheck extends Transformer implements Modifiers, Kinds {
maxindex[i] = symindex;
}
}
+ sym.flags |= ACCESSED;
return elimTypeNode(tree);
+
+ case Select(Tree qual, Name name):
+ 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");
+ }
+ return elimTypeNode(super.transform(tree));
+
default:
return elimTypeNode(super.transform(tree));
}
-
}
}