diff options
Diffstat (limited to 'sources/scalac/typechecker/Analyzer.java')
-rw-r--r-- | sources/scalac/typechecker/Analyzer.java | 158 |
1 files changed, 102 insertions, 56 deletions
diff --git a/sources/scalac/typechecker/Analyzer.java b/sources/scalac/typechecker/Analyzer.java index da24b2ea86..ee545ac7d3 100644 --- a/sources/scalac/typechecker/Analyzer.java +++ b/sources/scalac/typechecker/Analyzer.java @@ -85,7 +85,7 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { if (sym.pos == Position.NOPOS) { sym.setInfo(Type.ErrorType); String kind; - if (sym.name.isTermName()) kind = "module or method "; + if (sym.name.isTermName()) kind = "object or method "; else if (sym.name.isTypeName()) kind = "class "; else kind = "constructor "; throw new Type.Error("file " + unit.source + " does not define public " + @@ -213,7 +213,7 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { String decode(Name name) { if (name.isTypeName()) return "type " + name; else if (name.isConstrName()) return "constructor " + name; - else return name.toString(); + else return "value " + name.toString(); } /** Is `sym' accessible as a member of tree `site' in current context? @@ -318,6 +318,8 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { if ((bsym.flags & INTERFACE) != 0) error(constrs[0].pos, "superclass may not be a Java interface"); } else { + if ((bsym.flags & (JAVA | INTERFACE)) == JAVA) + error(constrs[i].pos, "Java class may not be used as mixin"); Type[] grandparents = parents[i].parents(); if (grandparents.length > 0 && !parents[0].isSubType(grandparents[0])) @@ -421,17 +423,6 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { } } - /** Check that found type conforms to required one. - */ - Type checkType(int pos, Type found, Type required) { - if (found.isSubType(required)) return found; - else { - typeError(pos, found, required); - explainTypes(found, required); - return Type.ErrorType; - } - } - /** Check that type is eta-expandable (i.e. no `def' parameters) */ void checkEtaExpandable(int pos, Type tp) { @@ -545,14 +536,21 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { Tree checkStable(Tree tree) { if (TreeInfo.isPureExpr(tree) || tree.type == Type.ErrorType) return tree; //new TextTreePrinter().print(tree).end();//DEBUG - //System.out.println(" " + tree.type);//DEBUG + //System.out.println(" " + tree.symbol() + ":" + tree.type);//DEBUG return error(tree.pos, "stable identifier required"); } - /** Check that (abstract) type can be instantiated. + /** Check that class can be instantiated. */ void checkInstantiatable(int pos, Type tp) { - error(pos, tp.symbol() + " is abstract; cannot be instantiated"); + Symbol clazz = tp.symbol(); + if (clazz.kind == CLASS) { + if ((clazz.flags & ABSTRACTCLASS) != 0) + error(pos, clazz + " is abstract, so it cannot be instantiated"); + else if (!tp.isSubType(tp.instanceType())) + error(pos, tp + " does not conform to its self-type " + + tp.instanceType() + ", so it cannot be instantiated"); + } } /** Check all members of class `clazz' for overriding conditions. @@ -851,9 +849,9 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { // Definining Symbols ------------------------------------------------------- - /** Define symbol associated with `tree' using given `context'. + /** Define symbol associated with `tree' using given `unit' and `context'. */ - void defineSym(Tree tree, Unit unit, Infer infer, Context curcontext) { + void defineSym(Tree tree, Unit unit, Context curcontext) { Unit savedUnit = this.unit; this.unit = unit; Context savedContext = this.context; @@ -878,6 +876,8 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { pushContext(tree, sym.constructor(), new Scope(context.scope)); Symbol[] tparamSyms = enterParams(tparams); Symbol[][] vparamSyms = enterParams(vparams); + if (vparamSyms.length == 0) + vparamSyms = new Symbol[][]{Symbol.EMPTY_ARRAY}; if ((mods & CASE) != 0 && vparams.length > 0) templ.body = desugarize.addCaseElements(templ.body, vparams[0]); @@ -891,7 +891,7 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { sym.constructor().flags |= INITIALIZED; if (tpe != Tree.Empty) - sym.setTypeOfThis(transform(tpe, TYPEmode).type); + sym.setTypeOfThis(new LazySelfType(tpe)); defineTemplate(templ, sym); owntype = templ.type; @@ -1001,7 +1001,7 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { void defineTemplate(Tree.Template templ, Symbol clazz) { // attribute parent constructors Tree[] constrs = transformConstrInvocations( - templ.pos, templ.parents, true, Type.AnyType); + templ.pos, templ.parents, true); Type[] parents = new Type[constrs.length]; for (int i = 0; i < parents.length; i++) @@ -1068,6 +1068,21 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { reenterParams(vparams[i]); } + /** Define self type of class or module `sym' + * associated with `tree' using given `unit' and `context'. + */ + void defineSelfType(Symbol sym, Tree tree, Unit unit, Context curcontext) { + Unit savedUnit = this.unit; + this.unit = unit; + Context savedContext = this.context; + this.context = curcontext; + + sym.setInfo(transform(tree, TYPEmode).type); + + this.unit = savedUnit; + this.context= savedContext; + } + // Attribution and Transform ------------------------------------------------- /** Attribute an identifier consisting of a simple name or an outer reference. @@ -1284,12 +1299,11 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { /** Attribute a sequence of constructor invocations. */ - Tree[] transformConstrInvocations(int pos, Tree[] constrs, - boolean delayArgs, Type pt) { + Tree[] transformConstrInvocations(int pos, Tree[] constrs, boolean delayArgs) { for (int i = 0; i < constrs.length; i++) { pushContext(constrs[i], context.owner, context.scope); context.delayArgs = delayArgs; - constrs[i] = transform(constrs[i], CONSTRmode, pt); + constrs[i] = transform(constrs[i], CONSTRmode, Type.AnyType); Symbol f = TreeInfo.methSymbol(constrs[i]); if (f != null) { Symbol c = f.primaryConstructorClass(); @@ -1306,7 +1320,7 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { if (global.debug) global.log("transforming " + owner);//debug //System.out.println(owner.info());//DEBUG Tree[] parents1 = transformConstrInvocations( - templ.pos, templ.parents, false, Type.AnyType); + templ.pos, templ.parents, false); if (owner.kind != ERROR) { validateParentClasses( templ.parents, owner.info().parents(), owner.typeOfThis()); @@ -1636,7 +1650,7 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { " does not conform to sequence " + clazz); } } else if (tree.type != Type.ErrorType) { - error(tree.pos, tree.symbol() + + error(tree.pos, tree.type.symbol() + " is neither a case class constructor nor a sequence class constructor"); } } @@ -1648,20 +1662,26 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { // check that other idents or selects are stable. switch (tree) { case Ident(Name name): - if (sym != null && isNullaryMethod(sym) && (sym.flags & CASE) != 0) { - ((Ident)tree).name = name.toTypeName(); - return transform(tree, mode, pt); - } else { + if (sym != null && isNullaryMethod(sym) && (sym.flags & CASE) != 0) + return transform( + make.Apply( + tree.pos, + copy.Ident(tree, name.toTypeName()), + Tree.EMPTY_ARRAY), + mode, pt); + else checkStable(tree); - } break; - case Select(_, Name selector): - if (sym != null && isNullaryMethod(sym) && (sym.flags & CASE) != 0) { - ((Select)tree).selector = selector.toTypeName(); - return transform(tree, mode, pt); - } else { + case Select(Tree qual, Name name): + if (sym != null && isNullaryMethod(sym) && (sym.flags & CASE) != 0) + return transform( + make.Apply( + tree.pos, + copy.Select(tree, qual, name.toTypeName()), + Tree.EMPTY_ARRAY), + mode, pt); + else checkStable(tree); - } } } } else if ((mode & EXPRmode) != 0) { @@ -1700,9 +1720,14 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { } } - if (!(tree.type instanceof Type.PolyType)) - tree.type = checkType(tree.pos, tree.type, pt); - + Type owntype = tree.type; + if ((mode & (CONSTRmode | FUNmode)) == (CONSTRmode)) + owntype = owntype.instanceType(); + if (!(owntype instanceof Type.PolyType || owntype.isSubType(pt))) { + typeError(tree.pos, owntype, pt); + explainTypes(owntype, pt); + tree.type = Type.ErrorType; + } return tree; } //where @@ -1757,6 +1782,8 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { Symbol sym = tree1.symbol(); if ((mode & FUNmode) == 0 && sym != null && sym.typeParams().length != 0) return error(tree.pos, sym + " takes type parameters."); +// else if (tree1.isType()) +// return gen.mkType(tree1.pos, tree1.type); else return tree1; } @@ -1807,12 +1834,6 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { Tree.ValDef[][] vparams1 = transform(vparams); Tree tpe1 = transform(tpe); 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); @@ -1954,8 +1975,7 @@ 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) - checkInstantiatable(tree.pos, owntype); + checkInstantiatable(tree.pos, owntype); return copy.New(tree, templ1) .setType(owntype.instanceType()); } else { @@ -2078,7 +2098,7 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { switch (enclClazz.info()) { case CompoundType(Type[] parents, _): return copy.Super(tree, tpe1) - .setType(Type.compoundType(parents, Scope.EMPTY)); + .setType(Type.compoundType(parents, Scope.EMPTY).symbol().thisType()); case ErrorType: return tree.setType(Type.ErrorType); default: @@ -2086,7 +2106,7 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { } } else { return error(tree.pos, - "super can be used only in a class, module, or template"); + "super can be used only in a class, object, or template"); } case This(Tree qual): @@ -2099,16 +2119,16 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { } else { return error( tree.pos, tree + - " can be used only in a class, module, or template"); + " can be used only in a class, object, or template"); } } else { Tree qual1 = transform(qual, TYPEmode | FUNmode); - clazz = qual1.symbol(); + clazz = qual1.type.symbol(); if (clazz.kind == CLASS) { Context clazzContext = context.outerContext(clazz); if (clazzContext != Context.NONE) { if (!(qual1 instanceof Tree.Ident)) - qual1 = gen.Ident(tree.pos, qual1.symbol()); + qual1 = gen.Ident(tree.pos, clazz); tree1 = copy.This(tree, qual1); } else { return error(qual.pos, @@ -2245,20 +2265,18 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { class LazyTreeType extends Type.LazyType { Tree tree; Unit u; - Infer i; Context c; LazyTreeType(Tree tree) { this.tree = tree; this.u = unit; - this.i = infer; 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); + defineSym(tree, u, c); } } @@ -2270,7 +2288,35 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { super(tree); } public void complete(Symbol sym) { - sym.setInfo(tree.symbol().constructor().type().instanceType()); + Type constrtype = tree.symbol().constructor().type().instanceType(); + switch (tree) { + case ClassDef(_, _, _, ValDef[][] vparams, _, _): + if (vparams.length == 0) { + constrtype = removeMethod(constrtype); + } + } + sym.setInfo(constrtype); + } + private Type removeMethod(Type tp) { + switch (tp) { + case MethodType(_, Type restp): + return restp; + case PolyType(Symbol[] tparams, Type restp): + return Type.PolyType(tparams, removeMethod(restp)); + default: + return tp; + } + } + } + + /** A lazy type for self types + */ + class LazySelfType extends LazyTreeType { + LazySelfType(Tree tree) { + super(tree); + } + public void complete(Symbol sym) { + defineSelfType(sym, tree, u, c); } } } |