summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sources/scalac/ast/TreeGen.java21
-rw-r--r--sources/scalac/symtab/Symbol.java5
-rw-r--r--sources/scalac/symtab/Type.java19
-rw-r--r--sources/scalac/transformer/ExplicitOuterClasses.java6
-rw-r--r--sources/scalac/transformer/PatternMatcher.java6
-rw-r--r--sources/scalac/transformer/matching/PatternMatcher.java6
-rw-r--r--sources/scalac/typechecker/Analyzer.java50
-rw-r--r--test/files/pos/List1.scala4
-rw-r--r--test/pos/List1.scala4
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);
}