summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sources/scalac/symtab/Type.java57
-rw-r--r--sources/scalac/transformer/LambdaLift.java37
-rw-r--r--sources/scalac/transformer/UnCurry.java4
-rw-r--r--sources/scalac/typechecker/Analyzer.java318
-rw-r--r--sources/scalac/util/Names.java1
-rw-r--r--test/files/neg/S2.scala19
-rw-r--r--test/files/neg/S4.scala11
-rw-r--r--test/files/neg/S6.scala12
-rw-r--r--test/files/neg/S7.scala7
-rw-r--r--test/files/neg/vincent.scala21
-rw-r--r--test/files/neg/vincent1.scala17
-rw-r--r--test/files/pos/S1.scala13
-rw-r--r--test/files/pos/S3.scala14
-rw-r--r--test/files/pos/S5.scala30
-rw-r--r--test/files/pos/S8.scala19
-rw-r--r--test/files/pos/philippe3.scala40
-rw-r--r--test/files/pos/scall.bat50
-rw-r--r--test/neg/S2.scala19
-rw-r--r--test/neg/S4.scala11
-rw-r--r--test/neg/S6.scala12
-rw-r--r--test/neg/S7.scala7
-rw-r--r--test/neg/vincent.scala21
-rw-r--r--test/neg/vincent1.scala17
-rw-r--r--test/pos/S1.scala13
-rw-r--r--test/pos/S3.scala14
-rw-r--r--test/pos/S5.scala30
-rw-r--r--test/pos/S8.scala19
-rw-r--r--test/pos/philippe3.scala40
-rw-r--r--test/pos/scall.bat50
29 files changed, 760 insertions, 163 deletions
diff --git a/sources/scalac/symtab/Type.java b/sources/scalac/symtab/Type.java
index a11f8bea8f..0f5a7ac6d4 100644
--- a/sources/scalac/symtab/Type.java
+++ b/sources/scalac/symtab/Type.java
@@ -80,7 +80,11 @@ public class Type implements Modifiers, Kinds, TypeTags {
public static final Type[] NO_ARRAY = new Type[0];
public static SingleType singleType(Type pre, Symbol sym) {
- return new ExtSingleType(pre, sym);
+ if (pre.isStable() || pre == ErrorType)
+ return new ExtSingleType(pre, sym);
+ else
+ throw new Type.Error(
+ "malformed type: " + pre + "." + sym.nameString() + ".type");
}
public static TypeRef appliedType(Type tycon, Type[] args) {
@@ -116,6 +120,16 @@ public class Type implements Modifiers, Kinds, TypeTags {
return res;
}
+ public static Type typeRef(Type pre, Symbol sym, Type[] args) {
+ if (pre.isStable() || pre == ErrorType)
+ return TypeRef(pre, sym, args);
+ else if (sym.kind == ALIAS)
+ return pre.memberInfo(sym);
+ else // todo: handle Java-style inner classes
+ throw new Type.Error(
+ "malformed type: " + pre + "." + sym.nameString());
+ }
+
static class ExtSingleType extends SingleType {
Type tp = null;
int definedId = -1;
@@ -569,12 +583,12 @@ public class Type implements Modifiers, Kinds, TypeTags {
case ThisType(_):
return tp;
case TypeRef(Type pre, Symbol sym, Type[] args):
- Type pre1 = map(pre);
+ Type pre1 = apply(pre);
Type[] args1 = map(args);
if (pre1 == pre && args1 == args) return tp;
else return TypeRef(pre1, sym, args1);
case SingleType(Type pre, Symbol sym):
- Type pre1 = map(pre);
+ Type pre1 = apply(pre);
if (pre1 == pre) return tp;
else return singleType(pre1, sym);
case CompoundType(Type[] parts, Scope members):
@@ -720,10 +734,11 @@ public class Type implements Modifiers, Kinds, TypeTags {
return pre.memberInfo(sym).baseType(clazz);
else if (clazz.isCompoundSym())
return NoType;
- else
+ else {
return sym.baseType(clazz)
.asSeenFrom(pre, clazz.owner())
.subst(sym.typeParams(), args);
+ }
case CompoundType(Type[] parts, _):
for (int i = parts.length - 1; i >= 0; i--) {
@@ -764,7 +779,15 @@ public class Type implements Modifiers, Kinds, TypeTags {
this.pre = pre; this.clazz = clazz;
}
+ public Type apply0(Type t) {
+ Type t1 = apply0(t);
+ System.out.println(t + " as seen from (" + pre + "," + clazz + ") = " + t1);//debug
+ return t1;
+ }
+
public Type apply(Type t) {
+ if (pre == NoType || clazz.kind != CLASS)
+ return t;
switch (t) {
case ThisType(Symbol sym):
return t.toPrefix(pre, clazz);
@@ -786,7 +809,8 @@ public class Type implements Modifiers, Kinds, TypeTags {
}
return t1;
} else {
- Type prefix1 = prefix.toPrefix(pre, clazz);
+ //Type prefix1 = prefix.toPrefix(pre, clazz);
+ Type prefix1 = apply(prefix);
Symbol sym1 = (prefix1 == prefix || (sym.flags & MODUL) != 0)
? sym : prefix1.rebind(sym);
boolean prevTypeArg = typeArg;
@@ -799,7 +823,8 @@ public class Type implements Modifiers, Kinds, TypeTags {
case SingleType(Type prefix, Symbol sym):
try {
- Type prefix1 = prefix.toPrefix(pre, clazz);
+ //Type prefix1 = prefix.toPrefix(pre, clazz);
+ Type prefix1 = apply(prefix);
if (prefix1 == prefix) return t;
else return singleType(prefix1, prefix1.rebind(sym));
} catch (Type.Error ex) {
@@ -849,17 +874,10 @@ public class Type implements Modifiers, Kinds, TypeTags {
Type toPrefix(Type pre, Symbol clazz) {
if (pre == NoType || clazz.kind != CLASS)
return this;
- if (symbol().isSubClass(clazz) &&
- pre.symbol().isSubClass(symbol())) {
- if (!pre.isStable() && pre != ErrorType) {
- throw new Type.Error (
- "malformed type: " + pre + "." + symbol().nameString());
- }
+ else if (symbol().isSubClass(clazz) && pre.symbol().isSubClass(symbol()))
return pre;
- } else {
- return toPrefix(
- pre.baseType(clazz).prefix(), clazz.owner());
- }
+ else
+ return toPrefix(pre.baseType(clazz).prefix(), clazz.owner());
}
/** This type Types as seen from prefix `pre' and class `clazz'. This means:
@@ -897,10 +915,9 @@ public class Type implements Modifiers, Kinds, TypeTags {
}
private Type memberTransform(Symbol sym, Type tp) {
- Type tp1 = tp.asSeenFrom(narrow(), sym.owner());
- Type tp2 = tp1.asSeenFrom(this, widen().symbol());
- //if (Global.instance.debug) System.out.println(this + "/" + widen() + ".memberType(" + sym + ":" + tp + ") = " + tp1 + "/" + tp2);//DEBUG
- return tp2;
+ Type tp1 = tp.asSeenFrom(this, sym.owner());
+ //if (Global.instance.debug) System.out.println(this + ".memberType(" + sym + ":" + tp + ") = " + tp1);//debug
+ return tp1;
}
// Substitutions ---------------------------------------------------------------
diff --git a/sources/scalac/transformer/LambdaLift.java b/sources/scalac/transformer/LambdaLift.java
index 608db61eae..48f1edf66a 100644
--- a/sources/scalac/transformer/LambdaLift.java
+++ b/sources/scalac/transformer/LambdaLift.java
@@ -380,6 +380,11 @@ public class LambdaLift extends OwnerTransformer
}
return copy.ValDef(tree, mods, name1, tpe1, rhs1);
+ case Tuple(Tree[] args):
+ Tree tree1 = mkList(tree.pos, tree.type, transform(args));
+ //new scalac.ast.printer.TextTreePrinter().print("TUPLE: ").print(tree).print("\n ==> \n").print(tree1).println().end();//DEBUG
+ return tree1;
+
case Apply(Tree fn, Tree[] args):
Symbol fsym = TreeInfo.methSymbol(fn);
Tree fn1 = transform(fn);
@@ -535,4 +540,36 @@ public class LambdaLift extends OwnerTransformer
return args;
}
}
+
+ Tree mkList(int pos, Type tpe, Tree[] args) {
+ return mkList(pos, tpe.typeArgs()[0], args, 0);
+ }
+
+ Tree mkList(int pos, Type elemtpe, Tree[] args, int start) {
+ if (start == args.length) return mkNil(pos, elemtpe);
+ else return mkCons(pos, elemtpe, args[start],
+ mkList(pos, elemtpe, args, start + 1));
+ }
+
+ Tree mkNil(int pos, Type elemtpe) {
+ return gen.New(
+ gen.Apply(
+ gen.TypeApply(
+ gen.mkRef(
+ pos,
+ global.definitions.getClass(Names.scala_Nil).constructor()),
+ new Tree[]{gen.mkType(pos, elemtpe)}),
+ new Tree[]{}));
+ }
+
+ Tree mkCons(int pos, Type elemtpe, Tree hd, Tree tl) {
+ return gen.New(
+ gen.Apply(
+ gen.TypeApply(
+ gen.mkRef(
+ pos,
+ global.definitions.getClass(Names.scala_COLONCOLON).constructor()),
+ new Tree[]{gen.mkType(pos, elemtpe)}),
+ new Tree[]{hd, tl}));
+ }
}
diff --git a/sources/scalac/transformer/UnCurry.java b/sources/scalac/transformer/UnCurry.java
index 9647b43852..427c7a0efd 100644
--- a/sources/scalac/transformer/UnCurry.java
+++ b/sources/scalac/transformer/UnCurry.java
@@ -146,10 +146,10 @@ public class UnCurry extends OwnerTransformer
private Tree[] transformArgs(int pos, Tree[] args, Type methtype) {
switch (methtype) {
case MethodType(Symbol[] params, _):
+ Tree[] args0 = args;//debug
if (params.length == 1 && (params[0].flags & REPEATED) != 0) {
assert (args.length != 1 || !(args[0] instanceof Tree.Tuple));
- args = new Tree[]{
- make.Tuple(pos, args).setType(params[0].type())};
+ args = new Tree[]{make.Tuple(pos, args).setType(params[0].type())};
}
Tree[] args1 = args;
for (int i = 0; i < args.length; i++) {
diff --git a/sources/scalac/typechecker/Analyzer.java b/sources/scalac/typechecker/Analyzer.java
index 1a37745586..fe6a0b13d5 100644
--- a/sources/scalac/typechecker/Analyzer.java
+++ b/sources/scalac/typechecker/Analyzer.java
@@ -182,6 +182,24 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
error(pos, infer.typeErrorMsg("type mismatch", found, req) + explanation);
}
+ void reportTypeError(int pos, Type.Error ex) {
+ if (ex instanceof CyclicReference) {
+ if (global.debug) ex.printStackTrace();//DEBUG
+ CyclicReference cyc = (CyclicReference) ex;
+ if (cyc.info instanceof LazyTreeType) {
+ switch (((LazyTreeType) cyc.info).tree) {
+ case ValDef(_, _, _, _):
+ error(pos, "recursive " + cyc.sym + " needs type");
+ break;
+ case DefDef(_, _, _, _, _, _):
+ error(pos, "recursive function " + cyc.sym.name + " needs result type");
+ }
+ }
+ }
+ //throw ex;//DEBUG
+ error(pos, ex.msg);
+ }
+
// Name resolution -----------------------------------------------------------
String decode(Name name) {
@@ -281,6 +299,7 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
* 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.
+ * - parent types do not refer to value parameters of class.
*/
void validateParentClasses(Tree[] constrs, Type[] parents, Type selfType) {
if (parents.length == 0 || !checkClassType(constrs[0].pos, parents[0])) return;
@@ -434,7 +453,28 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
}
}
- /** Check that
+ /** Check that type `tp' is not a subtype of itself.
+ */
+ public void checkNonCyclic(int pos, Type tp) {
+ switch (tp) {
+ case TypeRef(Type pre, Symbol sym, Type[] args):
+ sym.initialize();
+ if ((sym.flags & LOCKED) != 0) {
+ error(pos, "cyclic aliasing or subtyping involving " + sym);
+ } else if (sym.kind == ALIAS || sym.kind == TYPE) {
+ assert (sym.flags & LOCKED) == 0;
+ sym.flags |= LOCKED;
+ checkNonCyclic(
+ pos, pre.memberInfo(sym).subst(sym.typeParams(), args));
+ sym.flags &= ~LOCKED;
+ }
+ break;
+ case CompoundType(Type[] parents, Scope members):
+ for (int i = 0; i < parents.length; i++) {
+ checkNonCyclic(pos, parents[i]);
+ }
+ }
+ }
/** Check that type does not refer to components defined in current scope.
*/
@@ -451,25 +491,23 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
public Type apply(Type t) {
switch (t.unalias()) {
case TypeRef(ThisType(_), Symbol sym, Type[] args):
- Scope.Entry e = context.scope.lookupEntry(sym.name);
- if (e.sym == sym && e.owner == context.scope) {
- throw new Type.Error(
- "type " + t + " escapes its defining scope");
- } else {
- map(args);
- return t;
- }
+ checkNoEscape(t, sym);
+ break;
case SingleType(ThisType(_), Symbol sym):
- Scope.Entry e = context.scope.lookupEntry(sym.name);
- if (e.sym == sym && e.owner == context.scope) {
- return apply(t.widen());
- } else {
- return t;
- }
- default:
- return map(t);
+ checkNoEscape(t, sym);
+ break;
+ }
+ return map(t);
+ }
+ private void checkNoEscape(Type t, Symbol sym) {
+ Scope.Entry e = context.scope.lookupEntry(sym.name);
+ if (e.sym == sym && e.owner == context.scope &&
+ !(e.sym.kind == TYPE && (e.sym.flags & PARAM) != 0)) {
+ throw new Type.Error(
+ "type " + t + " escapes its defining scope");
}
- }};
+ }
+ };
/** Check that tree represents a pure definition.
*/
@@ -755,122 +793,129 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
Type savedPt = this.pt;
this.pt = Type.AnyType;
- Symbol sym = tree.symbol();
- 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 tpe, Tree.Template templ):
- assert (mods & LOCKED) == 0 || sym.isAnonymousClass(): sym; // to catch repeated evaluations
- ((ClassDef) tree).mods |= LOCKED;
-
- pushContext(tree, sym.constructor(), new Scope(context.scope));
- Symbol[] tparamSyms = enterParams(tparams);
- Symbol[][] vparamSyms = enterParams(vparams);
-
- if ((mods & CASE) != 0 && vparams.length > 0)
- templ.body = desugarize.addCaseElements(templ.body, vparams[0]);
-
- 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,
- Type.TypeRef(sym.owner().thisType(), sym, Symbol.type(tparamSyms)));
- 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();
- break;
+ try {
+ Symbol sym = tree.symbol();
+ 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 tpe, Tree.Template templ):
+ if ((mods & LOCKED) != 0 && !sym.isAnonymousClass()) {
+ sym.setInfo(Type.ErrorType);
+ throw new CyclicReference(sym, Type.NoType);
+ }
- case ModuleDef(int mods, Name name, Tree tpe, Tree.Template templ):
- Symbol clazz = sym.moduleClass();
- defineTemplate(templ, clazz);
- clazz.setInfo(templ.type);
- if (tpe == Tree.Empty) owntype = clazz.type();
- else owntype = transform(tpe, TYPEmode).type;
- break;
+ ((ClassDef) tree).mods |= LOCKED;
- case ValDef(int mods, Name name, Tree tpe, Tree rhs):
- if (tpe == Tree.Empty) {
- pushContext(tree, sym, context.scope);
- if (rhs == Tree.Empty) {
- 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());
- } else {
- error(tree.pos, "missing parameter type");
- ((ValDef) tree).tpe = tpe =
- gen.mkType(tree.pos, Type.ErrorType);
- }
- owntype = tpe.type;
- } else {
- if ((mods & CASE) != 0) {
- //rhs was already attributed
+ pushContext(tree, sym.constructor(), new Scope(context.scope));
+ Symbol[] tparamSyms = enterParams(tparams);
+ Symbol[][] vparamSyms = enterParams(vparams);
+
+ if ((mods & CASE) != 0 && vparams.length > 0)
+ templ.body = desugarize.addCaseElements(templ.body, vparams[0]);
+
+ Type constrtype = makeMethodType(
+ tparamSyms,
+ vparamSyms,
+ Type.TypeRef(sym.owner().thisType(), sym, Symbol.type(tparamSyms)));
+ sym.constructor().setInfo(constrtype);
+ // necessary so that we can access tparams
+ sym.constructor().flags |= INITIALIZED;
+
+ if (tpe != Tree.Empty)
+ sym.setTypeOfThis(
+ checkNoEscape(tpe.pos, transform(tpe, TYPEmode).type));
+
+ defineTemplate(templ, sym);
+ owntype = templ.type;
+ popContext();
+ break;
+
+ case ModuleDef(int mods, Name name, Tree tpe, Tree.Template templ):
+ Symbol clazz = sym.moduleClass();
+ defineTemplate(templ, clazz);
+ clazz.setInfo(templ.type);
+ if (tpe == Tree.Empty) owntype = clazz.type();
+ else owntype = transform(tpe, TYPEmode).type;
+ break;
+
+ case ValDef(int mods, Name name, Tree tpe, Tree rhs):
+ if (tpe == Tree.Empty) {
+ pushContext(tree, sym, context.scope);
+ if (rhs == Tree.Empty) {
+ 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());
+ } else {
+ error(tree.pos, "missing parameter type");
+ ((ValDef) tree).tpe = tpe =
+ gen.mkType(tree.pos, Type.ErrorType);
+ }
+ owntype = tpe.type;
} else {
- ((ValDef) tree).rhs = rhs = transform(rhs, EXPRmode);
+ if ((mods & CASE) != 0) {
+ //rhs was already attributed
+ } else {
+ ((ValDef) tree).rhs = rhs = transform(rhs, EXPRmode);
+ }
+ owntype = rhs.type;
}
- owntype = rhs.type;
+ popContext();
+ } else {
+ owntype = transform(tpe, TYPEmode).type;
}
- popContext();
- } else {
- owntype = transform(tpe, TYPEmode).type;
- }
- break;
-
- 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);
- if (tpe == Tree.Empty) {
- int rhsmode = name.isConstrName() ? CONSTRmode : EXPRmode;
- ((DefDef) tree).rhs = rhs = transform(rhs, rhsmode);
- restpe = rhs.type;
- }
- popContext();
- owntype = makeMethodType(tparamSyms, vparamSyms, restpe);
- break;
+ break;
- case TypeDef(int mods, Name name, Tree rhs):
- //todo: alwyas have context.owner as owner.
- if (sym.kind == TYPE) {
- pushContext(rhs, context.owner, context.scope);
- context.delayArgs = true;
- owntype = transform(rhs, TYPEmode).type;
- owntype.symbol().initialize();//to detect cycles
- popContext();
- } else { // sym.kind == ALIAS
+ case DefDef(int mods, Name name, Tree.TypeDef[] tparams, Tree.ValDef[][] vparams, Tree tpe, Tree rhs):
pushContext(tree, sym, new Scope(context.scope));
- owntype = transform(rhs, TYPEmode | FUNmode).type;
+ Symbol[] tparamSyms = enterParams(tparams);
+ Symbol[][] vparamSyms = enterParams(vparams);
+ Type restpe;
+ if (tpe == Tree.Empty) {
+ int rhsmode = name.isConstrName() ? CONSTRmode : EXPRmode;
+ ((DefDef) tree).rhs = rhs = transform(rhs, rhsmode);
+ restpe = checkNoEscape(rhs.pos, rhs.type);
+ } else {
+ restpe = checkNoEscape(
+ tpe.pos, transform(tpe, TYPEmode).type);
+ }
popContext();
- }
- break;
+ owntype = makeMethodType(tparamSyms, vparamSyms, restpe);
+ break;
- case Import(Tree expr, Name[] selectors):
- Tree expr1 = transform(expr, EXPRmode | QUALmode);
- ((Import) tree).expr = expr1;
- checkStable(expr1);
- owntype = expr1.type;
- break;
+ case TypeDef(int mods, Name name, Tree rhs):
+ //todo: alwyas have context.owner as owner.
+ if (sym.kind == TYPE) {
+ pushContext(rhs, context.owner, context.scope);
+ 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));
+ owntype = transform(rhs, TYPEmode | FUNmode).type;
+ popContext();
+ }
+ checkNonCyclic(tree.pos, owntype);
+ break;
- default:
- throw new ApplicationError();
+ case Import(Tree expr, Name[] selectors):
+ Tree expr1 = transform(expr, EXPRmode | QUALmode);
+ ((Import) tree).expr = expr1;
+ checkStable(expr1);
+ owntype = expr1.type;
+ break;
+
+ default:
+ throw new ApplicationError();
+ }
+ sym.setInfo(owntype);
+ validate(sym);
+ if (global.debug) System.out.println("defined " + sym);//debug
+ } catch (Type.Error ex) {
+ reportTypeError(tree.pos, ex);
}
- sym.setInfo(owntype);
- validate(sym);
- if (global.debug) System.out.println("defined " + sym);//debug
+
this.unit = savedUnit;
this.context = savedContext;
this.mode = savedMode;
@@ -1167,8 +1212,8 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
pushContext(constrs[i], context.owner, context.scope);
context.delayArgs = delayArgs;
constrs[i] = transform(constrs[i], CONSTRmode, pt);
- if (constrs[i].hasSymbol())
- constrs[i].symbol().initialize();//to detect cycles
+ Symbol c = TreeInfo.methSymbol(constrs[i]).primaryConstructorClass();
+ if (c.kind == CLASS) c.initialize();//to detect cycles
popContext();
}
return constrs;
@@ -1590,10 +1635,13 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
pushContext(tree, sym.constructor(), new Scope(context.scope));
reenterParams(tparams);
Tree.TypeDef[] tparams1 = transform(tparams);
- Tree tpe1 = transform(tpe);
reenterParams(vparams);
Tree.ValDef[][] vparams1 = transform(vparams);
+ Tree tpe1 = transform(tpe);
Tree.Template templ1 = transformTemplate(templ, sym);
+ for (int i = 0; i < templ1.parents.length; i++)
+ checkNoEscape(templ1.parents[i].pos, templ1.parents[i].type);
+
if ((sym.flags & ABSTRACTCLASS) == 0 &&
!sym.type().isSubType(sym.typeOfThis()))
error(sym.pos, sym +
@@ -1631,9 +1679,9 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
pushContext(tree, sym, new Scope(context.scope));
reenterParams(tparams);
Tree.TypeDef[] tparams1 = transform(tparams);
- Tree tpe1 = transform(tpe, TYPEmode);
reenterParams(vparams);
Tree.ValDef[][] vparams1 = transform(vparams);
+ Tree tpe1 = transform(tpe, TYPEmode);
Tree rhs1 = rhs;
if (tpe1 == Tree.Empty) {
tpe1 = gen.mkType(rhs1.pos, rhs1.type);
@@ -2018,20 +2066,8 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
throw new ApplicationError("illegal tree: " + tree);
}
} catch (Type.Error ex) {
- if (ex instanceof CyclicReference) {
- if (global.debug) ex.printStackTrace();//DEBUG
- CyclicReference cyc = (CyclicReference) ex;
- if (cyc.info instanceof LazyTreeType) {
- switch (((LazyTreeType) cyc.info).tree) {
- case ValDef(_, _, _, _):
- return error(tree, "recursive " + cyc.sym + " needs type");
- case DefDef(_, _, _, _, _, _):
- return error(tree, "recursive function " + cyc.sym.name + " needs result type");
- }
- }
- }
- throw ex;//debug
- //return error(tree, ex.msg);
+ reportTypeError(tree.pos, ex);
+ return tree;
}
}
diff --git a/sources/scalac/util/Names.java b/sources/scalac/util/Names.java
index c54f044f06..a70d6beedb 100644
--- a/sources/scalac/util/Names.java
+++ b/sources/scalac/util/Names.java
@@ -75,6 +75,7 @@ public class Names {
public static final Name predef = Name.fromString("predef");
public static final Name runtime = Name.fromString("runtime");
public static final Name scala = Name.fromString("scala");
+ public static final Name scala_COLONCOLON = Name.fromString("scala." + COLONCOLON);
public static final Name scala_Algebraic = Name.fromString("scala.Algebraic");
public static final Name scala_Any = Name.fromString("scala.Any");
public static final Name scala_AnyRef = Name.fromString("scala.AnyRef");
diff --git a/test/files/neg/S2.scala b/test/files/neg/S2.scala
new file mode 100644
index 0000000000..83cc1829a3
--- /dev/null
+++ b/test/files/neg/S2.scala
@@ -0,0 +1,19 @@
+/* I was wondering for a long time what types x and y have;
+** the compiler claims: z.Inner (see commented out line)
+** This is strange because z is not in scope.
+** Furthermore, compilation of this class yields the message: (why?)
+**
+** S2.scala:16: illegal cyclic reference involving value t
+** def t = foo(x, y);
+** ^
+*/
+module M {
+ def foo[T](x: T, y: T): T = x;
+ class S2() {
+ class Inner() extends S2() {}
+ def x = { val z = new S2(); new z.Inner(); }
+ def y = { val z = new S2(); new z.Inner(); }
+ def t = foo(x, y);
+ //def testType: Inner = x;
+ }
+}
diff --git a/test/files/neg/S4.scala b/test/files/neg/S4.scala
new file mode 100644
index 0000000000..4f7941082f
--- /dev/null
+++ b/test/files/neg/S4.scala
@@ -0,0 +1,11 @@
+/* This one compiles, but even if we would have dependent
+** constructor types, it would be not sound.
+*/
+class S4(a: Other) extends a.Inner() {
+ def foo(x: a.Inner) = x;
+ val b = new Other();
+ foo(new S4(b))
+}
+class Other() {
+ class Inner() {}
+}
diff --git a/test/files/neg/S6.scala b/test/files/neg/S6.scala
new file mode 100644
index 0000000000..dfe53d22bd
--- /dev/null
+++ b/test/files/neg/S6.scala
@@ -0,0 +1,12 @@
+/* This program puts the compiler into an endless loop
+*/
+trait T1 {
+ type T;
+}
+trait T2 {
+ type S;
+ type T <: S;
+}
+abstract class S6() extends T1 with T2 {
+ type S <: T;
+}
diff --git a/test/files/neg/S7.scala b/test/files/neg/S7.scala
new file mode 100644
index 0000000000..ecb801b9dc
--- /dev/null
+++ b/test/files/neg/S7.scala
@@ -0,0 +1,7 @@
+/* Another example for a non-terminating compiler run.
+*/
+class S7[T]() {
+ val a: S7[T] = this;
+ class A() extends a.C() {}
+ class C() extends a.A() {}
+}
diff --git a/test/files/neg/vincent.scala b/test/files/neg/vincent.scala
new file mode 100644
index 0000000000..0af526d6aa
--- /dev/null
+++ b/test/files/neg/vincent.scala
@@ -0,0 +1,21 @@
+module test {
+
+ trait A { type T; }
+
+ trait B { type T; }
+
+ /** def functor(x: A): B with { type T = x.T } */
+ abstract class functor() {
+ val arg: A;
+ val res: B with { type T = arg.T } =
+ new B with { type T = arg.T; };
+ }
+
+ val a = new A with { type T = String };
+ /** val b: B with { type T = String } = functor(a) */
+ val b: B with { type T = String } = {
+ val tmp = new functor() with { val arg = a };
+ tmp.res
+ }
+
+}
diff --git a/test/files/neg/vincent1.scala b/test/files/neg/vincent1.scala
new file mode 100644
index 0000000000..afcb9a94f4
--- /dev/null
+++ b/test/files/neg/vincent1.scala
@@ -0,0 +1,17 @@
+module test {
+
+ trait A { type T; }
+
+ trait B { type T; }
+
+ def functor(x: A): B with { type T = x.T } =
+ new B with {
+ type T = x.T;
+ };
+
+ val a = new A with { type T = String };
+ val b = functor(a);
+
+ val s: b.T = "coucou";
+
+}
diff --git a/test/files/pos/S1.scala b/test/files/pos/S1.scala
new file mode 100644
index 0000000000..eba81109b3
--- /dev/null
+++ b/test/files/pos/S1.scala
@@ -0,0 +1,13 @@
+/* This is probably no bug, I just don't understand why
+** type inference does not find the right instantiation of foo.
+** Currently it reports:
+**
+** S1.scala:12: inferred type arguments [S1] do not conform to
+** method foo's type parameter bounds [T <: S1.this.type]
+** foo(this);
+** ^
+*/
+class S1() {
+ def foo[T <: this.type](x: T) = x;
+ foo(this);
+}
diff --git a/test/files/pos/S3.scala b/test/files/pos/S3.scala
new file mode 100644
index 0000000000..1e0f0288b1
--- /dev/null
+++ b/test/files/pos/S3.scala
@@ -0,0 +1,14 @@
+/* Why does this code fail? b has type a.type, so the third
+** declaration in S3 should be okay... The compiler writes instead:
+**
+** found : S3.this.b.type (with underlying type S3)
+** required: S3.this.a.type
+** val c: a.type = b;
+** ^
+** Without declaration 3, everything is fine.
+*/
+class S3() {
+ val a = new S3();
+ val b: a.type = a;
+ val c: a.type = b;
+}
diff --git a/test/files/pos/S5.scala b/test/files/pos/S5.scala
new file mode 100644
index 0000000000..87325b47e4
--- /dev/null
+++ b/test/files/pos/S5.scala
@@ -0,0 +1,30 @@
+/* Here's a fragment of a Scala encoding for the Keris module system;
+** the compiler claims:
+**
+** S5.scala:28: value n in class N of type N.this._N.n
+** cannot override value n in class M of type M.this._N.n
+** val system = new M() with N() {}
+** ^
+** To me it seems like the code is perfectly fine...
+*/
+abstract class M() {
+ val _N: N;
+ val n: _N.n;
+ val _M: M = this;
+ val m: _M.m = new _M.m();
+ class m() {
+ // module body of M
+ }
+}
+abstract class N() {
+ val _N: N = this;
+ val n: _N.n = new _N.n();
+ val _M: M;
+ val m: _M.m;
+ class n() {
+ // module body of N
+ }
+}
+module O {
+ val system = new M() with N() {}
+}
diff --git a/test/files/pos/S8.scala b/test/files/pos/S8.scala
new file mode 100644
index 0000000000..e4339bb3f1
--- /dev/null
+++ b/test/files/pos/S8.scala
@@ -0,0 +1,19 @@
+/* I believe this code is correct, but the compiler rejects it:
+**
+** S8.scala:18: type mismatch;
+** found : M.x.A
+** required: M.x.a.B
+** val y: x.a.B = new x.A(); //correct?
+** ^
+** For a given value x of type S8, type x.A should be
+** a subtype of x.a.B.
+*/
+class S8() {
+ val a: S8 = this;
+ class A() extends a.B() {}
+ class B() {}
+}
+module M {
+ val x = new S8();
+ val y: x.a.B = new x.A(); //correct?
+}
diff --git a/test/files/pos/philippe3.scala b/test/files/pos/philippe3.scala
new file mode 100644
index 0000000000..d99ec41f52
--- /dev/null
+++ b/test/files/pos/philippe3.scala
@@ -0,0 +1,40 @@
+
+class Foo(x: Int) {}
+case class Bar(y: Int) extends Foo(y);
+
+
+trait T {}
+trait U {}
+class C() {}
+
+
+trait T1;
+trait T2 {}
+trait T5 extends T;
+trait T6 extends T {}
+trait T7 extends T with U;
+trait T8 extends T with U {}
+
+class C1();
+class C2() {}
+class C5() extends C();
+class C6() extends C() {}
+class C7() extends C() with U;
+class C8() extends C() with U {}
+
+case class D1();
+case class D2() {}
+case class D5() extends C();
+case class D6() extends C() {}
+case class D7() extends C() with U;
+case class D8() extends C() with U {}
+
+module M1;
+module M2 {}
+module M5 extends C();
+module M6 extends C() {}
+module M7 extends C() with U;
+module M8 extends C() with U {}
+
+
+
diff --git a/test/files/pos/scall.bat b/test/files/pos/scall.bat
new file mode 100644
index 0000000000..4e9f31425e
--- /dev/null
+++ b/test/files/pos/scall.bat
@@ -0,0 +1,50 @@
+scalac -prompt A.scala;
+scalac -prompt IntSet.scala;
+scalac -prompt List1.scala;
+scalac -prompt Rational.scala;
+scalac -prompt X.scala;
+scalac -prompt Y.scala;
+scalac -prompt Z.scala;
+scalac -prompt abstract.scala;
+scalac -prompt cls.scala;
+scalac -prompt cls1.scala;
+scalac -prompt clsrefine.scala;
+scalac -prompt cours1.scala;
+scalac -prompt cours2.scala;
+scalac -prompt cours2a.scala;
+scalac -prompt cours2b.scala;
+scalac -prompt cours2c.scala;
+scalac -prompt eta.scala;
+scalac -prompt exceptions.scala;
+scalac -prompt imports.scala;
+scalac -prompt lambda.scala;
+scalac -prompt lambdalift.scala;
+scalac -prompt lambdalift1.scala;
+scalac -prompt matthias1.scala;
+scalac -prompt maxim1.scala;
+scalac -prompt michel1.scala;
+scalac -prompt michel2.scala;
+scalac -prompt michel3.scala;
+scalac -prompt michel4.scala;
+scalac -prompt michel5.scala;
+scalac -prompt modules.scala;
+scalac -prompt modules1.scala;
+scalac -prompt moduletrans.scala;
+scalac -prompt nested.scala;
+scalac -prompt override.scala;
+scalac -prompt patterns.scala;
+scalac -prompt patterns2.scala;
+scalac -prompt philippe1.scala;
+scalac -prompt philippe2.scala;
+scalac -prompt reftest.scala;
+scalac -prompt sort1.scala;
+scalac -prompt sqrt.scala;
+scalac -prompt stable.scala;
+scalac -prompt strings.scala;
+scalac -prompt test1.scala;
+scalac -prompt test2.scala;
+scalac -prompt test4.scala;
+scalac -prompt test4a.scala;
+scalac -prompt test4refine.scala;
+scalac -prompt test5.scala;
+scalac -prompt test5refine.scala;
diff --git a/test/neg/S2.scala b/test/neg/S2.scala
new file mode 100644
index 0000000000..83cc1829a3
--- /dev/null
+++ b/test/neg/S2.scala
@@ -0,0 +1,19 @@
+/* I was wondering for a long time what types x and y have;
+** the compiler claims: z.Inner (see commented out line)
+** This is strange because z is not in scope.
+** Furthermore, compilation of this class yields the message: (why?)
+**
+** S2.scala:16: illegal cyclic reference involving value t
+** def t = foo(x, y);
+** ^
+*/
+module M {
+ def foo[T](x: T, y: T): T = x;
+ class S2() {
+ class Inner() extends S2() {}
+ def x = { val z = new S2(); new z.Inner(); }
+ def y = { val z = new S2(); new z.Inner(); }
+ def t = foo(x, y);
+ //def testType: Inner = x;
+ }
+}
diff --git a/test/neg/S4.scala b/test/neg/S4.scala
new file mode 100644
index 0000000000..4f7941082f
--- /dev/null
+++ b/test/neg/S4.scala
@@ -0,0 +1,11 @@
+/* This one compiles, but even if we would have dependent
+** constructor types, it would be not sound.
+*/
+class S4(a: Other) extends a.Inner() {
+ def foo(x: a.Inner) = x;
+ val b = new Other();
+ foo(new S4(b))
+}
+class Other() {
+ class Inner() {}
+}
diff --git a/test/neg/S6.scala b/test/neg/S6.scala
new file mode 100644
index 0000000000..dfe53d22bd
--- /dev/null
+++ b/test/neg/S6.scala
@@ -0,0 +1,12 @@
+/* This program puts the compiler into an endless loop
+*/
+trait T1 {
+ type T;
+}
+trait T2 {
+ type S;
+ type T <: S;
+}
+abstract class S6() extends T1 with T2 {
+ type S <: T;
+}
diff --git a/test/neg/S7.scala b/test/neg/S7.scala
new file mode 100644
index 0000000000..ecb801b9dc
--- /dev/null
+++ b/test/neg/S7.scala
@@ -0,0 +1,7 @@
+/* Another example for a non-terminating compiler run.
+*/
+class S7[T]() {
+ val a: S7[T] = this;
+ class A() extends a.C() {}
+ class C() extends a.A() {}
+}
diff --git a/test/neg/vincent.scala b/test/neg/vincent.scala
new file mode 100644
index 0000000000..0af526d6aa
--- /dev/null
+++ b/test/neg/vincent.scala
@@ -0,0 +1,21 @@
+module test {
+
+ trait A { type T; }
+
+ trait B { type T; }
+
+ /** def functor(x: A): B with { type T = x.T } */
+ abstract class functor() {
+ val arg: A;
+ val res: B with { type T = arg.T } =
+ new B with { type T = arg.T; };
+ }
+
+ val a = new A with { type T = String };
+ /** val b: B with { type T = String } = functor(a) */
+ val b: B with { type T = String } = {
+ val tmp = new functor() with { val arg = a };
+ tmp.res
+ }
+
+}
diff --git a/test/neg/vincent1.scala b/test/neg/vincent1.scala
new file mode 100644
index 0000000000..afcb9a94f4
--- /dev/null
+++ b/test/neg/vincent1.scala
@@ -0,0 +1,17 @@
+module test {
+
+ trait A { type T; }
+
+ trait B { type T; }
+
+ def functor(x: A): B with { type T = x.T } =
+ new B with {
+ type T = x.T;
+ };
+
+ val a = new A with { type T = String };
+ val b = functor(a);
+
+ val s: b.T = "coucou";
+
+}
diff --git a/test/pos/S1.scala b/test/pos/S1.scala
new file mode 100644
index 0000000000..eba81109b3
--- /dev/null
+++ b/test/pos/S1.scala
@@ -0,0 +1,13 @@
+/* This is probably no bug, I just don't understand why
+** type inference does not find the right instantiation of foo.
+** Currently it reports:
+**
+** S1.scala:12: inferred type arguments [S1] do not conform to
+** method foo's type parameter bounds [T <: S1.this.type]
+** foo(this);
+** ^
+*/
+class S1() {
+ def foo[T <: this.type](x: T) = x;
+ foo(this);
+}
diff --git a/test/pos/S3.scala b/test/pos/S3.scala
new file mode 100644
index 0000000000..1e0f0288b1
--- /dev/null
+++ b/test/pos/S3.scala
@@ -0,0 +1,14 @@
+/* Why does this code fail? b has type a.type, so the third
+** declaration in S3 should be okay... The compiler writes instead:
+**
+** found : S3.this.b.type (with underlying type S3)
+** required: S3.this.a.type
+** val c: a.type = b;
+** ^
+** Without declaration 3, everything is fine.
+*/
+class S3() {
+ val a = new S3();
+ val b: a.type = a;
+ val c: a.type = b;
+}
diff --git a/test/pos/S5.scala b/test/pos/S5.scala
new file mode 100644
index 0000000000..87325b47e4
--- /dev/null
+++ b/test/pos/S5.scala
@@ -0,0 +1,30 @@
+/* Here's a fragment of a Scala encoding for the Keris module system;
+** the compiler claims:
+**
+** S5.scala:28: value n in class N of type N.this._N.n
+** cannot override value n in class M of type M.this._N.n
+** val system = new M() with N() {}
+** ^
+** To me it seems like the code is perfectly fine...
+*/
+abstract class M() {
+ val _N: N;
+ val n: _N.n;
+ val _M: M = this;
+ val m: _M.m = new _M.m();
+ class m() {
+ // module body of M
+ }
+}
+abstract class N() {
+ val _N: N = this;
+ val n: _N.n = new _N.n();
+ val _M: M;
+ val m: _M.m;
+ class n() {
+ // module body of N
+ }
+}
+module O {
+ val system = new M() with N() {}
+}
diff --git a/test/pos/S8.scala b/test/pos/S8.scala
new file mode 100644
index 0000000000..e4339bb3f1
--- /dev/null
+++ b/test/pos/S8.scala
@@ -0,0 +1,19 @@
+/* I believe this code is correct, but the compiler rejects it:
+**
+** S8.scala:18: type mismatch;
+** found : M.x.A
+** required: M.x.a.B
+** val y: x.a.B = new x.A(); //correct?
+** ^
+** For a given value x of type S8, type x.A should be
+** a subtype of x.a.B.
+*/
+class S8() {
+ val a: S8 = this;
+ class A() extends a.B() {}
+ class B() {}
+}
+module M {
+ val x = new S8();
+ val y: x.a.B = new x.A(); //correct?
+}
diff --git a/test/pos/philippe3.scala b/test/pos/philippe3.scala
new file mode 100644
index 0000000000..d99ec41f52
--- /dev/null
+++ b/test/pos/philippe3.scala
@@ -0,0 +1,40 @@
+
+class Foo(x: Int) {}
+case class Bar(y: Int) extends Foo(y);
+
+
+trait T {}
+trait U {}
+class C() {}
+
+
+trait T1;
+trait T2 {}
+trait T5 extends T;
+trait T6 extends T {}
+trait T7 extends T with U;
+trait T8 extends T with U {}
+
+class C1();
+class C2() {}
+class C5() extends C();
+class C6() extends C() {}
+class C7() extends C() with U;
+class C8() extends C() with U {}
+
+case class D1();
+case class D2() {}
+case class D5() extends C();
+case class D6() extends C() {}
+case class D7() extends C() with U;
+case class D8() extends C() with U {}
+
+module M1;
+module M2 {}
+module M5 extends C();
+module M6 extends C() {}
+module M7 extends C() with U;
+module M8 extends C() with U {}
+
+
+
diff --git a/test/pos/scall.bat b/test/pos/scall.bat
new file mode 100644
index 0000000000..4e9f31425e
--- /dev/null
+++ b/test/pos/scall.bat
@@ -0,0 +1,50 @@
+scalac -prompt A.scala;
+scalac -prompt IntSet.scala;
+scalac -prompt List1.scala;
+scalac -prompt Rational.scala;
+scalac -prompt X.scala;
+scalac -prompt Y.scala;
+scalac -prompt Z.scala;
+scalac -prompt abstract.scala;
+scalac -prompt cls.scala;
+scalac -prompt cls1.scala;
+scalac -prompt clsrefine.scala;
+scalac -prompt cours1.scala;
+scalac -prompt cours2.scala;
+scalac -prompt cours2a.scala;
+scalac -prompt cours2b.scala;
+scalac -prompt cours2c.scala;
+scalac -prompt eta.scala;
+scalac -prompt exceptions.scala;
+scalac -prompt imports.scala;
+scalac -prompt lambda.scala;
+scalac -prompt lambdalift.scala;
+scalac -prompt lambdalift1.scala;
+scalac -prompt matthias1.scala;
+scalac -prompt maxim1.scala;
+scalac -prompt michel1.scala;
+scalac -prompt michel2.scala;
+scalac -prompt michel3.scala;
+scalac -prompt michel4.scala;
+scalac -prompt michel5.scala;
+scalac -prompt modules.scala;
+scalac -prompt modules1.scala;
+scalac -prompt moduletrans.scala;
+scalac -prompt nested.scala;
+scalac -prompt override.scala;
+scalac -prompt patterns.scala;
+scalac -prompt patterns2.scala;
+scalac -prompt philippe1.scala;
+scalac -prompt philippe2.scala;
+scalac -prompt reftest.scala;
+scalac -prompt sort1.scala;
+scalac -prompt sqrt.scala;
+scalac -prompt stable.scala;
+scalac -prompt strings.scala;
+scalac -prompt test1.scala;
+scalac -prompt test2.scala;
+scalac -prompt test4.scala;
+scalac -prompt test4a.scala;
+scalac -prompt test4refine.scala;
+scalac -prompt test5.scala;
+scalac -prompt test5refine.scala;