From 1956c530070b9ad3c75991ac90c2969081483c41 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Tue, 4 Mar 2003 18:15:23 +0000 Subject: *** empty log message *** --- sources/scalac/ast/TreeGen.java | 21 ++++++--- sources/scalac/symtab/Symbol.java | 5 +++ sources/scalac/symtab/Type.java | 19 ++++++-- .../scalac/transformer/ExplicitOuterClasses.java | 6 +-- sources/scalac/transformer/PatternMatcher.java | 6 +-- .../transformer/matching/PatternMatcher.java | 6 +-- sources/scalac/typechecker/Analyzer.java | 50 ++++++++++++---------- test/files/pos/List1.scala | 4 +- test/pos/List1.scala | 4 +- 9 files changed, 78 insertions(+), 43 deletions(-) diff --git a/sources/scalac/ast/TreeGen.java b/sources/scalac/ast/TreeGen.java index 29bb0d6d8a..6853b924a5 100644 --- a/sources/scalac/ast/TreeGen.java +++ b/sources/scalac/ast/TreeGen.java @@ -63,6 +63,21 @@ public class TreeGen implements Kinds, Modifiers { .setInfo(Type.NoType); } + public Tree mkStable(Tree tree) { + Symbol sym = tree.symbol(); + if (sym.isStable()) { + switch (tree) { + case Ident(_): + tree.setType(Type.singleType(sym.owner().thisType(), sym)); + break; + case Select(Tree qual, _): + if (qual.type.isStable()) + tree.setType(Type.singleType(qual.type, sym)); + } + } + return tree; + } + public Tree mkRef(int pos, Type pre, Symbol sym) { if (pre.isSameAs(Type.localThisType) || pre.symbol().isRoot()) return Ident(pos, sym); @@ -81,7 +96,7 @@ public class TreeGen implements Kinds, Modifiers { case ThisType(Symbol sym): return make.This(pos, Ident(pos, sym)).setType(pre); case SingleType(Type pre1, Symbol sym): - return mkRef(pos, pre1, sym); + return mkStable(mkRef(pos, pre1, sym)); default: throw new ApplicationError(); } @@ -361,8 +376,6 @@ public class TreeGen implements Kinds, Modifiers { Global.instance.nextPhase(); Type symtype = qual.type.memberType(sym); Global.instance.prevPhase(); - if (sym.kind == VAL && qual.type.isStable() && symtype.isObjectType()) - symtype = Type.singleType(qual.type, sym); return make.Select(pos, qual, sym.name) .setSymbol(sym).setType(symtype); } @@ -383,8 +396,6 @@ public class TreeGen implements Kinds, Modifiers { Global.instance.nextPhase(); Type symtype = sym.type(); Global.instance.prevPhase(); - if (sym.kind == VAL && symtype.isObjectType()) - symtype = Type.singleType(sym.owner().thisType(), sym); return make.Ident(pos, sym.name) .setSymbol(sym).setType(symtype); } diff --git a/sources/scalac/symtab/Symbol.java b/sources/scalac/symtab/Symbol.java index 48e07b4021..4f78b26978 100644 --- a/sources/scalac/symtab/Symbol.java +++ b/sources/scalac/symtab/Symbol.java @@ -152,6 +152,11 @@ public abstract class Symbol implements Modifiers, Kinds { return kind == VAL && !(isModule() && isJava()) && !isPackage(); } + /** Does this symbol denote a stable value? */ + public final boolean isStable() { + return kind == VAL && (flags & MUTABLE) == 0 && type().isObjectType(); + } + /** Does this symbol denote a variable? */ public final boolean isVariable() { return kind == VAL && (flags & MUTABLE) != 0; diff --git a/sources/scalac/symtab/Type.java b/sources/scalac/symtab/Type.java index c239146f78..df4e0d51a2 100644 --- a/sources/scalac/symtab/Type.java +++ b/sources/scalac/symtab/Type.java @@ -417,7 +417,6 @@ public class Type implements Modifiers, Kinds, TypeTags { switch (unalias()) { case ThisType(_): case SingleType(_, _): - case ErrorType: return true; default: return false; @@ -861,7 +860,7 @@ public class Type implements Modifiers, Kinds, TypeTags { return this; if (symbol().isSubClass(clazz) && pre.symbol().isSubClass(symbol())) { - if (!pre.isStable()) { + if (!pre.isStable() && pre != ErrorType) { throw new Type.Error ( "malformed type: " + pre + "." + symbol().nameString()); } @@ -2097,7 +2096,7 @@ public class Type implements Modifiers, Kinds, TypeTags { if (!first) buf.append("}"); return buf.toString(); case MethodType(Symbol[] vparams, Type result): - return ArrayApply.toString(Symbol.type(vparams), "(", ",", ")") + result; + return ArrayApply.toString(paramTypeString(vparams), "(", ",", ")") + result; case PolyType(Symbol[] tparams, Type result): return ArrayApply.toString(Symbol.defString(tparams), "[", ",", "]") + result; @@ -2139,6 +2138,20 @@ public class Type implements Modifiers, Kinds, TypeTags { } } + private String[] paramTypeString(Symbol[] vparams) { + String[] ss = new String[vparams.length]; + for (int i = 0; i < ss.length; i++) { + Type tp = vparams[i].type(); + if ((vparams[i].flags & REPEATED) != 0 && + tp.symbol() == Global.instance.definitions.SEQ_CLASS && + tp.typeArgs().length == 1) + ss[i] = tp.typeArgs()[0].toString() + "*"; + else + ss[i] = tp.toString(); + } + return ss; + } + public int hashCode() { switch (this) { case ErrorType: diff --git a/sources/scalac/transformer/ExplicitOuterClasses.java b/sources/scalac/transformer/ExplicitOuterClasses.java index d83cefb2a3..43f3056d2a 100644 --- a/sources/scalac/transformer/ExplicitOuterClasses.java +++ b/sources/scalac/transformer/ExplicitOuterClasses.java @@ -121,9 +121,9 @@ public class ExplicitOuterClasses extends Transformer { Symbol outerSym = (Symbol)outerIt.next(); if (root == null) - root = gen.Ident(outerSym); + root = gen.mkStable(gen.Ident(outerSym)); else - root = gen.Select(root, outerSym); + root = gen.mkStable(gen.Select(root, outerSym)); --level; } @@ -172,7 +172,7 @@ public class ExplicitOuterClasses extends Transformer { if (found && level > 0) { Tree root = outerRef(level); - return gen.Select(root, sym); + return gen.mkStable(gen.Select(root, sym)); } else { return super.transform(tree); } diff --git a/sources/scalac/transformer/PatternMatcher.java b/sources/scalac/transformer/PatternMatcher.java index 44304292ed..b9137daf32 100644 --- a/sources/scalac/transformer/PatternMatcher.java +++ b/sources/scalac/transformer/PatternMatcher.java @@ -99,12 +99,12 @@ public class PatternMatcher { this.owner = owner; this.selector = selector; this.root = makeConstrPat(selector.pos, - selector.type.widen()); + selector.type); this.root.and = makeHeader(selector.pos, - selector.type.widen(), + selector.type, make.Ident(selector.pos, root.symbol().name) - .setType(selector.type.widen()) + .setType(selector.type) .setSymbol(root.symbol())); this.resultVar = new TermSymbol(selector.pos, RESULT_N, diff --git a/sources/scalac/transformer/matching/PatternMatcher.java b/sources/scalac/transformer/matching/PatternMatcher.java index 44304292ed..b9137daf32 100644 --- a/sources/scalac/transformer/matching/PatternMatcher.java +++ b/sources/scalac/transformer/matching/PatternMatcher.java @@ -99,12 +99,12 @@ public class PatternMatcher { this.owner = owner; this.selector = selector; this.root = makeConstrPat(selector.pos, - selector.type.widen()); + selector.type); this.root.and = makeHeader(selector.pos, - selector.type.widen(), + selector.type, make.Ident(selector.pos, root.symbol().name) - .setType(selector.type.widen()) + .setType(selector.type) .setSymbol(root.symbol())); this.resultVar = new TermSymbol(selector.pos, RESULT_N, diff --git a/sources/scalac/typechecker/Analyzer.java b/sources/scalac/typechecker/Analyzer.java index 68aef668de..e8e8daef27 100644 --- a/sources/scalac/typechecker/Analyzer.java +++ b/sources/scalac/typechecker/Analyzer.java @@ -545,6 +545,8 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { overrideError(pos, member, other, "cannot override final member"); } else if ((other.flags & DEFERRED) == 0 && ((member.flags & OVERRIDE) == 0)) { overrideError(pos, member, other, "needs `override' modifier"); + } else if ((other.flags & STABLE) != 0 && ((member.flags & STABLE) == 0)) { + overrideError(pos, member, other, "needs to be an immutable value"); } else { Type self = clazz.thisType(); switch (other.kind) { @@ -803,7 +805,7 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { if ((sym.owner().flags & ACCESSOR) != 0) { // this is the paremeter of a variable setter method. ((ValDef) tree).tpe = tpe = - gen.mkType(tree.pos, sym.owner().accessed().type().widen()); + gen.mkType(tree.pos, sym.owner().accessed().type()); } else { error(tree.pos, "missing parameter type"); ((ValDef) tree).tpe = tpe = @@ -812,7 +814,7 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { owntype = tpe.type; } else { ((ValDef) tree).rhs = rhs = transform(rhs, EXPRmode); - owntype = rhs.type.widen(); + owntype = rhs.type; } popContext(); } else { @@ -831,7 +833,7 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { if (tpe == Tree.Empty) { int rhsmode = name.isConstrName() ? CONSTRmode : EXPRmode; ((DefDef) tree).rhs = rhs = transform(rhs, rhsmode); - restpe = rhs.type.widen(); + restpe = rhs.type; } popContext(); owntype = makeMethodType(tparamSyms, vparamSyms, restpe); @@ -1026,13 +1028,14 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { } sym = sym1; sym.flags |= (ACCESSED | SELECTOR); - Tree qual = checkStable(duplicator.transform(lastimports.importPrefix())); + Tree qual = 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); } symtype = pre.memberType(sym); - if (sym.isTerm() && (sym.flags & MUTABLE) == 0 && symtype.isObjectType()) { + if ((pt != null && pt.isStable() || (mode & QUALmode) != 0) + && sym.isStable()) { //System.out.println("making single " + sym + ":" + symtype);//DEBUG symtype = Type.singleType(pre, sym); } @@ -1054,9 +1057,9 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { if (sym.kind == NONE) { //System.out.println(qual.type + " has members " + qual.type.members());//DEBUG return error(tree, - decode(name) + " is not a member of " + qual.type.widen()); + decode(name) + " is not a member of " + qual.type); } else if (!isAccessible(sym, qual)) { - return error(tree, sym + " cannot be accessed in " + qual.type.widen()); + return error(tree, sym + " cannot be accessed in " + qual.type); } else { sym.flags |= (ACCESSED | SELECTOR); Type symtype = qual.type.memberType(sym); @@ -1071,8 +1074,8 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { symtype = Type.PolyType(uninst, symtype); } } - if (sym.isTerm() && (sym.flags & MUTABLE) == 0 && symtype.isObjectType() && - qual.type.isStable()) + if ((pt != null && pt.isStable() || (mode & QUALmode) != 0) && + sym.isStable() && qual.type.isStable()) symtype = Type.singleType(qual.type, sym); //System.out.println(qual.type + ".member: " + sym + ":" + symtype);//DEBUG switch (tree) { @@ -1606,7 +1609,7 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { Tree tpe1 = transform(tpe, TYPEmode); Tree rhs1 = rhs; if (tpe1 == Tree.Empty) { - tpe1 = gen.mkType(rhs1.pos, rhs.type.widen()); + tpe1 = gen.mkType(rhs1.pos, rhs.type); // rhs already attributed by defineSym in this case } else if (rhs != Tree.Empty) { pushContext(tree, sym, context.scope); @@ -1625,7 +1628,7 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { Tree.ValDef[][] vparams1 = transform(vparams); Tree rhs1 = rhs; if (tpe1 == Tree.Empty) { - tpe1 = gen.mkType(rhs1.pos, rhs1.type.widen()); + tpe1 = gen.mkType(rhs1.pos, rhs1.type); // rhs already attributed by defineSym in this case } else if (rhs != Tree.Empty) { rhs1 = transform(rhs, EXPRmode, @@ -1786,7 +1789,7 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { Type restype = desugarize.preFunction(vparams, pt); enterParams(vparams); Tree body1 = transform(body, EXPRmode, restype); - if (!infer.isFullyDefined(restype)) restype = body1.type.widen(); + if (!infer.isFullyDefined(restype)) restype = body1.type; popContext(); Tree tree1 = copy.Function(tree, vparams, body1); Tree tree2 = transform(desugarize.Function(tree1, restype)); @@ -1871,14 +1874,15 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { } case This(Tree qual): + Symbol clazz; + Tree tree1; if (qual == Tree.Empty) { - Symbol clazz = context.enclClass.owner; + clazz = context.enclClass.owner; if (clazz != null) { // we are in a class or module - return make.This( + tree1 = make.This( tree.pos, make.Ident(tree.pos, clazz.name) - .setSymbol(clazz).setType(clazz.type())) - .setType(clazz.thisType()); + .setSymbol(clazz).setType(clazz.type())); } else { return error( tree, tree + @@ -1886,11 +1890,11 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { } } else { Tree qual1 = transform(qual, TYPEmode | FUNmode); - Symbol clazz = qual1.symbol(); + clazz = qual1.symbol(); if (clazz.kind == CLASS) { Context clazzContext = context.outerContext(clazz); if (clazzContext != Context.NONE) { - return tree.setType(clazz.thisType()); + tree1 = tree; } else { return error( qual, clazz.name + " is not an enclosing class"); @@ -1899,14 +1903,16 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { return error(qual, "class identifier expected"); } } + return tree1.setType( + (pt != null && pt.isStable() || (mode & QUALmode) != 0) + ? clazz.thisType() : clazz.type()); case Select(Tree qual, Name name): - Tree qual1 = transform(qual, EXPRmode | POLYmode | QUALmode); + int qualmode = EXPRmode | POLYmode | QUALmode; + Tree qual1 = transform(qual, qualmode); if (name.isTypeName()) qual1 = checkStable(qual1); return transformSelect( - tree, - adapt(qual1, EXPRmode | POLYmode | QUALmode, Type.AnyType), - name); + tree, adapt(qual1, qualmode, Type.AnyType), name); case Ident(Name name): if (mode == PATTERNmode && name.isVariable()) { diff --git a/test/files/pos/List1.scala b/test/files/pos/List1.scala index 0e2ad848c9..ea25a5c5d5 100644 --- a/test/files/pos/List1.scala +++ b/test/files/pos/List1.scala @@ -8,7 +8,7 @@ module lists { } def Nil[a] = new List[a] { - def isEmpty: True.type = True; + def isEmpty: Boolean = True; def head = error[a]("head of Nil"); def tail = error[List[a]]("tail of Nil"); } @@ -32,7 +32,7 @@ module lists { class IntList() extends List[Int] { def isEmpty: Boolean = False; def head: Int = 1; - def foo: List[Int] with { def isEmpty: True.type; def head: Int; def tail: List[Int] } = Nil[Int]; + def foo: List[Int] with { def isEmpty: Boolean; def head: Int; def tail: List[Int] } = Nil[Int]; def tail0: List[Int] = foo.prepend(1).prepend(1+1); def tail: List[Int] = Nil[Int].prepend(1).prepend(1+1); } diff --git a/test/pos/List1.scala b/test/pos/List1.scala index 0e2ad848c9..ea25a5c5d5 100644 --- a/test/pos/List1.scala +++ b/test/pos/List1.scala @@ -8,7 +8,7 @@ module lists { } def Nil[a] = new List[a] { - def isEmpty: True.type = True; + def isEmpty: Boolean = True; def head = error[a]("head of Nil"); def tail = error[List[a]]("tail of Nil"); } @@ -32,7 +32,7 @@ module lists { class IntList() extends List[Int] { def isEmpty: Boolean = False; def head: Int = 1; - def foo: List[Int] with { def isEmpty: True.type; def head: Int; def tail: List[Int] } = Nil[Int]; + def foo: List[Int] with { def isEmpty: Boolean; def head: Int; def tail: List[Int] } = Nil[Int]; def tail0: List[Int] = foo.prepend(1).prepend(1+1); def tail: List[Int] = Nil[Int].prepend(1).prepend(1+1); } -- cgit v1.2.3