diff options
Diffstat (limited to 'sources/scalac/typechecker/Analyzer.java')
-rw-r--r-- | sources/scalac/typechecker/Analyzer.java | 143 |
1 files changed, 84 insertions, 59 deletions
diff --git a/sources/scalac/typechecker/Analyzer.java b/sources/scalac/typechecker/Analyzer.java index 232ba4a0c9..dd8a65ff22 100644 --- a/sources/scalac/typechecker/Analyzer.java +++ b/sources/scalac/typechecker/Analyzer.java @@ -27,6 +27,7 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { private final DeSugarize desugarize; private final AnalyzerPhase descr; final Infer infer; + final Transformer duplicator; public Analyzer(Global global, AnalyzerPhase descr) { super(global, descr); @@ -34,6 +35,8 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { this.descr = descr; this.infer = new Infer(this); this.desugarize = new DeSugarize(this, global); + this.duplicator = new Transformer( + global, descr, make, new StrictTreeFactory(make)); } /** Phase variables, used and set in transformers; @@ -152,19 +155,6 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { return fn.type == Type.ErrorType ? Type.ErrorType : Type.NoType; } - private Tree deepCopy(Tree tree) { - switch (tree) { - case Ident(Name name): - return make.Ident(tree.pos, name) - .setSymbol(tree.symbol()).setType(tree.type); - case Select(Tree qual, Name name): - return make.Select(tree.pos, deepCopy(qual), name) - .setSymbol(tree.symbol()).setType(tree.type); - default: - return tree; - } - } - static Name value2TypeName(Object value) { if (value instanceof Character) return Name.fromString("scala.Char"); else if (value instanceof Integer) return Name.fromString("scala.Int"); @@ -293,15 +283,19 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { * - final classes are only inherited by classes which are * nested within definition of base class, or that occur within same * statement sequence. + * - self-type of current class is a subtype of self-type of each parent class. */ - void validateParentClasses(Tree[] constrs, Type[] parents) { + void validateParentClasses(Tree[] constrs, Type[] parents, Type selfType) { if (parents.length == 0 || !checkClassType(constrs[0].pos, parents[0])) return; - for (int i = 1; i < parents.length; i++) { + for (int i = 0; i < parents.length; i++) { if (!checkClassType(constrs[i].pos, parents[i])) return; - Type[] grandparents = parents[i].parents(); - if (grandparents.length > 0 && !parents[0].isSubType(grandparents[0])) - error(constrs[i].pos, "illegal inheritance;\n " + parents[0] + - " does not conform to " + parents[i] + "'s supertype"); + if (1 <= i) { + Type[] grandparents = parents[i].parents(); + if (grandparents.length > 0 && + !parents[0].isSubType(grandparents[0])) + error(constrs[i].pos, "illegal inheritance;\n " + parents[0] + + " does not conform to " + parents[i] + "'s supertype"); + } Symbol bsym = parents[i].symbol(); if ((bsym.flags & FINAL) != 0) { // are we in same scope as base type definition? @@ -316,6 +310,11 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { } } } + if (!selfType.isSubType(parents[i].instanceType())) { + error(constrs[i].pos, "illegal inheritance;\n self-type " + + selfType + " does not conform to " + parents[i] + + "'s selftype " + parents[i].instanceType()); + } } } @@ -444,7 +443,7 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { try { return checkNoEscapeMap.apply(tp); } catch (Type.Error ex) { - error(pos, tp + "///" + ex.msg); + error(pos, ex.msg); return Type.ErrorType; } } @@ -496,6 +495,12 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { return error(tree, "stable identifier required"); } + /** Check that (abstract) type can be instantiated. + */ + void checkInstantiatable(int pos, Type tp) { + error(pos, tp.symbol() + " is abstract; cannot be instantiated"); + } + /** Check all members of class `clazz' for overriding conditions. */ void checkAllOverrides(Symbol clazz) { @@ -628,7 +633,7 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { if (clazz.isLocalClass()) unit.mangler.setMangledName(clazz); enterSym(tree, clazz.constructor()); - if ((mods & CASE) != 0) { + if ((mods & (ABSTRACTCLASS | CASE)) == CASE) { // enter case constructor method. enterInScope( new TermSymbol( @@ -652,10 +657,7 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { case TypeDef(int mods, Name name, _, _): int kind = (mods & (DEFERRED | PARAM)) != 0 ? TYPE : ALIAS; - TypeSymbol tsym = new TypeSymbol(kind, tree.pos, name, owner, mods); - if (kind == ALIAS) - tsym.constructor().setInfo(new LazyTreeType(tree)); - return enterSym(tree, tsym); + return enterSym(tree, new TypeSymbol(kind, tree.pos, name, owner, mods)); case Import(Tree expr, Name[] selectors): return enterImport(tree, @@ -700,7 +702,7 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { if (other.isPreloaded()) { // symbol was preloaded from package; // need to overwrite definition. - if (global.debug) System.out.println("overwriting " + other);//debug + if (global.debug) System.out.println(sym + " overwrites " + other);//debug sym.copyTo(other); if (sym.isModule()) { sym.moduleClass().copyTo( @@ -742,11 +744,11 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { /** Define symbol associated with `tree' using given `context'. */ - void defineSym(Tree tree, Unit unit, Infer infer, Context context) { + void defineSym(Tree tree, Unit unit, Infer infer, Context curcontext) { Unit savedUnit = this.unit; this.unit = unit; Context savedContext = this.context; - this.context = context; + this.context = curcontext; int savedMode = this.mode; this.mode = EXPRmode; Type savedPt = this.pt; @@ -756,7 +758,7 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { if (global.debug) System.out.println("defining " + sym);//debug Type owntype; switch (tree) { - case ClassDef(int mods, Name name, Tree.TypeDef[] tparams, Tree.ValDef[][] vparams, _, Tree.Template templ): + case ClassDef(int mods, Name name, Tree.TypeDef[] tparams, Tree.ValDef[][] vparams, Tree tpe, Tree.Template templ): assert (mods & LOCKED) == 0 || sym.isAnonymousClass(): sym; // to catch repeated evaluations ((ClassDef) tree).mods |= LOCKED; @@ -766,6 +768,10 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { pushContext(tree, sym.constructor(), new Scope(context.scope)); Symbol[] tparamSyms = enterParams(tparams); Symbol[][] vparamSyms = enterParams(vparams); + for (int i = 0; i < vparamSyms.length; i++) + for (int j = 0; j < vparamSyms[i].length; j++) + context.scope.unlink( + context.scope.lookupEntry(vparamSyms[i][j].name)); Type constrtype = makeMethodType( tparamSyms, vparamSyms, @@ -773,7 +779,10 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { sym.constructor().setInfo(constrtype); // necessary so that we can access tparams sym.constructor().flags |= INITIALIZED; + if (tpe != Tree.Empty) + sym.setTypeOfThis(transform(tpe, TYPEmode).type); + reenterParams(vparams); defineTemplate(templ, sym); owntype = templ.type; popContext(); @@ -812,31 +821,31 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { case DefDef(int mods, Name name, Tree.TypeDef[] tparams, Tree.ValDef[][] vparams, Tree tpe, Tree rhs): pushContext(tree, sym, new Scope(context.scope)); Symbol[] tparamSyms = enterParams(tparams); + Type restpe = null; + if (tpe != Tree.Empty) { + restpe = transform(tpe, TYPEmode).type; + } Symbol[][] vparamSyms = enterParams(vparams); - Type restpe; if (tpe == Tree.Empty) { int rhsmode = name.isConstrName() ? CONSTRmode : EXPRmode; ((DefDef) tree).rhs = rhs = transform(rhs, rhsmode); restpe = rhs.type.widen(); - } else { - restpe = transform(tpe, TYPEmode).type; } popContext(); owntype = makeMethodType(tparamSyms, vparamSyms, restpe); break; case TypeDef(int mods, Name name, Tree.TypeDef[] tparams, Tree rhs): + //todo: alwyas have context.owner as owner. if (sym.kind == TYPE) { pushContext(rhs, context.owner, context.scope); - this.context.delayArgs = true; + context.delayArgs = true; owntype = transform(rhs, TYPEmode).type; owntype.symbol().initialize();//to detect cycles popContext(); } else { // sym.kind == ALIAS pushContext(tree, sym, new Scope(context.scope)); - Symbol[] tparamSyms = enterParams(tparams); - sym.constructor().setInfo(Type.PolyType(tparamSyms, Type.NoType)); - owntype = transform(rhs, TYPEmode).type; + owntype = transform(rhs, TYPEmode | FUNmode).type; popContext(); } break; @@ -921,8 +930,9 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { /** Re-enter type parameters in current scope. */ void reenterParams(Tree[] params) { - for (int i = 0; i < params.length; i++) + for (int i = 0; i < params.length; i++) { context.scope.enter(params[i].symbol()); + } } /** Re-enter value parameters in current scope. @@ -1014,7 +1024,7 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { } sym = sym1; sym.flags |= (ACCESSED | SELECTOR); - Tree qual = checkStable(deepCopy(lastimports.importPrefix())); + Tree qual = checkStable(duplicator.transform(lastimports.importPrefix())); pre = qual.type; //new TextTreePrinter().print(name + " => ").print(lastimports.tree).print("." + name).println().end();//DEBUG tree = make.Select(tree.pos, qual, name); @@ -1048,7 +1058,7 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { } else { sym.flags |= (ACCESSED | SELECTOR); Type symtype = qual.type.memberType(sym); - //System.out.println(sym.name + ":" + symtype);//debug + //System.out.println(sym.name + ":" + symtype);//DEBUG if (uninst.length != 0) { switch (symtype) { case PolyType(Symbol[] tparams, Type restype): @@ -1156,7 +1166,8 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { Tree[] parents1 = transformConstrInvocations( templ.pos, templ.parents, false, Type.AnyType); if (owner.kind != ERROR) { - validateParentClasses(templ.parents, owner.info().parents()); + validateParentClasses( + templ.parents, owner.info().parents(), owner.typeOfThis()); validateBaseTypes(owner); } pushContext(templ, owner, owner.members()); @@ -1358,12 +1369,12 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { * Insert `apply' function if needed. */ Tree transform(Tree tree, int mode, Type pt) { - //new TextTreePrinter().print("transforming ").print(tree).println().end();//DEBUG int savedMode = this.mode; Type savedPt = this.pt; this.mode = mode; this.pt = pt; Tree tree1 = adapt(transform(tree), mode, pt); + this.mode = savedMode; this.pt = savedPt; return tree1; @@ -1562,11 +1573,16 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { case ClassDef(int mods, Name name, Tree.TypeDef[] tparams, Tree.ValDef[][] vparams, Tree tpe, Tree.Template templ): pushContext(tree, sym.constructor(), new Scope(context.scope)); reenterParams(tparams); - reenterParams(vparams); Tree.TypeDef[] tparams1 = transform(tparams); - Tree.ValDef[][] vparams1 = transform(vparams); Tree tpe1 = transform(tpe); + reenterParams(vparams); + Tree.ValDef[][] vparams1 = transform(vparams); Tree.Template templ1 = transformTemplate(templ, sym); + if ((sym.flags & ABSTRACTCLASS) == 0 && + !sym.type().isSubType(sym.typeOfThis())) + error(sym.pos, sym + + " needs to be abstract; it does not conform to its self-type " + + sym.typeOfThis()); popContext(); return copy.ClassDef(tree, mods, name, tparams1, vparams1, tpe1, templ1) .setType(definitions.UNIT_TYPE); @@ -1592,10 +1608,10 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { case DefDef(int mods, Name name, Tree.TypeDef[] tparams, Tree.ValDef[][] vparams, Tree tpe, Tree rhs): pushContext(tree, sym, new Scope(context.scope)); reenterParams(tparams); - reenterParams(vparams); Tree.TypeDef[] tparams1 = transform(tparams); - Tree.ValDef[][] vparams1 = transform(vparams); Tree tpe1 = transform(tpe, TYPEmode); + reenterParams(vparams); + Tree.ValDef[][] vparams1 = transform(vparams); Tree rhs1 = rhs; if (tpe1 == Tree.Empty) { tpe1 = gen.mkType(rhs1.pos, rhs1.type.widen()); @@ -1612,7 +1628,9 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { pushContext(tree, sym, new Scope(context.scope)); reenterParams(tparams); Tree.TypeDef[] tparams1 = transform(tparams); - Tree rhs1 = transform(rhs, TYPEmode); + int mode = TYPEmode; + if (sym.kind == ALIAS) mode |= FUNmode; + Tree rhs1 = transform(rhs, mode); popContext(); return copy.TypeDef(tree, mods, name, tparams1, rhs1) .setType(definitions.UNIT_TYPE); @@ -1642,6 +1660,12 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { .setType(tp); case Visitor(Tree.CaseDef[] cases): + if (infer.isFullyDefined(pt)) { + Type pt1 = pt.baseType(definitions.PARTIALFUNCTION_CLASS); + if (pt1.symbol() == definitions.PARTIALFUNCTION_CLASS) + return transform( + desugarize.partialFunction(tree, pt1.typeArgs())); + } return transform(desugarize.Visitor(tree)); case Assign(Apply(Tree funarray, Tree[] vparam), Tree rhs): @@ -1685,13 +1709,10 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { copy.Template(templ, new Tree[]{parent1}, body) .setType(parent1.type).setSymbol(Symbol.NONE); Type owntype = parent1.type; - if ((owntype.symbol().constructor().flags & - ABSTRACTCLASS) != 0) { - error(tree.pos, owntype.symbol() + - " is abstract; cannot be instantiated"); - } + if ((owntype.symbol().constructor().flags & ABSTRACTCLASS) != 0) + checkInstantiatable(tree.pos, owntype); return copy.New(tree, templ1) - .setType(owntype); + .setType(owntype.instanceType()); } else { pushContext(tree, context.owner, new Scope(context.scope)); Tree cd = make.ClassDef( @@ -1718,7 +1739,9 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { while (it.hasNext()) { Symbol sym1 = it.next(); Symbol basesym1 = base.lookupNonPrivate(sym1.name); - if (basesym1.kind != NONE && !basesym1.info().isSameAs(sym1.info())) + if (basesym1.kind != NONE && + !base.symbol().thisType().memberType(basesym1) + .isSameAs(sym1.type())) refinement.enter(sym1); } if (refinement.elems == Scope.Entry.NONE && @@ -1806,14 +1829,15 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { Symbol fsym = TreeInfo.methSymbol(tree1); if ((mode & (EXPRmode | FUNmode)) == EXPRmode && fsym != null && (fsym.flags & CASE) != 0) { - Symbol constr = fsym.type().resultType().symbol().constructor(); + Symbol constr = fsym.owner().info() + .lookup(fsym.name.toTypeName()).constructor(); Template templ = make.Template( tree1.pos, new Tree[]{desugarize.toConstructor(tree1, constr)}, Tree.EMPTY_ARRAY); templ.setSymbol(Symbol.NONE).setType(tree1.type); return adapt( - make.New(tree1.pos, templ).setType(tree1.type), mode, pt); + make.New(tree1.pos, templ).setType(tree1.type.instanceType()), mode, pt); } else { return tree1; } @@ -1919,8 +1943,7 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { Tree tpe1 = transform(tpe, TYPEmode | FUNmode); Tree[] args1 = transform(args, TYPEmode); Type[] argtypes = Tree.typeOf(args); - Symbol clazz = tpe1.type.unalias().symbol(); - Symbol[] tparams = clazz.typeParams(); + Symbol[] tparams = tpe1.type.typeParams(); if (tpe1.type != Type.ErrorType) { if (tparams.length != args.length) { if (tparams.length == 0) @@ -1968,7 +1991,8 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { } } } - return error(tree, ex.msg); + throw ex;//debug + //return error(tree, ex.msg); } } @@ -2005,6 +2029,7 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { this.c = context; } public void complete(Symbol sym) { + //System.out.println("completing " + sym);//debug //if (sym.isConstructor()) sym.constructorClass().initialize(); //else if (sym.isModule()) sym.moduleClass().initialize(); defineSym(tree, u, i, c); @@ -2019,7 +2044,7 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { super(tree); } public void complete(Symbol sym) { - sym.setInfo(tree.symbol().constructor().type()); + sym.setInfo(tree.symbol().constructor().type().instanceType()); } } } |