summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sources/scala/xml/Generic.scala6
-rw-r--r--sources/scalac/ast/printer/TextTreePrinter.java14
-rw-r--r--sources/scalac/symtab/Scope.java12
-rw-r--r--sources/scalac/symtab/Symbol.java3
-rw-r--r--sources/scalac/symtab/Type.java84
-rw-r--r--sources/scalac/transformer/LambdaLift.java10
-rw-r--r--sources/scalac/typechecker/Analyzer.java26
-rw-r--r--sources/scalac/typechecker/Infer.java21
-rw-r--r--sources/scalac/typechecker/RefCheck.java60
-rw-r--r--test/files/neg/bug97.check2
-rw-r--r--test/neg/bug97.check2
11 files changed, 135 insertions, 105 deletions
diff --git a/sources/scala/xml/Generic.scala b/sources/scala/xml/Generic.scala
index bc760bcfef..fd2628aeb1 100644
--- a/sources/scala/xml/Generic.scala
+++ b/sources/scala/xml/Generic.scala
@@ -67,10 +67,10 @@ object Generic {
def save( filename:String, doc:Any ):Unit = {
import java.io.{FileOutputStream,Writer};
import java.nio.channels.{Channels,FileChannel};
- def toXML( xs: List[Any], fc:Writer ):Unit = xs match {
+ def toXMLList( xs: List[Any], fc:Writer ):Unit = xs match {
case _::ys =>
toXML( xs.head, fc );
- toXML( ys, fc );
+ toXMLList( ys, fc );
case _ => ()
}
def toXML( doc: Any, fc:Writer ):Unit = doc match {
@@ -82,7 +82,7 @@ object Generic {
fc.write( Generic.toXML(( doc.asInstanceOf[ Attribbed ])
.attribs ));
fc.write( ">" );
- toXML( xs, fc );
+ toXMLList( xs, fc );
fc.write( "</" );
fc.write( tag );
fc.write( ">" );
diff --git a/sources/scalac/ast/printer/TextTreePrinter.java b/sources/scalac/ast/printer/TextTreePrinter.java
index e4889b9bc2..53b48c8a41 100644
--- a/sources/scalac/ast/printer/TextTreePrinter.java
+++ b/sources/scalac/ast/printer/TextTreePrinter.java
@@ -313,13 +313,13 @@ public class TextTreePrinter implements TreePrinter {
printOpt(TXT_EQUAL, rhs, true);
break;
- case DefDef(int mods,
- Name name,
- Tree.AbsTypeDef[] tparams,
- Tree.ValDef[][] vparams,
- Tree tpe,
- Tree rhs):
- printModifiers(mods);
+ case DefDef(int mods,
+ Name name,
+ Tree.AbsTypeDef[] tparams,
+ Tree.ValDef[][] vparams,
+ Tree tpe,
+ Tree rhs):
+ printModifiers(mods);
print(KW_DEF);
print(Text.Space);
if (name.isTypeName()) print(KW_THIS);
diff --git a/sources/scalac/symtab/Scope.java b/sources/scalac/symtab/Scope.java
index d0a2bf5b9b..9a3125f21c 100644
--- a/sources/scalac/symtab/Scope.java
+++ b/sources/scalac/symtab/Scope.java
@@ -69,11 +69,11 @@ public class Scope {
/** the next entry in the hash bucket
*/
- Entry tail;
+ private Entry tail;
/** the next entry in this scope
*/
- public Entry next;
+ private Entry next;
/** The owner of the entry;
*/
@@ -109,7 +109,7 @@ public class Scope {
/** all elements of this scope
*/
- public Entry elems;
+ private Entry elems;
/** the hash table
*/
@@ -165,6 +165,12 @@ public class Scope {
return clone;
}
+ /** is the scope empty?
+ */
+ public boolean isEmpty() {
+ return elems == Entry.NONE;
+ }
+
/** the number of entries in this scope
*/
int size() {
diff --git a/sources/scalac/symtab/Symbol.java b/sources/scalac/symtab/Symbol.java
index 1abfa90ec8..8a583ccff9 100644
--- a/sources/scalac/symtab/Symbol.java
+++ b/sources/scalac/symtab/Symbol.java
@@ -1020,7 +1020,8 @@ public abstract class Symbol implements Modifiers, Kinds {
assert this.name == that.name : Debug.show(this) + " <> " + Debug.show(that);
assert this.owner == that.owner : Debug.show(this) + " != " + Debug.show(that);
assert this.isConstructor() == that.isConstructor();
- int overflags = this.flags & that.flags & (JAVA | ACCESSFLAGS);
+ int overflags = (this.flags & that.flags & (JAVA | ACCESSFLAGS)) |
+ ((this.flags | that.flags) & ACCESSOR);
TermSymbol overloaded = (this.isConstructor())
? TermSymbol.newConstructor(this.constructorClass(), overflags)
: new TermSymbol(pos, name, owner, overflags);
diff --git a/sources/scalac/symtab/Type.java b/sources/scalac/symtab/Type.java
index 5fa9d9e745..e94c7e87bc 100644
--- a/sources/scalac/symtab/Type.java
+++ b/sources/scalac/symtab/Type.java
@@ -199,8 +199,8 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags {
return tsym;
}
void validate() {//debug
- for (Scope.Entry e = members.elems; e != Scope.Entry.NONE; e = e.next)
- assert e.sym.owner() == tsym;
+ for (Scope.SymbolIterator it = members.iterator(true); it.hasNext(); )
+ assert it.next().owner() == tsym;
}
}
@@ -599,7 +599,7 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags {
return sym.fullName().startsWith(Names.scala_Function) &&
args.length > 0;
case CompoundType(Type[] parents, Scope members):
- return members.elems == Scope.Entry.NONE &&
+ return members.isEmpty() &&
parents.length == 2 &&
parents[0].symbol().fullName() == Names.scala_Object &&
parents[1].isFunctionType();
@@ -607,6 +607,21 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags {
return false;
}
+ /** Is this a polymorphic method type?
+ */
+ public boolean isPolymorphic() {
+ return typeParams().length > 0;
+ }
+
+ /** Is this a parameterized or polymorphic method type?
+ */
+ public boolean isParameterized() {
+ switch (this) {
+ case MethodType(_, _): return true;
+ default: return isPolymorphic();
+ }
+ }
+
// Members and Lookup -------------------------------------------------------
/** Get the scope containing the local members of this type.
@@ -1665,8 +1680,9 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags {
/** Does this type implement all symbols in scope `s' with same or stronger types?
*/
public boolean specializes(Scope s) {
- for (Scope.Entry e = s.elems; e != Scope.Entry.NONE; e = e.next)
- if (!specializes(e.sym)) return false;
+ for (Scope.SymbolIterator it = s.iterator(true); it.hasNext();) {
+ if (!specializes(it.next())) return false;
+ }
return true;
}
@@ -1689,6 +1705,20 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags {
public boolean specializes0(Symbol sym1) {
Symbol sym = lookup(sym1.name);
+ switch (sym.info()) {
+ case NoType:
+ return false;
+ case OverloadedType(Symbol[] alts, Type[] alttypes):
+ for (int i = 0; i < alts.length; i++) {
+ if (specializes0(alts[i], sym1)) return true;
+ }
+ return false;
+ default:
+ return specializes0(sym, sym1);
+ }
+ }
+
+ private boolean specializes0(Symbol sym, Symbol sym1) {
Type self = narrow();
Symbol[] tparams = symbol().typeParams();
Type[] targs = typeArgs();
@@ -1888,8 +1918,8 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags {
/** Does scope `s1' define all symbols of scope `s2' with the same kinds and infos?
*/
private boolean isSubScope(Scope s1, Scope s2) {
- for (Scope.Entry e = s2.elems; e != Scope.Entry.NONE; e = e.next) {
- Symbol sym2 = e.sym;
+ for (Scope.SymbolIterator it = s2.iterator(); it.hasNext(); ) {
+ Symbol sym2 = it.next();
Symbol sym1 = s1.lookup(sym2.name);
if (sym1.kind != sym2.kind ||
!sym1.info().isSameAs(
@@ -2166,17 +2196,17 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags {
Type[] rtps = new Type[tps.length];
Type[] rlbs = new Type[tps.length];
for (int i = 0; i < allBaseTypes.length; i++) {
- for (Scope.Entry e = allBaseTypes[i].members().elems;
- e != Scope.Entry.NONE;
- e = e.next) {
- Name name = e.sym.name;
- if ((e.sym.flags & PRIVATE) == 0 && lubType.lookup(name) == e.sym) {
- Type symType = memberTp(lubThisType, e.sym);
- Type symLoBound = lubThisType.memberLoBound(e.sym);
+ for (Scope.SymbolIterator it = allBaseTypes[i].members().iterator();
+ it.hasNext(); ) {
+ Symbol sym = it.next();
+ Name name = sym.name;
+ if ((sym.flags & PRIVATE) == 0 && lubType.lookup(name) == sym) {
+ Type symType = memberTp(lubThisType, sym);
+ Type symLoBound = lubThisType.memberLoBound(sym);
int j = 0;
while (j < tps.length) {
rsyms[j] = tps[j].lookupNonPrivate(name);
- if (rsyms[j] == e.sym) break;
+ if (rsyms[j] == sym) break;
if (rsyms[j].isMethod()) break; // since methods cannot
// appear in refinements.
rtps[j] = memberTp(tps[j], rsyms[j])
@@ -2190,7 +2220,7 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags {
if (j == tps.length) {
Symbol lubSym = lub(rsyms, rtps, rlbs, lubType.symbol());
if (lubSym.kind != NONE &&
- !(lubSym.kind == e.sym.kind &&
+ !(lubSym.kind == sym.kind &&
lubSym.info().isSameAs(symType) &&
lubSym.loBound().isSameAs(symType)))
members.enter(lubSym);
@@ -2199,7 +2229,7 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags {
}
}
//System.out.print("lub "); System.out.print(ArrayApply.toString(tps)); System.out.println(" = " + lubType);//DEBUG
- if (leastBaseTypes.length == 1 && members.elems == Scope.Entry.NONE)
+ if (leastBaseTypes.length == 1 && members.isEmpty())
return leastBaseTypes[0];
else return lubType;
}
@@ -2254,7 +2284,7 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags {
treftl = new Type.List(tps[i], treftl);
break;
case CompoundType(Type[] parents, Scope members):
- if (members.elems != Scope.Entry.NONE)
+ if (!members.isEmpty())
comptl = new Type.List(tps[i], comptl);
for (int j = 0; j < parents.length; j++)
treftl = new Type.List(parents[i], treftl);
@@ -2286,7 +2316,7 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags {
// eliminate redudant typerefs
Type[] treftypes = elimRedundant(treftl.toArrayReverse(), false);
- if (treftypes.length != 1 || glbType.members.elems != Scope.Entry.NONE) {
+ if (treftypes.length != 1 || !glbType.members.isEmpty()) {
// step 4: replace all abstract types by their lower bounds.
boolean hasAbstract = false;
for (int i = 0; i < treftypes.length; i++) {
@@ -2321,7 +2351,7 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags {
if (lb != NoType) return lb;
}
- if (treftypes.length == 1 && glbType.members.elems == Scope.Entry.NONE) {
+ if (treftypes.length == 1 && glbType.members.isEmpty()) {
return treftypes[0];
} else {
glbType.parts = treftypes;
@@ -2359,8 +2389,8 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags {
*/
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;
+ for (Scope.SymbolIterator it = ss[i].iterator(); it.hasNext(); )
+ if (!addMember(result, it.next(), glbThisType)) return false;
return true;
}
@@ -2634,16 +2664,6 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags {
return h;
}
- public static int hashCode(Scope.Entry elems) {
- int h = 0;
- for (Scope.Entry e = elems; e != Scope.Entry.NONE; e = e.next)
- h = h * 41
- + e.sym.kind
- + e.sym.name.hashCode()
- + e.sym.info().hashCode();
- return h;
- }
-
// todo: change in relation to needs.
public boolean equals(Object other) {
diff --git a/sources/scalac/transformer/LambdaLift.java b/sources/scalac/transformer/LambdaLift.java
index 67b396ec2e..9e3a497c80 100644
--- a/sources/scalac/transformer/LambdaLift.java
+++ b/sources/scalac/transformer/LambdaLift.java
@@ -444,9 +444,13 @@ public class LambdaLift extends OwnerTransformer
(sym.kind == TYPE || (sym.kind == VAL && !sym.isMethod()))) {
sym = descr.proxy(sym, currentOwner);
}
- Tree tree1 = copy.Ident(tree, sym).setType(
- sym.nextType());
- if (name != sym.name) ((Ident)tree1).name = sym.name;
+ Tree tree1 = (sym.owner().kind == CLASS)
+ ? gen.mkRef(tree.pos, sym)
+ : copy.Ident(tree, sym).setType(sym.nextType());
+ if (name != sym.name) {
+ if (tree1 instanceof Ident) ((Ident)tree1).name = sym.name;
+ else ((Select)tree1).selector = sym.name;
+ }
if ((sym.flags & CAPTURED) != 0) return gen.Select(tree1, Names.elem);
else return tree1;
diff --git a/sources/scalac/typechecker/Analyzer.java b/sources/scalac/typechecker/Analyzer.java
index 55da4c5f88..fc53218f5e 100644
--- a/sources/scalac/typechecker/Analyzer.java
+++ b/sources/scalac/typechecker/Analyzer.java
@@ -369,7 +369,8 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
if ((bsym.flags & FINAL) != 0) {
error(constrs[i].pos, "illegal inheritance from final class");
} else if (bsym.isSealed() ||
- bsym.isSubClass(definitions.ANYVAL_CLASS)) {
+ bsym.isSubClass(definitions.ANYVAL_CLASS) ||
+ bsym.isSubClass(definitions.ARRAY_CLASS)) {
// are we in same scope as base type definition?
Scope.Entry e = context.scope.lookupEntry(bsym.name);
if (e.sym != bsym || e.owner != context.scope) {
@@ -859,7 +860,10 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
}
context.scope.unlink(e);
context.scope.enter(sym);
- } else if (sym.kind == VAL && other.kind == VAL) {
+ } else if (context.owner.kind == CLASS &&
+ sym.kind == VAL && other.kind == VAL &&
+ ((sym.flags & ACCESSOR) == 0 ||
+ (other.flags & ACCESSOR) == 0)) {
// it's an overloaded definition
/*
if (((sym.flags ^ other.flags) & SOURCEFLAGS) != 0) {
@@ -873,9 +877,14 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
*/
e.setSymbol(other.overloadWith(sym));
} else {
- error(sym.pos,
- sym.nameString() + " is already defined as " +
- other + other.locationString());
+ if (context.owner.kind == CLASS)
+ error(sym.pos,
+ sym.nameString() + " is already defined as " +
+ other + other.locationString());
+ else
+ error(sym.pos,
+ sym.nameString() +
+ " is already defined in local scope");
}
} else {
context.scope.enter(sym);
@@ -2075,7 +2084,7 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
.isSameAs(sym1.type()))
refinement.enter(sym1);
}
- if (refinement.elems == Scope.Entry.NONE &&
+ if (refinement.isEmpty() &&
parentTypes.length == 1)
owntype = parentTypes[0];
else
@@ -2187,8 +2196,9 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
} else {
// it was an alias type
// todo: handle overloaded constructors
- fn1 = gen.TypeApply(
- fn1, gen.mkTypes(fn1.pos, argtypes));
+ if (argtypes.length != 0)
+ fn1 = gen.TypeApply(
+ fn1, gen.mkTypes(fn1.pos, argtypes));
if (tsym.typeParams().length != 0 &&
!(fn0 instanceof AppliedType))
fn1.type = Type.PolyType(
diff --git a/sources/scalac/typechecker/Infer.java b/sources/scalac/typechecker/Infer.java
index c14515f841..5dcf9bf0db 100644
--- a/sources/scalac/typechecker/Infer.java
+++ b/sources/scalac/typechecker/Infer.java
@@ -65,23 +65,6 @@ public class Infer implements Modifiers, Kinds {
(sym == null ? "expression" : sym) + " of type " + tp;
}
-// Helper definitions ---------------------------------------------------------
-
- /** Is type `tp' a polymorphic method type?
- */
- private boolean isPolymorphic(Type tp) {
- return tp.typeParams().length > 0;
- }
-
- /** Is type `tp' a parameterized method type?
- */
- boolean isParameterized(Type tp) {
- switch (tp) {
- case MethodType(_, _): return true;
- default: return isPolymorphic(tp);
- }
- }
-
// Tree Substitution -------------------------------------------------------------
static class Substituter extends Transformer {
@@ -954,8 +937,8 @@ public class Infer implements Modifiers, Kinds {
}
//where
private boolean improves(Type tp1, Type tp2) {
- return isParameterized(tp2) &&
- (!isParameterized(tp1) || specializes(tp1, tp2));
+ return tp2.isParameterized() &&
+ (!tp1.isParameterized() || specializes(tp1, tp2));
}
/** Assign `tree' the type of an alternative
diff --git a/sources/scalac/typechecker/RefCheck.java b/sources/scalac/typechecker/RefCheck.java
index 24c452cf70..d3a603642a 100644
--- a/sources/scalac/typechecker/RefCheck.java
+++ b/sources/scalac/typechecker/RefCheck.java
@@ -69,14 +69,14 @@ public class RefCheck extends Transformer implements Modifiers, Kinds {
for (Scope.SymbolIterator it = closure[i].members().iterator(true);
it.hasNext();) {
Symbol other = it.next();
- Symbol members = ((other.flags & PRIVATE) != 0) ? other
+ Symbol member = ((other.flags & PRIVATE) != 0) ? other
: clazz.info().lookup(other.name);
- Symbol member = Symbol.NONE;
- if (members.kind != NONE &&
- members.owner() != other.owner() &&
- (members.owner() == clazz ||
- !members.owner().isSubClass(other.owner())))
- member = checkOverride(pos, clazz, members, other);
+ if (member.owner() == other.owner())
+ member = other;
+ else if (member.type() instanceof Type.OverloadedType)
+ member = findOverriding(pos, clazz, member, other);
+ if (member.kind != NONE && member != other)
+ checkOverride(pos, clazz, member, other);
if (clazz.kind == CLASS && (clazz.flags & ABSTRACTCLASS) == 0) {
if ((member.flags & DEFERRED) != 0) {
abstractClassError(
@@ -116,21 +116,7 @@ public class RefCheck extends Transformer implements Modifiers, Kinds {
clazz.flags |= ABSTRACTCLASS;
}
- /** Check that all conditions for overriding `other' by `member' are met.
- * That is for overriding member M and overridden member O:
- *
- * 1. M must have the same or stronger access privileges as O.
- * 2. O must not be final.
- * 3. O is deferred, or M has `override' modifier.
- * 4. O is not a class, nor a class constructor.
- * 5. If O is a type alias, then M is an alias of O.
- * 6. If O is an abstract type then
- * either M is an abstract type, and M's bounds are sharper than O's bounds.
- * or M is a type alias or class which conforms to O's bounds.
- * 7. If O and M are values, then M's type is a subtype of O's type.
- * 8. If O is an immutable value, then so is M.
- */
- Symbol checkOverride(int pos, Symbol clazz, Symbol members, Symbol other) {
+ Symbol findOverriding(int pos, Symbol clazz, Symbol members, Symbol other) {
Type self = clazz.thisType();
Symbol member = members;
Type memberinfo = normalizedInfo(self, member);
@@ -153,10 +139,29 @@ public class RefCheck extends Transformer implements Modifiers, Kinds {
}
}
}
- if (member == members) {
- }
}
- if (member.owner() == clazz) pos = member.pos;
+ return member;
+ }
+
+ /** Check that all conditions for overriding `other' by `member' are met.
+ * That is for overriding member M and overridden member O:
+ *
+ * 1. M must have the same or stronger access privileges as O.
+ * 2. O must not be final.
+ * 3. O is deferred, or M has `override' modifier.
+ * 4. O is not a class, nor a class constructor.
+ * 5. If O is a type alias, then M is an alias of O.
+ * 6. If O is an abstract type then
+ * either M is an abstract type, and M's bounds are sharper than O's bounds.
+ * or M is a type alias or class which conforms to O's bounds.
+ * 7. If O and M are values, then M's type is a subtype of O's type.
+ * 8. If O is an immutable value, then so is M.
+ */
+ void checkOverride(int pos, Symbol clazz, Symbol member, Symbol other) {
+ if (member.owner() == clazz)
+ pos = member.pos;
+ else if (member.owner().isSubClass(other.owner()))
+ return; // everything was already checked elsewhere
if ((member.flags & PRIVATE) != 0) {
overrideError(pos, member, other, "has weaker access privileges; it should not be private");
@@ -177,6 +182,7 @@ public class RefCheck extends Transformer implements Modifiers, Kinds {
":\n both are inherited from mixin classes; " +
"\n an overriding definition in the current template is required");
} else {
+ Type self = clazz.thisType();
switch (other.kind) {
case CLASS:
overrideError(pos, member, other, "cannot override a class");
@@ -189,7 +195,8 @@ public class RefCheck extends Transformer implements Modifiers, Kinds {
if (other.isConstructor())
overrideError(pos, member, other,
"cannot override a class constructor");
- if (!memberinfo.isSubType(otherinfo))
+ if (!normalizedInfo(self, member).isSubType(
+ normalizedInfo(self, other)))
overrideTypeError(pos, member, other, self, false);
if (member.kind == TYPE &&
!self.memberLoBound(other).isSubType(
@@ -198,7 +205,6 @@ public class RefCheck extends Transformer implements Modifiers, Kinds {
}
}
- return member;
}
void overrideError(int pos, Symbol member, Symbol other, String msg) {
diff --git a/test/files/neg/bug97.check b/test/files/neg/bug97.check
index 5d4fcacb1b..cc620b3650 100644
--- a/test/files/neg/bug97.check
+++ b/test/files/neg/bug97.check
@@ -1,4 +1,4 @@
-test/neg/bug97.scala:3: expected pattern type scala.Any does not conform to sequence trait scala.List
+bug97.scala:3: expected pattern type scala.Any does not conform to sequence trait scala.List
case List(y) => "zero"
^
one error found
diff --git a/test/neg/bug97.check b/test/neg/bug97.check
index 5d4fcacb1b..cc620b3650 100644
--- a/test/neg/bug97.check
+++ b/test/neg/bug97.check
@@ -1,4 +1,4 @@
-test/neg/bug97.scala:3: expected pattern type scala.Any does not conform to sequence trait scala.List
+bug97.scala:3: expected pattern type scala.Any does not conform to sequence trait scala.List
case List(y) => "zero"
^
one error found