From f7f15007686e355a2d8668bf890603be90810e29 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Mon, 19 May 2003 11:12:09 +0000 Subject: *** empty log message *** --- sources/scalac/symtab/Symbol.java | 3 +- sources/scalac/symtab/Type.java | 146 +++++++++++++++++++++++- sources/scalac/transformer/LambdaLift.java | 7 +- sources/scalac/transformer/LambdaLiftPhase.java | 27 ++++- sources/scalac/typechecker/Analyzer.java | 76 ++++-------- 5 files changed, 195 insertions(+), 64 deletions(-) (limited to 'sources/scalac') diff --git a/sources/scalac/symtab/Symbol.java b/sources/scalac/symtab/Symbol.java index 3bb3f76e87..a259e0d62f 100644 --- a/sources/scalac/symtab/Symbol.java +++ b/sources/scalac/symtab/Symbol.java @@ -748,7 +748,8 @@ public abstract class Symbol implements Modifiers, Kinds { /** String representation of location. */ public String locationString() { - if (owner.kind == CLASS && !owner.isAnonymousClass()) + if (owner.kind == CLASS && !owner.isAnonymousClass() || + Global.instance.debug) return " in " + owner; else return ""; diff --git a/sources/scalac/symtab/Type.java b/sources/scalac/symtab/Type.java index 110a0f80bc..15c3d47649 100644 --- a/sources/scalac/symtab/Type.java +++ b/sources/scalac/symtab/Type.java @@ -141,6 +141,7 @@ public class Type implements Modifiers, Kinds, TypeTags { public Type widen() { return type().widen(); } + /** If this type is a singleton type whose type is another, the end of the chain, * otherwise the type itself. */ @@ -235,6 +236,25 @@ public class Type implements Modifiers, Kinds, TypeTags { return this; } + /** The lower approximation of this type (which must be a typeref) + */ + public Type loBound() { + switch (unalias()) { + case TypeRef(Type pre, Symbol sym, Type[] args): + Type lb = Global.instance.definitions.ANY_TYPE; + if (sym.kind == TYPE) { + lb = sym.loBound().asSeenFrom(pre, sym.owner()); + } + if (lb.isSameAs(Global.instance.definitions.ANY_TYPE) && + this.isSubType(Global.instance.definitions.ANYREF_TYPE)) { + lb = Global.instance.definitions.ANYREF_TYPE; + } + return lb; + default: + throw new ApplicationError(); + } + } + /** The thistype or singleton type corresponding to values of this type. */ public Type narrow() { @@ -1306,9 +1326,7 @@ public class Type implements Modifiers, Kinds, TypeTags { case TypeRef(_, Symbol sym, _): switch (that) { case TypeRef(Type pre1, Symbol sym1, _): - if (sym1.kind == TYPE && - this.isSubType( - sym1.loBound().asSeenFrom(pre1, sym1.owner()))) + if (sym1.kind == TYPE && this.isSubType(that.loBound())) return true; } if (sym.kind == ALIAS) @@ -1826,7 +1844,6 @@ public class Type implements Modifiers, Kinds, TypeTags { } /** Return the least upper bound of non-empty array of types `tps'. - * todo: treat types with refinements */ public static Type lub(Type[] tps) { //System.out.println("lub" + ArrayApply.toString(tps));//DEBUG @@ -1922,11 +1939,130 @@ public class Type implements Modifiers, Kinds, TypeTags { } private static Type glb(Type[] tps) { + // step one: eliminate redunandant types; return if one one is left tps = elimRedundant(tps, false); if (tps.length == 1) return tps[0]; - else return NoType; + + // step two: build arrays of all typerefs and all refinements + Type.List treftl = Type.List.EMPTY; + Type.List comptl = Type.List.EMPTY; + for (int i = 0; i < tps.length; i++) { + switch (tps[i]) { + case TypeRef(_, _, _): + treftl = new Type.List(tps[i], treftl); + break; + case CompoundType(Type[] parents, Scope members): + if (members.elems != Scope.Entry.NONE) + comptl = new Type.List(tps[i], comptl); + for (int j = 0; j < parents.length; j++) + treftl = new Type.List(parents[i], treftl); + break; + case ThisType(_): + case SingleType(_, _): + return Global.instance.definitions.ALL_TYPE; + } + } + + CompoundType glbType = compoundType(Type.EMPTY_ARRAY, new Scope()); + Type glbThisType = glbType.narrow(); + + // step 3: compute glb of all refinements. + Scope members = Scope.EMPTY; + if (comptl != List.EMPTY) { + Type[] comptypes = comptl.toArrayReverse(); + Scope[] refinements = new Scope[comptypes.length]; + for (int i = 0; i < comptypes.length; i++) + refinements[i] = comptypes[i].members(); + if (!setGlb(glbType.members, refinements, glbThisType)) { + // refinements don't have lower bound, so approximate + // by AllRef + glbType.members = Scope.EMPTY; + treftl = new Type.List( + Global.instance.definitions.ALLREF_TYPE, treftl); + } + } + + // eliminate redudant typerefs + Type[] treftypes = elimRedundant(treftl.toArrayReverse(), false); + if (treftypes.length != 1 || glbType.members.elems != Scope.Entry.NONE) { + // step 4: replace all abstract types by their lower bounds. + boolean hasAbstract = false; + for (int i = 0; i < treftypes.length; i++) { + if (treftypes[i].unalias().symbol().kind == TYPE) + hasAbstract = true; + } + if (hasAbstract) { + treftl = Type.List.EMPTY; + for (int i = 0; i < treftypes.length; i++) { + if (treftypes[i].unalias().symbol().kind == TYPE) + treftl = new Type.List(treftypes[i].loBound(), treftl); + else + treftl = new Type.List(treftypes[i], treftl); + } + treftypes = elimRedundant(treftl.toArrayReverse(), false); + } + } + + if (treftypes.length != 1) { + // step 5: if there are conflicting instantiations of same + // class, replace them by lower bound. + Type lb = NoType; + for (int i = 0; + i < treftypes.length && + lb != Global.instance.definitions.ALL_TYPE; + i++) { + for (int j = 0; j < i; j++) { + if (treftypes[j].symbol() == treftypes[i].symbol()) + lb = treftypes[i].loBound(); + } + } + if (lb != NoType) return lb; + } + + if (treftypes.length == 1 && glbType.members.elems == Scope.Entry.NONE) { + return treftypes[0]; + } else { + glbType.parts = treftypes; + return glbType; + } + } + + private static boolean setGlb(Scope result, Scope[] ss, Type glbThisType) { + for (int i = 0; i < ss.length; i++) + for (Scope.Entry e = ss[i].elems; e != Scope.Entry.NONE; e = e.next) + if (!addMember(result, e.sym, glbThisType)) return false; + return true; } + private static boolean addMember(Scope s, Symbol sym, Type glbThisType) { + Type syminfo = sym.info().substThis(sym.owner(), glbThisType); + Scope.Entry e = s.lookupEntry(sym.name); + if (e == Scope.Entry.NONE) { + Symbol sym1 = sym.cloneSymbol(); + sym1.setOwner(glbThisType.symbol()); + sym1.setInfo(syminfo); + s.enter(sym1); + return true; + } else { + Type einfo = e.sym.info(); + if (einfo.isSameAs(syminfo)) { + return true; + } else if (einfo.isSubType(syminfo) && sym.kind != ALIAS) { + return true; + } else if (syminfo.isSubType(einfo) && e.sym.kind != ALIAS) { + e.sym.setInfo(syminfo); + return true; + } else if (sym.kind == VAL && e.sym.kind == VAL || + sym.kind == TYPE && e.sym.kind == TYPE) { + e.sym.setInfo(glb(new Type[]{einfo, syminfo})); + return true; + } else { + return false; + } + } + } + + // Erasure -------------------------------------------------------------------------- public static Map erasureMap = new MapOnlyTypes() { diff --git a/sources/scalac/transformer/LambdaLift.java b/sources/scalac/transformer/LambdaLift.java index e6d2fc902b..fd89c3c260 100644 --- a/sources/scalac/transformer/LambdaLift.java +++ b/sources/scalac/transformer/LambdaLift.java @@ -310,7 +310,9 @@ public class LambdaLift extends OwnerTransformer public Tree transform(Tree tree) { //global.debugPrinter.print("lifting ").print(tree).println().end();//DEBUG + //System.out.print(tree.type + " --> ");//DEBUG tree.type = descr.transform(tree.type, currentOwner); + //System.out.println(tree.type);//DEBUG switch (tree) { case ClassDef(_, _, TypeDef[] tparams, ValDef[][] vparams, Tree tpe, Template impl): Symbol sym = tree.symbol(); @@ -403,7 +405,7 @@ public class LambdaLift extends OwnerTransformer return copy.Apply( tree, fn1, addFreeArgs(tree.pos, get(free.fvs, fsym), args1)); - case Ident(_): + case Ident(Name name): Symbol sym = tree.symbol(); if (sym.isLocal() && (sym.kind == TYPE || (sym.kind == VAL && !sym.isMethod()))) { @@ -411,6 +413,7 @@ public class LambdaLift extends OwnerTransformer } Tree tree1 = copy.Ident(tree, sym).setType( sym.typeAt(descr.nextPhase)); + if (name != sym.name) ((Ident)tree1).name = sym.name; if ((sym.flags & CAPTURED) != 0) return gen.Select(tree1, Names.elem); else return tree1; @@ -563,7 +566,7 @@ public class LambdaLift extends OwnerTransformer gen.mkRef( pos, global.definitions.getClass(Names.scala_COLONCOLON).constructor()), - new Tree[]{gen.mkType(pos, elemtpe), gen.mkType(pos, elemtpe)}), + new Tree[]{gen.mkType(pos, elemtpe)}), new Tree[]{hd, tl})); } } diff --git a/sources/scalac/transformer/LambdaLiftPhase.java b/sources/scalac/transformer/LambdaLiftPhase.java index 11141db9b2..df31745da5 100644 --- a/sources/scalac/transformer/LambdaLiftPhase.java +++ b/sources/scalac/transformer/LambdaLiftPhase.java @@ -13,6 +13,7 @@ import scalac.util.*; import scalac.parser.*; import scalac.symtab.*; import scalac.checkers.*; +import java.util.ArrayList; public class LambdaLiftPhase extends PhaseDescriptor implements Kinds, Modifiers { @@ -43,7 +44,7 @@ public class LambdaLiftPhase extends PhaseDescriptor implements Kinds, Modifiers public Type transformInfo(Symbol sym, Type tp) { if (global.debug) - global.log("transform info for " + sym + sym.locationString()); + global.log("transform info for " + sym + ":" + tp + sym.locationString()); Type tp1 = tp; if (sym != Symbol.NONE) { switch (tp) { @@ -53,7 +54,7 @@ public class LambdaLiftPhase extends PhaseDescriptor implements Kinds, Modifiers break; default: if (sym.kind == CLASS) - tp = transform(tp, sym); + tp1 = transform(tp, sym); else tp1 = transform(tp, sym.owner()); } @@ -70,6 +71,7 @@ public class LambdaLiftPhase extends PhaseDescriptor implements Kinds, Modifiers private class TransformTypeMap extends Type.MapOnlyTypes { Symbol owner; +// ArrayList/**/ excluded = new ArrayList(); Type.Map setOwner(Symbol owner) { this.owner = owner; return this; } public Type apply(Type tp) { @@ -95,9 +97,24 @@ public class LambdaLiftPhase extends PhaseDescriptor implements Kinds, Modifiers } return Type.TypeRef(pre, sym, targs1); } + } else if (sym.isLocal()) { + assert targs.length == 0; + return proxy(sym, owner).type(); } } break; +/* + case PolyType(Symbol[] tparams, _): + if (tparams.length != 0) { + int len = excluded.size(); + for (int i = 0; i < tparams.length; i++) + excluded.add(tparams[i]); + Type tp1 = map(tp); + for (int i = 0; i < tparams.length; i++) + excluded.remove(excluded.size() - 1); + return tp1; + } +*/ } return map(tp); } @@ -116,7 +133,7 @@ public class LambdaLiftPhase extends PhaseDescriptor implements Kinds, Modifiers */ Symbol proxy(Symbol fv, Symbol owner) { if (global.debug) - global.log("proxy " + fv + " in " + LambdaLift.asFunction(owner)); + global.log("proxy " + fv + " of " + fv.owner() + " in " + LambdaLift.asFunction(owner)); Symbol o = owner; while (o.kind != NONE) { if (global.debug) @@ -134,9 +151,9 @@ public class LambdaLiftPhase extends PhaseDescriptor implements Kinds, Modifiers } assert o.owner() != o; o = o.owner(); - } - throw new ApplicationError("proxy " + fv + " in " + owner); + return fv; + //throw new ApplicationError("proxy " + fv + " in " + owner); } /** The type scala.Ref[tp] diff --git a/sources/scalac/typechecker/Analyzer.java b/sources/scalac/typechecker/Analyzer.java index f4d2ed8fa0..2bec0ab167 100644 --- a/sources/scalac/typechecker/Analyzer.java +++ b/sources/scalac/typechecker/Analyzer.java @@ -380,39 +380,38 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { */ void validateBaseTypes(Symbol clazz) { validateBaseTypes(clazz, clazz.type().parents(), - new boolean[clazz.closure().length], 0); + new Type[clazz.closure().length], 0); } //where - void validateBaseTypes(Symbol clazz, Type[] tps, boolean[] seen, int start) { + 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, boolean[] seen, int start) { + 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]) { + if (seen[index] != null) { // check that only uniform classes are inherited several times. if (!clazz.isCompoundSym() && !baseclazz.isTrait()) { error(clazz.pos, "illegal inheritance;\n" + clazz + " inherits " + baseclazz + " twice"); } - // check no two different type instances of same class - // are inherited. - Type tp1 = clazz.closure()[index]; - if (!tp1.isSameAs(tp)) { + // if there are two different type instances of same class + // check that second is a subtype of first. + if (!seen[index].isSubType(tp)) { if (clazz.isCompoundSym()) error(clazz.pos, "illegal combination;\n " + "compound type " + " combines different type instances of " + - baseclazz + ":\n" + tp + " and " + tp1); + baseclazz + ":\n" + tp + " and " + seen[index]); else error(clazz.pos, "illegal inheritance;\n " + clazz + " inherits different type instances of " + - baseclazz + ":\n" + tp + " and " + tp1); + baseclazz + ":\n" + tp + " and " + seen[index]); } } // check that case classes do not inherit from case classes @@ -420,7 +419,7 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { error(clazz.pos, "illegal inheritance;\n " + "case " + clazz + " inherits from other case " + baseclazz); - seen[index] = true; + seen[index] = tp; validateBaseTypes(clazz, tp.parents(), seen, start); } } @@ -468,8 +467,7 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { checkNonCyclic( pos, pre.memberInfo(sym).subst(sym.typeParams(), args)); if (sym.kind == TYPE) - checkNonCyclic( - pos, sym.loBound().asSeenFrom(pre, sym.owner())); + checkNonCyclic(pos, tp.loBound()); sym.flags &= ~LOCKED; } break; @@ -755,7 +753,7 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { void validateVariance(Symbol base, Type all, Type[] tps, int variance, Symbol[] tparams) { for (int i = 0; i < tps.length; i++) - if (tps[i] != tparams[i].type()) +// if (tps[i] != tparams[i].type()) validateVariance(base, all, tps[i], variance * tparams[i].variance()); } @@ -825,12 +823,16 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { if (clazz.isLocalClass()) unit.mangler.setMangledName(clazz); enterSym(tree, clazz.constructor()); - if ((mods & (ABSTRACTCLASS | CASE)) == CASE) { - // enter case constructor method. - enterInScope( - new TermSymbol( - tree.pos, name.toTermName(), owner, mods & (ACCESSFLAGS | CASE)) - .setInfo(new LazyConstrMethodType(tree))); + if ((mods & CASE) != 0) { + if (vparams.length == 0) { + error(tree.pos, "case class needs () parameter section"); + } else if ((mods & ABSTRACTCLASS) == 0) { + // enter case constructor method. + enterInScope( + new TermSymbol( + tree.pos, name.toTermName(), owner, mods & (ACCESSFLAGS | CASE)) + .setInfo(new LazyConstrMethodType(tree))); + } } return enterSym(tree, clazz); @@ -1755,30 +1757,11 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { return tree; } else { Symbol sym = tree.symbol(); - // convert nullary case methods to types - // check that other idents or selects are stable. + // check that idents or selects are stable. switch (tree) { case Ident(_): - if (sym != null && isNullaryMethod(sym) && (sym.flags & CASE) != 0) - return transform( - make.Apply( - tree.pos, - copy.Ident(tree, sym.type().resultType().symbol()), - Tree.EMPTY_ARRAY), - mode, pt); - else - checkStable(tree); - break; - case Select(Tree qual, _): - if (sym != null && isNullaryMethod(sym) && (sym.flags & CASE) != 0) - return transform( - make.Apply( - tree.pos, - copy.Select(tree, sym.type().resultType().symbol(), qual), - Tree.EMPTY_ARRAY), - mode, pt); - else - checkStable(tree); + case Select(_, _): + checkStable(tree); } } } else if ((mode & EXPRmode) != 0) { @@ -1815,15 +1798,6 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { return tree; } //where - boolean isNullaryMethod(Symbol sym) { - switch (sym.type()) { - case PolyType(_, Type restpe): - return !(restpe instanceof Type.MethodType); - default: - return false; - } - } - Type seqConstructorType(Type paramtp, Type resulttp) { Symbol constr = resulttp.symbol().constructor(); Symbol param = new TermSymbol( -- cgit v1.2.3