summaryrefslogtreecommitdiff
path: root/sources
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2004-04-06 17:57:30 +0000
committerMartin Odersky <odersky@gmail.com>2004-04-06 17:57:30 +0000
commit35f72d0a599e3aca2940e295052c0275c0a32533 (patch)
tree86c40542dc2a3412b4a0fcb76a71c1e1141522bf /sources
parent17c857d22ec405ec89e87e40206aecc2be84255d (diff)
downloadscala-35f72d0a599e3aca2940e295052c0275c0a32533.tar.gz
scala-35f72d0a599e3aca2940e295052c0275c0a32533.tar.bz2
scala-35f72d0a599e3aca2940e295052c0275c0a32533.zip
*** empty log message ***
Diffstat (limited to 'sources')
-rw-r--r--sources/scala/tools/scalac/ast/parser/Parser.scala16
-rw-r--r--sources/scala/tools/scalac/ast/printer/TextTreePrinter.scala12
-rw-r--r--sources/scala/tools/scalac/typechecker/Analyzer.scala63
-rw-r--r--sources/scala/tools/scalac/typechecker/DeSugarize.scala7
-rw-r--r--sources/scala/tools/scalac/typechecker/Infer.scala151
-rw-r--r--sources/scalac/ast/TreeGen.java2
-rw-r--r--sources/scalac/symtab/ClosureHistory.java2
-rw-r--r--sources/scalac/symtab/Symbol.java31
-rw-r--r--sources/scalac/symtab/Type.java63
-rw-r--r--sources/scalac/symtab/classfile/Pickle.java14
-rw-r--r--sources/scalac/symtab/classfile/UnPickle.java7
-rw-r--r--sources/scalac/typechecker/RefCheck.java39
12 files changed, 299 insertions, 108 deletions
diff --git a/sources/scala/tools/scalac/ast/parser/Parser.scala b/sources/scala/tools/scalac/ast/parser/Parser.scala
index 59d9a2821e..c33e62a76e 100644
--- a/sources/scala/tools/scalac/ast/parser/Parser.scala
+++ b/sources/scala/tools/scalac/ast/parser/Parser.scala
@@ -1849,15 +1849,15 @@ class Parser(unit: Unit) {
/** ClassDef ::= Id [TypeParamClause] [ParamClause] [`:' SimpleType] ClassTemplate
*/
def classDef(mods: int): Array[Tree] = {
- val lhs = new ListBuffer[Tuple4[Int, Name, Array[Tree$AbsTypeDef], Array[Array[Tree$ValDef]]]];
- do {
- s.nextToken();
- lhs.append(Tuple4(s.pos,
- ident().toTypeName(),
- typeParamClauseOpt(true),
- paramClauseOpt()));
+ val lhs = new ListBuffer[Tuple4[Int, Name, Array[Tree$AbsTypeDef], Array[Array[Tree$ValDef]]]];
+ do {
+ s.nextToken();
+ lhs.append(Tuple4(s.pos,
+ ident().toTypeName(),
+ typeParamClauseOpt(true),
+ paramClauseOpt()));
} while (s.token == COMMA);
- val thistpe = simpleTypedOpt();
+ val thistpe = simpleTypedOpt();
val template = classTemplate();
val ts = new myTreeList();
lhs foreach { case Tuple4(p, n, tp, vp) =>
diff --git a/sources/scala/tools/scalac/ast/printer/TextTreePrinter.scala b/sources/scala/tools/scalac/ast/printer/TextTreePrinter.scala
index 35f0d1a4be..14da5e6613 100644
--- a/sources/scala/tools/scalac/ast/printer/TextTreePrinter.scala
+++ b/sources/scala/tools/scalac/ast/printer/TextTreePrinter.scala
@@ -166,6 +166,7 @@ class TextTreePrinter(writer: PrintWriter) with TreePrinter {
protected final val TXT_EQUAL = Simple("=");
protected final val TXT_SUPERTYPE = Simple(">:");
protected final val TXT_SUBTYPE = Simple("<:");
+ protected final val TXT_VIEWBOUND = Simple("<+");
protected final val TXT_HASH = Simple("#");
protected final val TXT_RIGHT_ARROW = Simple("=>");
protected final val TXT_LEFT_PAREN = Simple("(");
@@ -293,7 +294,7 @@ class TextTreePrinter(writer: PrintWriter) with TreePrinter {
print(KW_TYPE);
print(Space);
printSymbolDefinition(tree.symbol(), name);
- printBounds(lobound, rhs);
+ printBounds(lobound, rhs, mods);
case Tree$AliasTypeDef(mods, name, tparams, rhs) =>
printModifiers(mods);
@@ -697,7 +698,7 @@ class TextTreePrinter(writer: PrintWriter) with TreePrinter {
case Tree$AbsTypeDef(mods, name, bound, lobound) =>
printModifiers(mods);
printSymbolDefinition(tree.symbol(), name);
- printBounds(lobound, bound);
+ printBounds(lobound, bound, mods);
case Tree$ValDef(mods, name, tpe, Tree.Empty) =>
printModifiers(mods);
@@ -708,7 +709,7 @@ class TextTreePrinter(writer: PrintWriter) with TreePrinter {
Debug.abort("bad parameter: " + tree);
}
- protected def printBounds(lobound: Tree, hibound: Tree): unit = {
+ protected def printBounds(lobound: Tree, hibound: Tree, mods: int): unit = {
val definitions: Definitions = scalac_Global.instance.definitions;
val printLoBound: Boolean =
if (lobound.getType() != null)
@@ -721,7 +722,10 @@ class TextTreePrinter(writer: PrintWriter) with TreePrinter {
hibound.getType().symbol() != definitions.ANY_CLASS
else
!"scala.Any".equals(hibound.toString());
- if (printHiBound) printOpt(TXT_SUBTYPE, hibound, true);
+ if (printHiBound)
+ printOpt(
+ if ((mods & Modifiers.VIEWBOUND) != 0) TXT_VIEWBOUND else TXT_SUBTYPE,
+ hibound, true);
}
}
}
diff --git a/sources/scala/tools/scalac/typechecker/Analyzer.scala b/sources/scala/tools/scalac/typechecker/Analyzer.scala
index 569b435f32..18cae3fe6d 100644
--- a/sources/scala/tools/scalac/typechecker/Analyzer.scala
+++ b/sources/scala/tools/scalac/typechecker/Analyzer.scala
@@ -408,9 +408,12 @@ class Analyzer(global: scalac_Global, descr: AnalyzerPhase) extends Transformer(
//System.out.println("checking " + sym);//DEBUG
checkNonCyclic(
pos, pre.memberInfo(sym).subst(sym.typeParams(), args));
- if (sym.kind == TYPE)
+ if (sym.kind == TYPE) {
checkNonCyclic(
pos, pre.memberLoBound(sym).subst(sym.typeParams(), args));
+ checkNonCyclic(
+ pos, pre.memberVuBound(sym).subst(sym.typeParams(), args));
+ }
sym.flags = sym.flags & ~LOCKED;
}
@@ -567,10 +570,21 @@ class Analyzer(global: scalac_Global, descr: AnalyzerPhase) extends Transformer(
// Views -----------------------------------------------------------------------
- private def applyView(v: View, tree: Tree, mode: int, pt: Type): Tree =
- transform(
- make.Apply(tree.pos, infer.viewExpr(tree.pos, v), NewArray.Tree(tree)),
- mode, pt);
+ private def applyView(v: View, tree: Tree, mode: int, pt: Type): Tree = {
+ val vexpr = infer.viewExpr(tree.pos, v);
+ val vapp = transform(
+ make.Apply(tree.pos, vexpr, NewArray.Tree(tree)), mode, pt);
+ if (v.symtype.isObjectType()) {
+ gen.If(
+ gen.Apply(
+ gen.Select(
+ vexpr.duplicate(),
+ definitions.ANY_EQEQ),
+ NewArray.Tree(gen.mkNullLit(tree.pos))),
+ gen.mkNullLit(tree.pos),
+ vapp)
+ } else vapp
+ }
// Contexts -------------------------------------------------------------------
@@ -1156,7 +1170,12 @@ class Analyzer(global: scalac_Global, descr: AnalyzerPhase) extends Transformer(
tree.asInstanceOf[Tree$AbsTypeDef].rhs = rhs;
lobound = transform(lobound, TYPEmode);
(tree.asInstanceOf[Tree$AbsTypeDef]).lobound = lobound;
- owntype = rhs.getType();
+ if (sym.isViewBounded()) {
+ sym.setVuBound(rhs.getType());
+ owntype = definitions.ANY_TYPE();
+ } else {
+ owntype = rhs.getType();
+ }
sym.setLoBound(lobound.getType());
owntype.symbol().initialize();//to detect cycles todo: needed?
@@ -1917,7 +1936,8 @@ class Analyzer(global: scalac_Global, descr: AnalyzerPhase) extends Transformer(
System.arraycopy(tparams, 0, tparams2, 0, tparams.length);
System.arraycopy(tparams1, 0, tparams2, tparams.length, tparams1.length);
}
- transformArgs(pos, meth, tparams2, restp, argMode, args, pt)
+ transformArgs(pos, meth, tparams2,
+ infer.skipViewParams(tparams2, restp), argMode, args, pt)
case Type.ErrorType =>
var i = 0; while (i < args.length) {
@@ -2425,28 +2445,13 @@ class Analyzer(global: scalac_Global, descr: AnalyzerPhase) extends Transformer(
// match against arguments
fn1.getType() match {
case Type$PolyType(tparams, restp) if (tparams.length == argtypes.length) =>
- /* constant fold asInstanceOf calls.
- fn1 match {
- case Tree$Select(qual, name) =>
- if (fn1.symbol() == definitions.ANY_AS &&
- qual.getType().isInstanceOf[Type$ConstantType]) {
- val restp1: Type = constfold.foldAsInstanceOf(
- tree.pos,
- qual.getType().asInstanceOf[Type$ConstantType],
- argtypes(0));
- restp1 match {
- case ConstantType(_, Object value) =>
- return make.Literal(tree.pos, value)
- .setType(restp1);
- case =>
- }
- }
- case _ =>
- }
- */
constfold.tryToFold(
- copy.TypeApply(tree, fn1, args1)
- .setType(restp.subst(tparams, argtypes)));
+ infer.completeTypeApply(
+ copy.TypeApply(tree, fn1, args1)
+ .setType(restp.subst(tparams, argtypes))));
+
+ case Type.ErrorType =>
+ tree.setType(Type.ErrorType)
case fn1tp =>
if (!fn1tp.isError()) error(tree.pos,
@@ -2531,7 +2536,7 @@ class Analyzer(global: scalac_Global, descr: AnalyzerPhase) extends Transformer(
if (tsym == c) {
fn0 match {
case Tree$AppliedType(_, targs) =>
- fn1 = gen.TypeApply(fn1, targs);
+ fn1 = infer.completeTypeApply(gen.TypeApply(fn1, targs));
case _ =>
}
} else {
diff --git a/sources/scala/tools/scalac/typechecker/DeSugarize.scala b/sources/scala/tools/scalac/typechecker/DeSugarize.scala
index d4a5c84297..59ec8946d6 100644
--- a/sources/scala/tools/scalac/typechecker/DeSugarize.scala
+++ b/sources/scala/tools/scalac/typechecker/DeSugarize.scala
@@ -293,17 +293,19 @@ class DeSugarize(make: TreeFactory, copy: TreeCopier, gen: TreeGen, infer: scala
/** expands view-bounded class and method definitions
*/
- def Definition(tree: Tree) =
+ def Definition(tree: Tree): Tree =
tree match {
case Tree$ClassDef(mods, name, tparams, vparams, tpe, templ) =>
+ //System.out.println("DEF " + make.ClassDef(tree.pos, mods, name, tparams, addViewParams(tparams, vparams), tpe, templ));//DEBUG
make.ClassDef(tree.pos, mods, name, tparams,
addViewParams(tparams, vparams), tpe, templ);
+
case Tree$DefDef(mods, name, tparams, vparams, tpe, rhs) =>
make.DefDef(tree.pos, mods, name, tparams,
addViewParams(tparams, vparams), tpe, rhs)
case _ =>
- tree
+ return tree
}
def addViewParams(tparams: Array[Tree$AbsTypeDef], vparams: Array[Array[Tree$ValDef]]): Array[Array[Tree$ValDef]] = {
@@ -330,6 +332,7 @@ class DeSugarize(make: TreeFactory, copy: TreeCopier, gen: TreeGen, infer: scala
val vparams1 = new Array[Array[Tree$ValDef]](vparams.length + 1);
vparams1(0) = new Array[Tree$ValDef](viewparams.length());
viewparams.copyTo(vparams1(0));
+ //for (val t <- vparams1(0)) System.out.println("new view param: " + t);//DEBUG
System.arraycopy(vparams, 0, vparams1, 1, vparams.length);
vparams1
} else vparams
diff --git a/sources/scala/tools/scalac/typechecker/Infer.scala b/sources/scala/tools/scalac/typechecker/Infer.scala
index ab69716ad2..8dada48e1b 100644
--- a/sources/scala/tools/scalac/typechecker/Infer.scala
+++ b/sources/scala/tools/scalac/typechecker/Infer.scala
@@ -115,7 +115,9 @@ class Infer(global: scalac_Global, gen: TreeGen, make: TreeFactory) extends scal
case VAL =>
variance(tparam, sym.info())
case TYPE =>
- variance(tparam, sym.info()) & flip(variance(tparam, sym.loBound()))
+ variance(tparam, sym.info()) &
+ flip(variance(tparam, sym.loBound())) &
+ variance(tparam, sym.vuBound())
case ALIAS =>
cut(variance(tparam, sym.info()))
case _ =>
@@ -151,7 +153,7 @@ class Infer(global: scalac_Global, gen: TreeGen, make: TreeFactory) extends scal
v
}
- /** Does given `tparam' occur with variance `v' in type?
+ /** Compute variance of type parameter `tparam' in type `tp'.
*/
private def variance(tparam: Symbol, tp: Type): int = tp match {
case Type.ErrorType | Type.AnyType | Type.NoType | Type.NoPrefix |
@@ -318,36 +320,62 @@ class Infer(global: scalac_Global, gen: TreeGen, make: TreeFactory) extends scal
}
def viewExpr(pos: int, v: View): Tree = {
- val qual = v.qual.duplicate();
- qual.pos = pos;
val viewType = checkAccessible(
- pos, v.sym, v.symtype, qual, qual.getType());
- make.Select(pos, qual, v.sym.name)
- .setSymbol(v.sym).setType(viewType)
+ pos, v.sym, v.symtype, v.qual, v.qual.getType());
+ v.qual match {
+ case Tree.Empty =>
+ make.Ident(pos, v.sym.name)
+ .setSymbol(v.sym).setType(viewType)
+ case _ =>
+ val qual = v.qual.duplicate();
+ qual.pos = pos;
+ make.Select(pos, qual, v.sym.name)
+ .setSymbol(v.sym).setType(viewType)
+ }
+ }
+
+ private def viewObj(meth: Tree, msym: Symbol) = msym.getType() match {
+ case Type$MethodType(params: Array[Symbol], _) =>
+ assert(params.length == 1);
+ val paramsym = params(0).cloneSymbol(getContext.owner);
+ gen.mkFunction(
+ meth.pos,
+ NewArray.ValDef(gen.mkParam(paramsym)),
+ gen.Apply(meth, NewArray.Tree(gen.Ident(meth.pos, paramsym))),
+ meth.getType().resultType(),
+ getContext.owner)
+ case _ =>
+ meth
}
- def viewArg(pos: int, vtype: Type, targs: Array[Type]): Tree = {
+ private def viewArg(pos: int, vtype: Type, targs: Array[Type]): Tree = {
val vargs = vtype.typeArgs();
- val v = bestView(vargs(0), vargs(1), Names.EMPTY);
- if (v != null) {
- var vtree = viewExpr(pos, v);
- vtree.getType() match {
- case Type$PolyType(vtparams, vrestype) =>
- assert(vtparams.length != 0);
- vtree = exprInstance(vtree, vtparams, vrestype, vtype);
- assert(vtree.getType().isSubType(vtype));
- }
- vtree
+ if (vargs(0).isSubType(vargs(1))) {
+ gen.mkNullLit(pos)
} else {
- error(pos,
- "type instantiation with [" +
- ArrayApply.toString(targs.asInstanceOf[Array[Object]], ",") +
- "] failed since " + vargs(0) + " is not viewable as " + vargs(1));
- gen.mkDefaultValue(pos, vtype)
+ val v = bestView(vargs(0), vargs(1), Names.EMPTY);
+ if (v != null) {
+ var vmeth = viewExpr(pos, v);
+ vmeth.getType() match {
+ case Type$PolyType(vtparams, vrestype) =>
+ assert(vtparams.length != 0);
+ vmeth = exprInstance(vmeth, vtparams, vrestype, vtype);
+ assert(vmeth.getType().isSubType(vtype));
+ case _ =>
+ }
+ viewObj(vmeth, v.sym)
+ } else {
+ error(pos,
+ "type instantiation with [" +
+ ArrayApply.toString(targs.asInstanceOf[Array[Object]], ",") +
+ "] failed since " + vargs(0) + " is not viewable as " + vargs(1));
+ gen.mkDefaultValue(pos, vtype)
+ }
}
}
- def addViewArgs(tree: Tree, tparams: Array[Symbol], restype: Type, targs: Array[Type]): Tree = {
+ private def passViewArgs(tree: Tree, tparams: Array[Symbol], restype: Type,
+ targs: Array[Type]): Tree =
restype match {
case Type$MethodType(params, _) =>
val viewargs = new Array[Tree](params.length);
@@ -356,10 +384,42 @@ class Infer(global: scalac_Global, gen: TreeGen, make: TreeFactory) extends scal
tree.pos, params(i).getType().subst(tparams, targs), targs);
i = i + 1
}
+ //System.out.println("new view args: " + gen.Apply(tree, viewargs));//DEBUG
gen.Apply(tree, viewargs);
case Type.ErrorType =>
tree
}
+
+ def isViewBounded(tparams: Array[Symbol]) = {
+ var viewbounded = false;
+ var j = 0; while (j < tparams.length) {
+ viewbounded = viewbounded | tparams(j).isViewBounded();
+ j = j + 1
+ }
+ viewbounded
+ }
+
+ def skipViewParams(tparams: Array[Symbol], tp: Type): Type = tp match {
+ case Type$MethodType(_, restp) if isViewBounded(tparams) =>
+ restp
+ case _ =>
+ tp
+ }
+
+ def completeTypeApply(tree: Tree): Tree = {
+ tree match {
+ case Tree$TypeApply(fn, targs) =>
+ fn.getType() match {
+ case Type$PolyType(tparams, restp) if tparams.length == targs.length =>
+ if (isViewBounded(tparams)) {
+ val result = passViewArgs(tree, tparams, restp, Tree.typeOf(targs));
+ //System.out.println("completed type apply: " + result + ":" + result.getType());//DEBUG
+ result
+ } else tree
+ case _ => tree
+ }
+ case _ => tree
+ }
}
// Type parameter inference -----------------------------------------------------
@@ -621,6 +681,10 @@ class Infer(global: scalac_Global, gen: TreeGen, make: TreeFactory) extends scal
newparams(i).loBound()
.subst(tparams, newparams)
.subst(tparams1, newparams1));
+ newparams(i).setVuBound(
+ newparams(i).vuBound()
+ .subst(tparams, newparams)
+ .subst(tparams1, newparams1));
i = i + 1
}}
new Type$PolyType(newparams, restp1.subst(tparams, newparams))
@@ -693,14 +757,18 @@ class Infer(global: scalac_Global, gen: TreeGen, make: TreeFactory) extends scal
true
}
- /** Type arguments mapped to `scala.All' are taken to be uninstantiated.
+ /** Type arguments mapped to `scala.All' and not covariant in `restype'
+ * are taken to be uninstantiated.
* Map all those type arguments to their corresponding type parameters
* and return all these type parameters as result.
*/
- private def normalizeArgs(targs: Array[Type], tparams: Array[Symbol]): Array[Symbol] = {
+ private def normalizeArgs(targs: Array[Type], tparams: Array[Symbol], restype: Type): Array[Symbol] = {
var uninstantiated: Type$List = Type$List.EMPTY;
{ var i = 0; while (i < targs.length) {
- if (targs(i).symbol() == definitions.ALL_CLASS) {
+ if (targs(i).symbol() == definitions.ALL_CLASS &&
+ (variance(tparams(i), restype) & COVARIANT) == 0 &&
+ !tparams(i).isViewBounded()) {
+ //System.out.println("normalizing " + tparams(i) + " / " + restype);//DEBUG
targs(i) = tparams(i).getType();
uninstantiated = Type$List.append(uninstantiated, targs(i));
}
@@ -783,7 +851,7 @@ class Infer(global: scalac_Global, gen: TreeGen, make: TreeFactory) extends scal
argtypes: Array[Type], restp: Type,
pt: Type,
needToSucceed: boolean, regularValue: boolean): Array[Type] = {
- //System.out.println("methTypeArgs, tparams = " + ArrayApply.toString(tparams) + ", params = " + ArrayApply.toString(params) + ", type(params) = " + ArrayApply.toString(Symbol.type(params)) + ", argtypes = " + ArrayApply.toString(argtypes));//DEBUG
+ //System.out.println("methTypeArgs, tparams = " + ArrayApply.toString(tparams.asInstanceOf[Array[Object]]) + ", params = " + ArrayApply.toString(params.asInstanceOf[Array[Object]]) + ", type(params) = " + ArrayApply.toString(Symbol.getType(params).asInstanceOf[Array[Object]]) + ", argtypes = " + ArrayApply.toString(argtypes.asInstanceOf[Array[Object]]) + ", restp = " + restp + ", pt = " + pt);//DEBUG
val tvars: Array[Type] = freshVars(tparams);
val formals: Array[Type] = formalTypes(params, argtypes.length);
@@ -834,7 +902,6 @@ class Infer(global: scalac_Global, gen: TreeGen, make: TreeFactory) extends scal
solve(tparams, false, variance(tparams, formals), tvars, i);
i = i + 1
}}
- //System.out.println(" = " + ArrayApply.toString(tvars));//DEBUG
tvars
}
@@ -861,18 +928,16 @@ class Infer(global: scalac_Global, gen: TreeGen, make: TreeFactory) extends scal
}
if (0 < i) {
val argtrees: Array[Tree] = new Array[Tree](i);
- var viewbounded = false;
{ var j = 0; while (j < i) {
argtrees(j) = gen.mkType(tree.pos, targs(j));
- viewbounded = viewbounded | ((tparams(j).flags & VIEWBOUND) != 0);
j = j + 1
}}
- tree1 = make.TypeApply(tree.pos, tree1, argtrees)
- .setType(restype.subst(tparams, targs));
- if (viewbounded)
- tree1 = addViewArgs(tree1, tparams, restype, targs);
+ completeTypeApply(
+ make.TypeApply(tree.pos, tree1, argtrees)
+ .setType(restype.subst(tparams, targs)))
+ } else {
+ tree1.setType(restype.subst(tparams, targs));
}
- tree1
}
/** Return the instantiated and normalized type of polymorphic expression
@@ -934,6 +999,7 @@ class Infer(global: scalac_Global, gen: TreeGen, make: TreeFactory) extends scal
* types `argtypes' and its result type is compatible with `pt'.
*/
def methodInstance(tree: Tree, tparams: Array[Symbol], restype: Type, argtypes: Array[Type], pt: Type): Tree = {
+ //System.out.println("methodinstance, tree = " + tree + ":" + tree.getType() + ", tparams = " + ArrayApply.toString(tparams.asInstanceOf[Array[Object]]) + ", restype = " + restype + ", argtypes = " + ArrayApply.toString(argtypes.asInstanceOf[Array[Object]]) + ", pt = " + pt);//DEBUG
restype match {
case Type$PolyType(tparams1, restype1) =>
val tparams2: Array[Symbol] = new Array[Symbol](tparams.length + tparams1.length);
@@ -944,7 +1010,14 @@ class Infer(global: scalac_Global, gen: TreeGen, make: TreeFactory) extends scal
case Type$MethodType(params, restpe) =>
var targs: Array[Type] = _;
try {
- targs = methTypeArgs(tparams, params, argtypes, restpe, pt, true, false);
+ restpe match {
+ case Type$MethodType(params1, restpe1) if isViewBounded(tparams) =>
+ targs = methTypeArgs(
+ tparams, params1, argtypes, restpe1, pt, true, false);
+ case _ =>
+ targs = methTypeArgs(
+ tparams, params, argtypes, restpe, pt, true, false);
+ }
} catch {
case ex: NoInstance =>
throw new Type$Error(
@@ -954,7 +1027,7 @@ class Infer(global: scalac_Global, gen: TreeGen, make: TreeFactory) extends scal
Type.widen(argtypes), Type.AnyType) +
"\n --- because ---\n" + ex.getMessage());
}
- val uninstantiated: Array[Symbol] = normalizeArgs(targs, tparams);
+ val uninstantiated: Array[Symbol] = normalizeArgs(targs, tparams, restype);
checkBounds(tparams, targs, "inferred ");
val restype1: Type =
if (uninstantiated.length == 0) restype
@@ -1032,7 +1105,7 @@ class Infer(global: scalac_Global, gen: TreeGen, make: TreeFactory) extends scal
val targs: Array[Type] = methTypeArgs(
tparams, params, argtypes, restpe, pt, false, regularValue);
if (targs != null) {
- val uninstantiated: Array[Symbol] = normalizeArgs(targs, tparams);
+ val uninstantiated: Array[Symbol] = normalizeArgs(targs, tparams, restpe);
isWithinBounds(tparams, targs) &&
exprTypeArgs(uninstantiated,
restpe.subst(tparams, targs), pt,
diff --git a/sources/scalac/ast/TreeGen.java b/sources/scalac/ast/TreeGen.java
index 1bbb32aebf..4abd940f9c 100644
--- a/sources/scalac/ast/TreeGen.java
+++ b/sources/scalac/ast/TreeGen.java
@@ -1094,7 +1094,7 @@ public class TreeGen implements Kinds, Modifiers, TypeTags {
AbsTypeDef tree = make.AbsTypeDef(
sym.pos,
sym,
- TypeTerm(sym.pos, sym.nextInfo()),
+ TypeTerm(sym.pos, sym.isViewBounded() ? sym.vuBound() : sym.nextInfo()),
TypeTerm(sym.pos, sym.loBound()));
tree.setType(Type.NoType);
return tree;
diff --git a/sources/scalac/symtab/ClosureHistory.java b/sources/scalac/symtab/ClosureHistory.java
index 8825fb3e20..c17ad46f90 100644
--- a/sources/scalac/symtab/ClosureHistory.java
+++ b/sources/scalac/symtab/ClosureHistory.java
@@ -14,6 +14,7 @@ import java.util.TreeMap;
import scalac.Global;
import scalac.framework.History;
import scalac.util.Debug;
+import scalac.util.ArrayApply;
/** This class implements a closure history. */
public class ClosureHistory extends History {
@@ -43,6 +44,7 @@ public class ClosureHistory extends History {
closure[0] = clasz.type();
for (int i = 1; i < closure.length; i++)
closure[i] = (Type)types.next();
+ //System.out.println("closure(" + owner + ") = " + ArrayApply.toString(closure));//DEBUG
return closure;
}
diff --git a/sources/scalac/symtab/Symbol.java b/sources/scalac/symtab/Symbol.java
index c65bdcdc6c..ccd9f2632a 100644
--- a/sources/scalac/symtab/Symbol.java
+++ b/sources/scalac/symtab/Symbol.java
@@ -504,6 +504,12 @@ public abstract class Symbol implements Modifiers, Kinds {
throw new ApplicationError("setLoBound inapplicable for " + this);
}
+ /** Set the view bound of this type variable
+ */
+ public Symbol setVuBound(Type lobound) {
+ throw new ApplicationError("setVuBound inapplicable for " + this);
+ }
+
/** Add an auxiliary constructor to class.
*/
public void addConstructor(Symbol constr) {
@@ -575,6 +581,13 @@ public abstract class Symbol implements Modifiers, Kinds {
return kind == VAL && (flags & MUTABLE) != 0;
}
+ /** Does this symbol denote a view bounded type variable? */
+ public final boolean isViewBounded() {
+ Global global = Global.instance;
+ return kind == TYPE && (flags & VIEWBOUND) != 0 &&
+ global.currentPhase.id <= global.PHASE.REFCHECK.id();
+ }
+
/**
* Does this symbol denote a final method? A final method is one
* that can't be overridden in a subclass. This method assumes
@@ -1278,6 +1291,12 @@ public abstract class Symbol implements Modifiers, Kinds {
return Global.instance.definitions.ALL_TYPE();
}
+ /** The view bound of this type variable
+ */
+ public Type vuBound() {
+ return Global.instance.definitions.ANY_TYPE();
+ }
+
/** Get this.type corresponding to this symbol
*/
public Type thisType() {
@@ -1757,6 +1776,7 @@ final class AliasTypeSymbol extends TypeSymbol {
final class AbsTypeSymbol extends TypeSymbol {
private Type lobound = null;
+ private Type vubound = null;
/** Initializes this instance. */
AbsTypeSymbol(int pos, Name name, Symbol owner, int flags, int attrs) {
@@ -1769,14 +1789,25 @@ final class AbsTypeSymbol extends TypeSymbol {
return lobound == null ? Global.instance.definitions.ALL_TYPE() : lobound;
}
+ public Type vuBound() {
+ initialize();
+ return vubound == null ? Global.instance.definitions.ANY_TYPE() : vubound;
+ }
+
public Symbol setLoBound(Type lobound) {
this.lobound = lobound;
return this;
}
+ public Symbol setVuBound(Type vubound) {
+ this.vubound = vubound;
+ return this;
+ }
+
protected TypeSymbol cloneTypeSymbolImpl(Symbol owner, int attrs) {
TypeSymbol clone = new AbsTypeSymbol(pos, name, owner, flags, attrs);
clone.setLoBound(loBound());
+ clone.setVuBound(vuBound());
return clone;
}
diff --git a/sources/scalac/symtab/Type.java b/sources/scalac/symtab/Type.java
index 9adcade4a2..4bff125e53 100644
--- a/sources/scalac/symtab/Type.java
+++ b/sources/scalac/symtab/Type.java
@@ -1035,8 +1035,10 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags {
}
for (int i = 0; i < syms2.length; i++) {
syms2[i].setInfo(syms1[i].info().subst(syms1, syms2));
- if (syms2[i].kind == TYPE)
+ if (syms2[i].kind == TYPE) {
syms2[i].setLoBound(syms1[i].loBound().subst(syms1, syms2));
+ syms2[i].setVuBound(syms1[i].vuBound().subst(syms1, syms2));
+ }
}
for (int i = 0; i < syms2.length; i++) {
members2.enter(syms2[i]);
@@ -1086,6 +1088,12 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags {
if (!dontClone) sym = sym.cloneSymbol();
sym.setLoBound(lb1);
}
+ Type vb = sym.vuBound();
+ Type vb1 = apply(vb);
+ if (vb != vb1) {
+ if (!dontClone) sym = sym.cloneSymbol();
+ sym.setVuBound(vb1);
+ }
}
return sym;
}
@@ -1319,6 +1327,12 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags {
return sym.loBound().asSeenFrom(this, sym.owner());
}
+ /** The view bound of `sym', seen as a member of this type.
+ */
+ public Type memberVuBound(Symbol sym) {
+ return sym.vuBound().asSeenFrom(this, sym.owner());
+ }
+
// Substitutions ---------------------------------------------------------------
/** A common map superclass for symbol/symbol and type/symbol substitutions.
@@ -1920,7 +1934,8 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags {
if (ps.length != ps1.length) return false;
for (int i = 0; i < ps.length; i++)
if (!ps1[i].info().subst(ps1, ps).isSameAs(ps[i].info()) ||
- !ps[i].loBound().isSameAs(ps1[i].loBound().subst(ps1, ps)))
+ !ps[i].loBound().isSameAs(ps1[i].loBound().subst(ps1, ps)) ||
+ !ps[i].vuBound().isSameAs(ps1[i].vuBound().subst(ps1, ps)))
return false;
return res.isSubType(res1.subst(ps1, ps));
}
@@ -1979,9 +1994,9 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags {
return true;
}
- case TypeRef(_, Symbol sym, Type[] args):
+ case TypeRef(_, Symbol sym, _):
switch (that) {
- case TypeRef(Type pre1, Symbol sym1, _):
+ case TypeRef(_, Symbol sym1, _):
if (sym1.kind == TYPE && this.isSubType(that.loBound()))
return true;
}
@@ -2092,7 +2107,9 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags {
self.memberInfo(sym).subst(tparams, targs)
.isSubType(sym1.info().substThis(sym1.owner(), self)) &&
sym1.loBound().substThis(sym1.owner(), self)
- .isSubType(self.memberLoBound(sym).subst(tparams, targs))
+ .isSubType(self.memberLoBound(sym).subst(tparams, targs)) &&
+ self.memberVuBound(sym).subst(tparams, targs)
+ .isSubType(sym1.vuBound().substThis(sym1.owner(), self))
||
(sym.kind == TYPE && sym1.kind == ALIAS &&
sym1.info().unalias().isSameAs(sym.type())));
@@ -2203,7 +2220,8 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags {
if (ps.length != ps1.length) return false;
for (int i = 0; i < ps.length; i++)
if (!ps1[i].info().subst(ps1, ps).isSameAs(ps[i].info()) ||
- !ps1[i].loBound().subst(ps1, ps).isSameAs(ps[i].loBound()))
+ !ps1[i].loBound().subst(ps1, ps).isSameAs(ps[i].loBound()) ||
+ !ps1[i].vuBound().subst(ps1, ps).isSameAs(ps[i].vuBound()))
return false;
return res.isSameAs(res1.subst(ps1, ps));
}
@@ -2293,6 +2311,9 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags {
sym2.owner(), sym1.owner().thisType())) ||
!sym1.loBound().isSameAs(
sym2.loBound().substThis(
+ sym2.owner(), sym1.owner().thisType())) ||
+ !sym1.vuBound().isSameAs(
+ sym2.vuBound().substThis(
sym2.owner(), sym1.owner().thisType())))
return false;
}
@@ -2656,6 +2677,7 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags {
private static Type polyLub(Type[] tps, Symbol[] tparams0) {
Type[][] hiboundss = new Type[tparams0.length][tps.length];
Type[][] loboundss = new Type[tparams0.length][tps.length];
+ Type[][] vuboundss = new Type[tparams0.length][tps.length];
Type[] restps = new Type[tps.length];
for (int i = 0; i < tps.length; i++) {
switch (tps[i]) {
@@ -2666,6 +2688,8 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags {
.subst(tparams, tparams0);
loboundss[j][i] = tparams[j].loBound()
.subst(tparams, tparams0);
+ vuboundss[j][i] = tparams[j].vuBound()
+ .subst(tparams, tparams0);
}
restps[i] = restp.subst(tparams, tparams0);
} else {
@@ -2678,15 +2702,18 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags {
}
Type[] hibounds = new Type[tparams0.length];
Type[] lobounds = new Type[tparams0.length];
+ Type[] vubounds = new Type[tparams0.length];
for (int j = 0; j < tparams0.length; j++) {
hibounds[j] = glb(hiboundss[j]);
lobounds[j] = lub(loboundss[j]);
+ vubounds[j] = glb(vuboundss[j]);
}
Symbol[] tparams = new Symbol[tparams0.length];
for (int j = 0; j < tparams.length; j++) {
tparams[j] = tparams0[j].cloneSymbol(Symbol.NONE)
.setInfo(hibounds[j].subst(tparams0, tparams))
- .setLoBound(lobounds[j].subst(tparams0, tparams));
+ .setLoBound(lobounds[j].subst(tparams0, tparams))
+ .setVuBound(vubounds[j].subst(tparams0, tparams));
}
return Type.PolyType(tparams, lub(restps).subst(tparams0, tparams));
}
@@ -2899,11 +2926,15 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags {
private static boolean addMember(Scope s, Symbol sym, Type glbThisType) {
Type syminfo = sym.info().substThis(sym.owner(), glbThisType);
Type symlb = sym.loBound().substThis(sym.owner(), glbThisType);
+ Type symvb = sym.vuBound().substThis(sym.owner(), glbThisType);
Scope.Entry e = s.lookupEntry(sym.name);
if (e == Scope.Entry.NONE) {
Symbol sym1 = sym.cloneSymbol(glbThisType.symbol());
sym1.setInfo(syminfo);
- if (sym1.kind == TYPE) sym1.setLoBound(symlb);
+ if (sym1.kind == TYPE) {
+ sym1.setLoBound(symlb);
+ sym1.setVuBound(symvb);
+ }
s.enter(sym1);
} else {
Type einfo = e.sym.info();
@@ -2926,6 +2957,14 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags {
} else {
e.sym.setLoBound(lub(new Type[]{elb, symlb}));
}
+ Type evb = e.sym.vuBound();
+ if (evb.isSameAs(symvb)) {
+ } else if (evb.isSubType(symvb)) {
+ } else if (symvb.isSubType(evb)) {
+ e.sym.setVuBound(symvb);
+ } else {
+ e.sym.setVuBound(glb(new Type[]{evb, symvb}));
+ }
}
}
return true;
@@ -2934,6 +2973,7 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags {
private static Type polyGlb(Type[] tps, Symbol[] tparams0) {
Type[][] hiboundss = new Type[tparams0.length][tps.length];
Type[][] loboundss = new Type[tparams0.length][tps.length];
+ Type[][] vuboundss = new Type[tparams0.length][tps.length];
Type[] restps = new Type[tps.length];
for (int i = 0; i < tps.length; i++) {
switch (tps[i]) {
@@ -2944,6 +2984,8 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags {
.subst(tparams, tparams0);
loboundss[j][i] = tparams[j].loBound()
.subst(tparams, tparams0);
+ vuboundss[j][i] = tparams[j].vuBound()
+ .subst(tparams, tparams0);
}
restps[i] = restp.subst(tparams, tparams0);
} else {
@@ -2956,15 +2998,18 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags {
}
Type[] hibounds = new Type[tparams0.length];
Type[] lobounds = new Type[tparams0.length];
+ Type[] vubounds = new Type[tparams0.length];
for (int j = 0; j < tparams0.length; j++) {
hibounds[j] = lub(hiboundss[j]);
lobounds[j] = glb(loboundss[j]);
+ vubounds[j] = lub(vuboundss[j]);
}
Symbol[] tparams = new Symbol[tparams0.length];
for (int j = 0; j < tparams.length; j++) {
tparams[j] = tparams0[j].cloneSymbol(Symbol.NONE)
.setInfo(hibounds[j].subst(tparams0, tparams))
- .setLoBound(lobounds[j].subst(tparams0, tparams));
+ .setLoBound(lobounds[j].subst(tparams0, tparams))
+ .setVuBound(vubounds[j].subst(tparams0, tparams));
}
return Type.PolyType(tparams, glb(restps).subst(tparams0, tparams));
}
diff --git a/sources/scalac/symtab/classfile/Pickle.java b/sources/scalac/symtab/classfile/Pickle.java
index fcf3143da7..2c46855821 100644
--- a/sources/scalac/symtab/classfile/Pickle.java
+++ b/sources/scalac/symtab/classfile/Pickle.java
@@ -118,15 +118,18 @@ public class Pickle implements Kinds, Modifiers, EntryTags {
if (isLocal(sym)) {
putEntry(sym.name);
putSymbol(sym.isConstructor() ? sym.constructorClass() : sym.owner());
- putType(sym.info());
switch (sym.kind) {
case TYPE:
+ if (sym.isViewBounded()) putType(sym.vuBound());
+ else putType(sym.info());
putType(sym.loBound());
break;
case ALIAS:
+ putType(sym.info());
putSymbol(sym.allConstructors());
break;
case CLASS:
+ putType(sym.info());
putType(sym.typeOfThis());
putSymbol(sym.allConstructors());
for (Scope.SymbolIterator it = sym.members().iterator();
@@ -134,6 +137,7 @@ public class Pickle implements Kinds, Modifiers, EntryTags {
putSymbol(it.next());
break;
case VAL:
+ putType(sym.info());
if (sym.isConstructor() &&
sym == sym.constructorClass().allConstructors())
putSymbol(sym.constructorClass());
@@ -336,25 +340,31 @@ public class Pickle implements Kinds, Modifiers, EntryTags {
writeRef(sym.name);
writeRef(sym.isConstructor() ? sym.constructorClass() : sym.owner());
writeNat(sym.flags);
- writeRef(sym.info());
switch (sym.kind) {
case TYPE:
+ if (sym.isViewBounded()) writeRef(sym.vuBound());
+ else writeRef(sym.info());
writeRef(sym.loBound());
break;
case ALIAS:
+ writeRef(sym.info());
writeRef(sym.allConstructors());
break;
case CLASS:
+ writeRef(sym.info());
writeRef(sym.typeOfThis());
writeRef(sym.allConstructors());
break;
case VAL:
+ writeRef(sym.info());
if (sym.isConstructor() &&
sym == sym.constructorClass().allConstructors())
writeRef(sym.constructorClass());
else if (sym.isModule())
writeRef(sym.moduleClass());
break;
+ default:
+ throw new ApplicationError();
}
} else if (sym.kind == NONE) {
writeByte(NONEsym);
diff --git a/sources/scalac/symtab/classfile/UnPickle.java b/sources/scalac/symtab/classfile/UnPickle.java
index 74a7027424..ba27cbbf60 100644
--- a/sources/scalac/symtab/classfile/UnPickle.java
+++ b/sources/scalac/symtab/classfile/UnPickle.java
@@ -244,7 +244,12 @@ public class UnPickle implements Kinds, Modifiers, EntryTags, TypeTags {
case TYPEsym:
entries[n] = sym = owner.newAbstractType(
Position.NOPOS, flags, name);
- sym.setInfo(getType(inforef, sym));
+ if ((flags & VIEWBOUND) != 0) {
+ sym.setInfo(global.definitions.ANY_TYPE());
+ sym.setVuBound(getType(inforef, sym));
+ } else {
+ sym.setInfo(getType(inforef, sym));
+ }
sym.setLoBound(readTypeRef(sym));
break;
diff --git a/sources/scalac/typechecker/RefCheck.java b/sources/scalac/typechecker/RefCheck.java
index c7e2572d72..2bb96cbe69 100644
--- a/sources/scalac/typechecker/RefCheck.java
+++ b/sources/scalac/typechecker/RefCheck.java
@@ -58,6 +58,8 @@ public class RefCheck extends Transformer implements Modifiers, Kinds {
// Override checking ------------------------------------------------------------
+ static final int HIBOUND = 0, LOBOUND = 1, VUBOUND = 2;
+
static boolean isIncomplete(Symbol sym) {
return sym.isDeferred() ||
sym.isAbstractOverride() &&
@@ -255,15 +257,17 @@ public class RefCheck extends Transformer implements Modifiers, Kinds {
if (other.typeParams().length != 0)
overrideError(pos, member, other, "may not override parameterized type");
if (!self.memberType(member).isSameAs(self.memberType(other)))
- overrideTypeError(pos, member, other, self, false);
+ overrideTypeError(pos, member, other, self, HIBOUND);
break;
case TYPE:
if (member.typeParams().length != 0)
overrideError(pos, member, other, "may not be parameterized");
if (!self.memberInfo(member).isSubType(self.memberInfo(other)))
- overrideTypeError(pos, member, other, self, false);
+ overrideTypeError(pos, member, other, self, HIBOUND);
if (!self.memberLoBound(other).isSubType(self.memberLoBound(member)))
- overrideTypeError(pos, member, other, self, true);
+ overrideTypeError(pos, member, other, self, LOBOUND);
+ if (!self.memberVuBound(member).isSubType(self.memberVuBound(other)))
+ overrideTypeError(pos, member, other, self, VUBOUND);
break;
default:
if (other.isConstructor())
@@ -271,7 +275,7 @@ public class RefCheck extends Transformer implements Modifiers, Kinds {
"cannot override a class constructor");
if (!normalizedInfo(self, member).isSubType(
normalizedInfo(self, other)))
- overrideTypeError(pos, member, other, self, false);
+ overrideTypeError(pos, member, other, self, HIBOUND);
}
}
}
@@ -284,17 +288,25 @@ public class RefCheck extends Transformer implements Modifiers, Kinds {
}
void overrideTypeError(int pos, Symbol member, Symbol other, Type site,
- boolean lobound) {
+ int boundkind) {
if (!other.type().isError() && !member.type().isError()) {
- Type memberInfo = lobound ? site.memberLoBound(member)
- : normalizedInfo(site, member);
- Type otherInfo = lobound ? site.memberLoBound(other)
- : normalizedInfo(site, other);
+ Type memberInfo;
+ Type otherInfo;
+ if (boundkind == LOBOUND) {
+ memberInfo = site.memberLoBound(member);
+ otherInfo = site.memberLoBound(other);
+ } else if (boundkind == VUBOUND) {
+ memberInfo = site.memberVuBound(member);
+ otherInfo = site.memberVuBound(other);
+ } else {
+ memberInfo = normalizedInfo(site, member);
+ otherInfo = normalizedInfo(site, other);
+ }
unit.error(pos,
member + member.locationString() +
- infoString(member, memberInfo, lobound) +
+ infoString(member, memberInfo, boundkind) +
"\n cannot override " + other + other.locationString() +
- infoString(other, otherInfo, lobound));
+ infoString(other, otherInfo, boundkind));
Type.explainTypes(memberInfo, otherInfo);
}
}
@@ -303,10 +315,10 @@ public class RefCheck extends Transformer implements Modifiers, Kinds {
return site.memberInfo(sym).derefDef();
}
- String infoString(Symbol sym, Type symtype, boolean lobound) {
+ String infoString(Symbol sym, Type symtype, int boundkind) {
switch (sym.kind) {
case ALIAS: return ", which equals " + symtype;
- case TYPE: return " bounded" + (lobound ? " from below" : "") + " by " + symtype;
+ case TYPE: return " bounded" + (boundkind == LOBOUND ? " from below" : "") + " by " + symtype;
case VAL: return " of type " + symtype;
default: return "";
}
@@ -956,6 +968,7 @@ public class RefCheck extends Transformer implements Modifiers, Kinds {
case AbsTypeDef(_, _, _, _):
validateVariance(sym, sym.info(), CoVariance);
validateVariance(sym, sym.loBound(), ContraVariance);
+ validateVariance(sym, sym.vuBound(), CoVariance);
return super.transform(tree);
case AliasTypeDef(_, _, _, _):