summaryrefslogtreecommitdiff
path: root/sources/scalac/symtab
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2003-04-30 09:06:27 +0000
committerMartin Odersky <odersky@gmail.com>2003-04-30 09:06:27 +0000
commit21f24de326d79515c44f80665f9679410389b1ab (patch)
treebc8820c917f88ecda8469c90bd7f7298fdc27975 /sources/scalac/symtab
parente0d3451834b3cc5748dadb6b53971c05878faee4 (diff)
downloadscala-21f24de326d79515c44f80665f9679410389b1ab.tar.gz
scala-21f24de326d79515c44f80665f9679410389b1ab.tar.bz2
scala-21f24de326d79515c44f80665f9679410389b1ab.zip
*** empty log message ***
Diffstat (limited to 'sources/scalac/symtab')
-rw-r--r--sources/scalac/symtab/Definitions.java38
-rw-r--r--sources/scalac/symtab/Symbol.java56
-rw-r--r--sources/scalac/symtab/Type.java109
-rw-r--r--sources/scalac/symtab/classfile/AttributeParser.java2
4 files changed, 178 insertions, 27 deletions
diff --git a/sources/scalac/symtab/Definitions.java b/sources/scalac/symtab/Definitions.java
index 93ab003055..5f2bf4735c 100644
--- a/sources/scalac/symtab/Definitions.java
+++ b/sources/scalac/symtab/Definitions.java
@@ -92,6 +92,16 @@ public class Definitions {
public final Symbol OBJECT_CLASS;
public final Type OBJECT_TYPE;
+ /** the scala.All class
+ */
+ public final Symbol ALL_CLASS;
+ public final Type ALL_TYPE;
+
+ /** the scala.AllRef class
+ */
+ public final Symbol ALLREF_CLASS;
+ public final Type ALLREF_TYPE;
+
/** the primitive types
*/
public final Symbol BYTE_CLASS;
@@ -220,6 +230,22 @@ public class Definitions {
ANYVAL_CLASS = getClass(Names.scala_AnyVal);
ANYVAL_TYPE = ANYVAL_CLASS.typeConstructor();
+ // the scala.ALL class
+ ALL_CLASS = new ClassSymbol(
+ Position.NOPOS, Names.All.toTypeName(), SCALA_CLASS, 0);
+ SCALA_CLASS.members().enter(ALL_CLASS);
+ ALL_TYPE = ALL_CLASS.typeConstructor();
+ ALL_CLASS.setInfo(Type.compoundType(new Type[]{ANY_TYPE}, new Scope(), ALL_CLASS));
+ ALL_CLASS.constructor().setInfo(Type.MethodType(Symbol.EMPTY_ARRAY, ALL_TYPE));
+
+ // the scala.ALLREF class
+ ALLREF_CLASS = new ClassSymbol(
+ Position.NOPOS, Names.AllRef.toTypeName(), SCALA_CLASS, 0);
+ SCALA_CLASS.members().enter(ALLREF_CLASS);
+ ALLREF_TYPE = ALLREF_CLASS.typeConstructor();
+ ALLREF_CLASS.setInfo(Type.compoundType(new Type[]{ANYREF_TYPE}, new Scope(), ALLREF_CLASS));
+ ALLREF_CLASS.constructor().setInfo(Type.MethodType(Symbol.EMPTY_ARRAY, ALLREF_TYPE));
+
// the primitive types
DOUBLE_CLASS = getClass(Names.scala_Double);
DOUBLE_TYPE = DOUBLE_CLASS.typeConstructor();
@@ -248,8 +274,7 @@ public class Definitions {
JAVA_THROWABLE_TYPE = JAVA_THROWABLE_CLASS.typeConstructor();
THROW = new TermSymbol(
Position.NOPOS, Names.throw_, JAVA_THROWABLE_CLASS, Modifiers.FINAL);
- Symbol tvar = newTypeParameter(THROW, ANY_TYPE);
- THROW.setInfo(Type.PolyType(new Symbol[]{tvar}, tvar.type()));
+ THROW.setInfo(ALL_TYPE);
JAVA_THROWABLE_CLASS.members().enter(THROW);
// add the java.lang.String class to the scala package
@@ -292,7 +317,7 @@ public class Definitions {
AS = new TermSymbol(
Position.NOPOS, Names.as, ANY_CLASS, Modifiers.FINAL);
- tvar = newTypeParameter(AS, ANY_TYPE);
+ Symbol tvar = newTypeParameter(AS, ANY_TYPE);
AS.setInfo(Type.PolyType(new Symbol[]{tvar}, tvar.type()));
ANY_CLASS.members().enter(AS);
@@ -327,8 +352,7 @@ public class Definitions {
// add a null value to the root scope
NULL = new TermSymbol(
Position.NOPOS, Names.null_, ROOT_CLASS, 0);
- tvar = newTypeParameter(NULL, ANYREF_TYPE);
- NULL.setInfo(Type.PolyType(new Symbol[]{tvar}, tvar.type()));
+ NULL.setInfo(ALLREF_TYPE);
ROOT.members().enter(NULL);
}
@@ -338,8 +362,8 @@ public class Definitions {
}
private Symbol newTypeParameter(Symbol owner, Type bound) {
- return new TypeSymbol(
- Kinds.TYPE, Position.NOPOS, Name.fromString("T").toTypeName(), owner, Modifiers.PARAM)
+ return new AbsTypeSymbol(
+ Position.NOPOS, Name.fromString("T").toTypeName(), owner, Modifiers.PARAM)
.setInfo(bound);
}
diff --git a/sources/scalac/symtab/Symbol.java b/sources/scalac/symtab/Symbol.java
index f2e387c67b..eeb4d6e647 100644
--- a/sources/scalac/symtab/Symbol.java
+++ b/sources/scalac/symtab/Symbol.java
@@ -141,6 +141,12 @@ public abstract class Symbol implements Modifiers, Kinds {
return this;
}
+ /** Set the low bound of this type variable
+ */
+ public Symbol setLoBound(Type lobound) {
+ throw new ApplicationError("setLoBound inapplicable for " + this);
+ }
+
// Symbol classification ----------------------------------------------------
/** Does this symbol denote a type? */
@@ -341,6 +347,14 @@ public abstract class Symbol implements Modifiers, Kinds {
}
}
+ /** The variance of this symbol as an integer
+ */
+ public int variance() {
+ if ((flags & COVARIANT) != 0) return 1;
+ else if ((flags & CONTRAVARIANT) != 0) return -1;
+ else return 0;
+ }
+
// Symbol names ----------------------------------------------------------------
/** Get the fully qualified name of this Symbol
@@ -592,6 +606,12 @@ public abstract class Symbol implements Modifiers, Kinds {
throw new ApplicationError("typeConstructor inapplicable for " + this);
}
+ /** The low bound of this type variable
+ */
+ public Type loBound() {
+ throw new ApplicationError("loBound inapplicable for " + this);
+ }
+
/** Get this.type corresponding to this symbol
*/
public Type thisType() {
@@ -1107,6 +1127,7 @@ public class TypeSymbol extends Symbol {
private void computeClosure() {
assert closures.closure != BAD_CLOSURE : this;
closures.closure = BAD_CLOSURE; // to catch cycles.
+ // todo: why can't we do: inclClosure(SymSet.EMPTY, this) ?
SymSet closureClassSet = inclClosureBases(SymSet.EMPTY, this);
Symbol[] closureClasses = new Symbol[closureClassSet.size() + 1];
closureClasses[0] = this;
@@ -1116,6 +1137,7 @@ public class TypeSymbol extends Symbol {
//System.out.println(ArrayApply.toString(closures.closure));//DEBUG
adjustType(type());
//System.out.println("closure(" + this + ") at " + Global.instance.currentPhase.name() + " = " + ArrayApply.toString(closures.closure));//DEBUG
+
}
//where
@@ -1151,6 +1173,36 @@ public class TypeSymbol extends Symbol {
}
}
+public class AbsTypeSymbol extends TypeSymbol {
+
+ private Type lobound = null;
+
+ /** Constructor */
+ public AbsTypeSymbol(int pos, Name name, Symbol owner, int flags) {
+ super(TYPE, pos, name, owner, flags);
+ }
+
+ /** Return a fresh symbol with the same fields as this one.
+ */
+ public Symbol cloneSymbol() {
+ if (Global.instance.debug) System.out.println("cloning " + this + this.locationString() + " in phase " + Global.instance.currentPhase.name());
+ TypeSymbol other = new AbsTypeSymbol(pos, name, owner(), flags);
+ other.setInfo(info());
+ other.setLoBound(loBound());
+ return other;
+ }
+
+ public Type loBound() {
+ initialize();
+ return lobound == null ? Global.instance.definitions.ALL_TYPE : lobound;
+ }
+
+ public Symbol setLoBound(Type lobound) {
+ this.lobound = lobound;
+ return this;
+ }
+}
+
/** A class for class symbols. It has JavaClassSymbol as a subclass.
*/
public class ClassSymbol extends TypeSymbol {
@@ -1377,6 +1429,10 @@ public final class ErrorSymbol extends Symbol {
return this;
}
+ public Type loBound() {
+ return Type.ErrorType;
+ }
+
public void reset(Type completer) {
}
}
diff --git a/sources/scalac/symtab/Type.java b/sources/scalac/symtab/Type.java
index d532db05c4..80e0823f97 100644
--- a/sources/scalac/symtab/Type.java
+++ b/sources/scalac/symtab/Type.java
@@ -489,6 +489,7 @@ public class Type implements Modifiers, Kinds, TypeTags {
}
/** Is this type a reference to an object type?
+ * todo: replace by this.isSubType(global.definitions.ANY_TYPE)?
*/
public boolean isObjectType() {
switch (unalias()) {
@@ -1266,7 +1267,10 @@ public class Type implements Modifiers, Kinds, TypeTags {
case TypeRef(Type pre1, Symbol sym1, Type[] args1):
switch (this) {
case TypeRef(Type pre, Symbol sym, Type[] args):
- if (sym == sym1 && pre.isSameAs(pre1) && isSubArgs(args, args1))
+ if (sym == sym1 && pre.isSameAs(pre1) &&
+ isSubArgs(args, args1, sym.typeParams())
+ ||
+ sym.kind == TYPE && pre.memberInfo(sym).isSubType(that))
return true;
break;
}
@@ -1355,11 +1359,26 @@ public class Type implements Modifiers, Kinds, TypeTags {
return constr.inst.isSubType(that);
} else {
constr.hibounds = new List(that.dropVariance(), constr.hibounds);
+ assert that.dropVariance().symbol() != Global.instance.definitions.ALL_CLASS;//debug
return true;
}
case TypeRef(_, Symbol sym, _):
- if (sym.kind == ALIAS) return this.unalias().isSubType(that);
+ switch (that) {
+ case TypeRef(Type pre1, Symbol sym1, _):
+ if (sym1.kind == TYPE &&
+ this.isSubType(
+ sym1.loBound().asSeenFrom(pre1, sym1.owner())))
+ return true;
+ }
+ if (sym.kind == ALIAS)
+ return this.unalias().isSubType(that);
+ else if (sym == Global.instance.definitions.ALL_CLASS)
+ return that.isSubType(Global.instance.definitions.ANY_TYPE);
+ else if (sym == Global.instance.definitions.ALLREF_CLASS)
+ return
+ that.isSameAs(Global.instance.definitions.ANY_TYPE) ||
+ that.isSubType(Global.instance.definitions.ANYREF_TYPE);
break;
case OverloadedType(Symbol[] alts, Type[] alttypes):
@@ -1390,7 +1409,7 @@ public class Type implements Modifiers, Kinds, TypeTags {
/** Are types `these' arguments types conforming to corresponding types `those'?
*/
- static boolean isSubArgs(Type[] these, Type[] those) {
+ static boolean isSubArgs(Type[] these, Type[] those, Symbol[] tparams) {
if (these.length != those.length) return false;
for (int i = 0; i < these.length; i++) {
switch (those[i]) {
@@ -1404,8 +1423,12 @@ public class Type implements Modifiers, Kinds, TypeTags {
}
break;
default:
- if (these[i].isCovarType() || !these[i].isSameAs(those[i]))
- return false;
+ if (these[i].isCovarType()) return false;
+ if ((tparams[i].flags & COVARIANT) != 0) {
+ if (!these[i].isSubType(those[i])) return false;
+ } else {
+ if (!these[i].isSameAs(those[i])) return false;
+ }
}
}
return true;
@@ -1811,7 +1834,8 @@ public class Type implements Modifiers, Kinds, TypeTags {
static Type arglub(Type[] types) {
Type pre = types[0].prefix();
Symbol sym = types[0].symbol();
- Type[] args = new Type[sym.typeParams().length];
+ Symbol[] tparams = sym.typeParams();
+ Type[] args = new Type[tparams.length];
Type[][] argss = new Type[args.length][types.length];
for (int i = 0; i < types.length; i++) {
switch (types[i]) {
@@ -1828,9 +1852,15 @@ public class Type implements Modifiers, Kinds, TypeTags {
}
}
for (int j = 0; j < args.length; j++) {
- args[j] = commonType(argss[j]);
- if (args[j] == NoType)
- args[j] = CovarType(lub(argss[j]));
+ if ((tparams[j].flags & COVARIANT) != 0) {
+ args[j] = commonType(argss[j]);
+ if (args[j] == NoType)
+ args[j] = lub(argss[j]);
+ } else { //todo: test if all same, return notype otherwise.
+ args[j] = commonType(argss[j]);
+ if (args[j] == NoType)
+ args[j] = CovarType(lub(argss[j]));
+ }
}
return typeRef(pre, sym, args);
}
@@ -1861,16 +1891,55 @@ public class Type implements Modifiers, Kinds, TypeTags {
*/
public static Type lub(Type[] tps) {
//System.out.println("lub" + ArrayApply.toString(tps));//DEBUG
+
+ // remove All and AllRef types
+ boolean all = false;
+ boolean allref = false;
+ for (int i = 0; i < tps.length; i++) {
+ if (!tps[i].isObjectType()) {
+ System.out.println("not an object type");
+ return Type.NoType;//todo: change
+ }
+ all |= tps[i].symbol() == Global.instance.definitions.ALL_CLASS;
+ allref |= tps[i].symbol() == Global.instance.definitions.ALLREF_CLASS;
+ }
+
+ if (all | allref) {
+ Type.List tl = Type.List.EMPTY;
+ for (int i = 0; i < tps.length; i++) {
+ if (tps[i].symbol() != Global.instance.definitions.ALL_CLASS &&
+ tps[i].symbol() != Global.instance.definitions.ALLREF_CLASS) {
+ if (allref &&
+ !tps[i].isSubType(Global.instance.definitions.ANYREF_TYPE))
+ return Global.instance.definitions.ANY_TYPE;
+ else
+ tl = new Type.List(tps[i], tl);
+ }
+ }
+ if (tl == Type.List.EMPTY) {
+ return allref ? Global.instance.definitions.ALLREF_TYPE
+ : Global.instance.definitions.ALL_TYPE;
+ }
+ tps = tl.toArrayReverse();
+ }
+
+ // fast path if all types agree.
Type lubType = commonType(tps);
if (lubType != NoType) return lubType;
+
+ // intersect closures and build frontier.
Type[][] closures = new Type[tps.length][];
for (int i = 0; i < tps.length; i++) {
- if (!tps[i].isObjectType()) return Type.NoType;//todo: change
closures[i] = tps[i].closure();
}
Type[] allBaseTypes = intersection(closures);
Type[] leastBaseTypes = frontier(allBaseTypes);
- if (leastBaseTypes.length == 0) return Type.NoType;
+ if (leastBaseTypes.length == 0) {
+ //System.out.println("empty intersection");//DEBUG
+ return Type.NoType;
+ }
+
+ // add refinements where necessary
Scope members = new Scope();
lubType = compoundType(leastBaseTypes, members);
Type lubThisType = lubType.narrow();
@@ -1936,7 +2005,7 @@ public class Type implements Modifiers, Kinds, TypeTags {
lubSym = new TermSymbol(syms[0].pos, syms[0].name, owner, 0);
break;
case TYPE: case ALIAS: case CLASS:
- lubSym = new TypeSymbol(TYPE, syms[0].pos, syms[0].name, owner, 0);
+ lubSym = new AbsTypeSymbol(syms[0].pos, syms[0].name, owner, 0);
break;
default:
throw new ApplicationError();
@@ -2022,10 +2091,9 @@ public class Type implements Modifiers, Kinds, TypeTags {
Name fullname = sym.fullName();
if (fullname == Names.scala_Array && args.length == 1
/*&& args[0].unalias().symbol().kind != TYPE Q: why needed?*/) {
- Global global = Global.instance;
Type bound = args[0].bound();
- if (bound.symbol() != global.definitions.ANY_CLASS &&
- bound.symbol() != global.definitions.ANYVAL_CLASS)
+ if (bound.symbol() != Global.instance.definitions.ANY_CLASS &&
+ bound.symbol() != Global.instance.definitions.ANYVAL_CLASS)
{
return UnboxedArrayType(args[0].erasure());
}
@@ -2051,10 +2119,13 @@ public class Type implements Modifiers, Kinds, TypeTags {
return pre.memberInfo(sym).erasure();
case CLASS:
- if (Global.instance.definitions.UNIT_CLASS == sym) return this;
- if (sym.fullName() == Names.java_lang_Object ||
- sym.fullName() == Names.scala_AnyRef ||
- sym.fullName() == Names.scala_AnyVal)
+ if (sym == Global.instance.definitions.UNIT_CLASS) return this;
+ Name fullname = sym.fullName();
+ if (fullname == Names.java_lang_Object ||
+ fullname == Names.scala_AnyRef ||
+ fullname == Names.scala_AnyVal ||
+ fullname == Names.scala_All ||
+ fullname == Names.scala_AllRef)
return Global.instance.definitions.ANY_TYPE;
else {
Type this1 = unbox();
diff --git a/sources/scalac/symtab/classfile/AttributeParser.java b/sources/scalac/symtab/classfile/AttributeParser.java
index a6ae0a9083..dba5daa3de 100644
--- a/sources/scalac/symtab/classfile/AttributeParser.java
+++ b/sources/scalac/symtab/classfile/AttributeParser.java
@@ -187,7 +187,7 @@ public class AttributeParser implements ClassfileConstants {
}
Symbol s = tvars.lookup(Name.fromString(name).toTypeName());
if (s == Symbol.NONE) {
- s = new TypeSymbol(Kinds.TYPE,
+ s = new AbsTypeSymbol(
Position.NOPOS,
Name.fromString(token).toTypeName(),
owner,