summaryrefslogtreecommitdiff
path: root/sources/scalac/typechecker
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/typechecker
parent3228df8eafa7a70792615356042b427595999b26 (diff)
downloadscala-ec46a90f5cd17d5ed506201bdc0b0a55324dffae.tar.gz
scala-ec46a90f5cd17d5ed506201bdc0b0a55324dffae.tar.bz2
scala-ec46a90f5cd17d5ed506201bdc0b0a55324dffae.zip
*** empty log message ***
Diffstat (limited to 'sources/scalac/typechecker')
-rw-r--r--sources/scalac/typechecker/Analyzer.java79
-rw-r--r--sources/scalac/typechecker/RefCheck.java71
2 files changed, 108 insertions, 42 deletions
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));
}
-
}
}