summaryrefslogtreecommitdiff
path: root/sources
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2003-05-08 14:53:48 +0000
committerMartin Odersky <odersky@gmail.com>2003-05-08 14:53:48 +0000
commit6f062616e25ccc18848b0e86ba999202bc20a6a2 (patch)
tree5d8beca433b1a9b75434246c6a43a4eee0865875 /sources
parent723503c1c8f2cfd89b24af71a638202354bc4c7e (diff)
downloadscala-6f062616e25ccc18848b0e86ba999202bc20a6a2.tar.gz
scala-6f062616e25ccc18848b0e86ba999202bc20a6a2.tar.bz2
scala-6f062616e25ccc18848b0e86ba999202bc20a6a2.zip
*** empty log message ***
Diffstat (limited to 'sources')
-rw-r--r--sources/meta/scala/MetaFunction.java2
-rw-r--r--sources/meta/scala/MetaTuple.java2
-rw-r--r--sources/scala/$colon$colon.scala8
-rw-r--r--sources/scala/BufferedIterator.scala2
-rw-r--r--sources/scala/Cell.scala5
-rw-r--r--sources/scala/Iterator.scala2
-rw-r--r--sources/scala/Labelled.scala2
-rw-r--r--sources/scala/List.scala45
-rw-r--r--sources/scala/Nil.scala6
-rw-r--r--sources/scala/None.scala9
-rw-r--r--sources/scala/Option.scala25
-rw-r--r--sources/scala/PartialFunction.scala2
-rw-r--r--sources/scala/Seq.scala2
-rw-r--r--sources/scala/Some.scala10
-rw-r--r--sources/scala/Stream.scala35
-rw-r--r--sources/scalac/symtab/Symbol.java2
-rw-r--r--sources/scalac/symtab/Type.java66
-rw-r--r--sources/scalac/transformer/LambdaLift.java16
-rw-r--r--sources/scalac/typechecker/Analyzer.java29
-rw-r--r--sources/scalac/typechecker/DeSugarize.java25
-rw-r--r--sources/scalac/typechecker/Infer.java82
21 files changed, 198 insertions, 179 deletions
diff --git a/sources/meta/scala/MetaFunction.java b/sources/meta/scala/MetaFunction.java
index 4f8c441e72..269cae0943 100644
--- a/sources/meta/scala/MetaFunction.java
+++ b/sources/meta/scala/MetaFunction.java
@@ -37,7 +37,7 @@ public class MetaFunction extends AbstractJavaExpander {
public void printClassScalaTParams() {
for (int i = 0; i < arity; i++)
- writer.print("?A").print(i).print(", ");
+ writer.print("- ?A").print(i).print(", ");
writer.print("+ ?R");
}
diff --git a/sources/meta/scala/MetaTuple.java b/sources/meta/scala/MetaTuple.java
index fe34f1fa3a..3a438aa4c4 100644
--- a/sources/meta/scala/MetaTuple.java
+++ b/sources/meta/scala/MetaTuple.java
@@ -36,7 +36,7 @@ public class MetaTuple extends AbstractScalaExpander {
public void printTParams() {
for (int i = 1; i <= arity; i++) {
if (i > 1) writer.print(", ");
- writer.print("T").print(i);
+ writer.print("+ T").print(i);
}
}
diff --git a/sources/scala/$colon$colon.scala b/sources/scala/$colon$colon.scala
index cb1bf098cc..16ad50f31a 100644
--- a/sources/scala/$colon$colon.scala
+++ b/sources/scala/$colon$colon.scala
@@ -3,9 +3,9 @@ package scala {
/* A non empty list.
*
*/
- final case class ::[b](hd: b, tl: List[b]) extends List[b] {
- def isEmpty = false;
- def head = hd;
- def tail = tl;
+ final case class ::[b, c <: b](hd: b, tl: List[c]) extends List[b] {
+ def isEmpty: boolean = false;
+ def head: b = hd;
+ def tail: List[b] = tl;
}
}
diff --git a/sources/scala/BufferedIterator.scala b/sources/scala/BufferedIterator.scala
index 9bd7d23e82..7885485e6b 100644
--- a/sources/scala/BufferedIterator.scala
+++ b/sources/scala/BufferedIterator.scala
@@ -1,5 +1,5 @@
package scala;
-trait BufferedIterator[b] extends Iterator[b] {
+trait BufferedIterator[+b] extends Iterator[b] {
def head: b;
}
diff --git a/sources/scala/Cell.scala b/sources/scala/Cell.scala
index 4b3a7273ea..8336704eb7 100644
--- a/sources/scala/Cell.scala
+++ b/sources/scala/Cell.scala
@@ -1,3 +1,2 @@
-package scala {
- case class Cell[T](elem: T)
-} \ No newline at end of file
+package scala;
+case class Cell[+T](elem: T);
diff --git a/sources/scala/Iterator.scala b/sources/scala/Iterator.scala
index 25a1c81308..8325f0e5a6 100644
--- a/sources/scala/Iterator.scala
+++ b/sources/scala/Iterator.scala
@@ -1,6 +1,6 @@
package scala;
-trait Iterator[a] {
+trait Iterator[+a] {
def hasNext: Boolean;
def next: a;
diff --git a/sources/scala/Labelled.scala b/sources/scala/Labelled.scala
index 9967185572..14a8fc2877 100644
--- a/sources/scala/Labelled.scala
+++ b/sources/scala/Labelled.scala
@@ -1,3 +1,3 @@
package scala;
-case class Labelled(symbol: Symbol, elements: List[+Any]) {}
+case class Labelled(symbol: Symbol, elements: List[Any]) {}
diff --git a/sources/scala/List.scala b/sources/scala/List.scala
index e3a099a3e5..29a512a3b1 100644
--- a/sources/scala/List.scala
+++ b/sources/scala/List.scala
@@ -8,7 +8,7 @@ package scala;
*
* @arg a the type of the elements contained in the list.
*/
-trait List[a] extends Seq[a] {
+trait List[+a] extends Seq[a] {
/** Tests if this list is empty.
* @return True iff the list contains no element.
@@ -34,8 +34,8 @@ trait List[a] extends Seq[a] {
* @param x the element to append.
* @return the list with <code>x</code> appended at the beginning.
*/
- def ::(x: a): List[a] =
- new scala.::[a](x, this);
+ def ::[b >: a](x: b): List[b] =
+ new scala.::[b, a](x, this);
/** Returns a list resulting from the concatenation of the given
* list <code>prefix</code> and this list.
@@ -45,9 +45,9 @@ trait List[a] extends Seq[a] {
* @param prefix the list to concatenate at the beginning of this list.
* @return the concatenation of the two lists.
*/
- def :::(prefix: List[a]): List[a] =
+ def :::[b >: a](prefix: List[b]): List[b] =
if (prefix.isEmpty) this
- else prefix.head :: (prefix.tail ::: this);
+ else prefix.head :: prefix.tail ::: this;
/** Returns the number of elements in the list.
* @return the number of elements in the list.
@@ -127,9 +127,9 @@ trait List[a] extends Seq[a] {
* @return the element at position <code>n</code> in this list.
* @throws java.lang.RuntimeException if the list is too short.
*/
- def apply(n: Int) = drop(n).head;
+ def apply(n: Int): a = drop(n).head;
- def at(n: Int) = drop(n).head;
+ def at(n: Int): a = drop(n).head;
/** Returns the list resulting from applying the given function <code>f</code> to each
* element of this list.
@@ -187,21 +187,22 @@ trait List[a] extends Seq[a] {
case x :: xs => xs.foldLeft[b](f(z, x))(f)
}
- def foldLeft_:[b](z: b)(f: (b, a) => b): b = foldLeft(z)(f);
-
def foldRight[b](z: b)(f: (a, b) => b): b = match {
case Nil => z
case x :: xs => f(x, xs.foldRight(z)(f))
}
- def reduceLeft(f: (a, a) => a): a = this match {
+ def /:[b](z: b)(f: (b, a) => b): b = foldLeft(z)(f);
+ def :/[b](z: b)(f: (a, b) => b): b = foldRight(z)(f);
+
+ def reduceLeft[b >: a](f: (b, b) => b): b = this match {
case Nil => error("Nil.reduceLeft")
- case x :: xs => (xs foldLeft x)(f)
+ case x :: xs => ((xs: List[b]) foldLeft (x: b))(f)
}
- def reduceRight(f: (a, a) => a): a = match {
+ def reduceRight[b >: a](f: (b, b) => b): b = match {
case Nil => error("Nil.reduceRight")
- case x :: Nil => x
+ case x :: Nil => x: b
case x :: xs => f(x, xs.reduceRight(f))
}
@@ -254,7 +255,7 @@ trait List[a] extends Seq[a] {
* @return the given array <code>xs</code> filled with this list.
* @throws error if the list is empty.
*/
- def copyToArray(xs: Array[a], start: Int): Array[a] = match {
+ def copyToArray[b >: a](xs: Array[b], start: Int): Array[b] = match {
case Nil => xs
case y :: ys => xs(start) = y; ys.copyToArray(xs, start + 1)
}
@@ -298,7 +299,7 @@ trait List[a] extends Seq[a] {
* @return True iff there is an element of this list which is
* equal (w.r.t. <code>==</code>) to <code>elem</code>.
*/
- def contains(elem: a) = exists(
+ def contains(elem: Any): boolean = exists(
new Object with Function1[a, Boolean] {
def apply(x: a): Boolean = x == elem;
});
@@ -309,11 +310,12 @@ trait List[a] extends Seq[a] {
* @return a list without doubles containing the elements of this
* list and those of the given list <code>that</code>.
*/
- def union(that: List[a]): List[a] =
+ def union[b >: a](that: List[b]): List[b] =
if (this.isEmpty) that
else {
val result = this.tail union that;
- if (that contains this.head) result else this.head :: result;
+ if (that contains this.head) result
+ else this.head :: result
}
/** Computes the difference between this list and the given list
@@ -321,11 +323,12 @@ trait List[a] extends Seq[a] {
* @param that the list of elements to remove from this list.
* @return this list without the elements of the given list <code>that</code>.
*/
- def diff(that: List[a]): List[a] =
- if (this.isEmpty || that.isEmpty) this
+ def diff[b >: a](that: List[b]): List[b] =
+ if (this.isEmpty || that.isEmpty) this: List[b]
else {
val result = this.tail diff that;
- if (that contains this.head) result else this.head :: result;
+ if (that contains this.head) result: List[b]
+ else this.head :: result: List[b]
}
/** Computes the intersection between this list and the given list
@@ -334,7 +337,7 @@ trait List[a] extends Seq[a] {
* @return the list of elements contained both in this list and
* in the given list <code>that</code>.
*/
- def intersect(that: List[a]): List[a] = filter(x => that contains x);
+ def intersect[b >: a](that: List[b]): List[b] = filter(x => that contains x);
/** Removes redundant elements from the list. Uses the method <code>==</code>
* to decide if two elements are identical.
diff --git a/sources/scala/Nil.scala b/sources/scala/Nil.scala
index 09f9bf0bc8..ffede06248 100644
--- a/sources/scala/Nil.scala
+++ b/sources/scala/Nil.scala
@@ -3,10 +3,10 @@ package scala {
/* An empty list. Scala provides <code>[]</code> as syntactic sugar
* for <code>Nil</code>.
*/
- final case class Nil[c] extends List[c] {
+ case object Nil extends List[All] {
def isEmpty = true;
- def head: c = error("head of empty list");
- def tail: List[c] = error("tail of empty list");
+ def head: All = error("head of empty list");
+ def tail: List[All] = error("tail of empty list");
}
}
diff --git a/sources/scala/None.scala b/sources/scala/None.scala
index 767bb80ec8..942bb5a4a6 100644
--- a/sources/scala/None.scala
+++ b/sources/scala/None.scala
@@ -1,7 +1,2 @@
-package scala {
- final case class None[b] extends Option[b] {
- def isNone = true;
- def get: b = error("None does not have an element.");
- override def toString() = "None";
- }
-} \ No newline at end of file
+package scala;
+case object None extends Option[All];
diff --git a/sources/scala/Option.scala b/sources/scala/Option.scala
index 3c7abb7034..3a37835bc5 100644
--- a/sources/scala/Option.scala
+++ b/sources/scala/Option.scala
@@ -1,15 +1,32 @@
package scala {
- trait Option[a] {
+ trait Option[+a] {
- def isNone: Boolean;
- def get: a;
+ def get: a = this match {
+ case None => error("None.get")
+ case Some(x) => x
+ }
def map[b](f: a => b): Option[b] = this match {
case None => None
case Some(x) => Some(f(x))
}
+ def flatMap[b](f: a => Option[b]): Option[b] = this match {
+ case None => None
+ case Some(x) => f(x)
+ }
+
+ def filter(p: a => boolean): Option[a] = this match {
+ case None => None
+ case Some(x) => if (p(x)) Some(x) else None
+ }
+
+ def foreach(f: a => Unit): Unit = this match {
+ case None => ()
+ case Some(x) => f(x)
+ }
+
def toList: List[a] = this match {
case None => Predef.List()
case Some(x) => Predef.List(x)
@@ -18,4 +35,4 @@ package scala {
def print: Unit =
System.out.println(this.toString())
}
-} \ No newline at end of file
+}
diff --git a/sources/scala/PartialFunction.scala b/sources/scala/PartialFunction.scala
index 58e797b3f4..3a5ece7f19 100644
--- a/sources/scala/PartialFunction.scala
+++ b/sources/scala/PartialFunction.scala
@@ -9,7 +9,7 @@
// $Id$
package scala {
- trait PartialFunction[A, +B] {
+ trait PartialFunction[-A, +B] {
def apply(x: A): B;
def isDefinedAt(x: A): scala.Boolean;
}
diff --git a/sources/scala/Seq.scala b/sources/scala/Seq.scala
index 12667a01fc..939373b60c 100644
--- a/sources/scala/Seq.scala
+++ b/sources/scala/Seq.scala
@@ -1,6 +1,6 @@
package scala;
-trait Seq[a] extends scala.Object with Function1[Int, a] {
+trait Seq[+a] extends scala.Object with Function1[Int, a] {
def length: Int;
def elements: Iterator[a];
def apply(index: Int): a;
diff --git a/sources/scala/Some.scala b/sources/scala/Some.scala
index 84df35c8d7..53040fec44 100644
--- a/sources/scala/Some.scala
+++ b/sources/scala/Some.scala
@@ -1,7 +1,3 @@
-package scala {
- final case class Some[c](x: c) extends Option[c] {
- def isNone = false;
- def get: c = x;
- override def toString() = "Some(" + x + ")"
- }
-}
+package scala;
+final case class Some[+c](x: c) extends Option[c];
+
diff --git a/sources/scala/Stream.scala b/sources/scala/Stream.scala
index 461725e53e..7521932d66 100644
--- a/sources/scala/Stream.scala
+++ b/sources/scala/Stream.scala
@@ -1,6 +1,6 @@
package scala;
-trait Stream[a] {
+trait Stream[+a] {
def isEmpty: Boolean;
def head: a;
@@ -59,24 +59,25 @@ trait Stream[a] {
def exists(p: a => Boolean): Boolean =
!isEmpty && (p(head) || tail.exists(p));
- // the next four functions are obsolete!
+ def foldLeft[b](z: b)(f: (b, a) => b): b =
+ if (isEmpty) z
+ else tail.foldLeft[b](f(z, head))(f);
- def reduce(op: (a, a) => a): a =
- if (isEmpty) error("reduce of empty stream")
- else tail.fold(op)(head);
+ def foldRight[b](z: b)(f: (a, b) => b): b =
+ if (isEmpty) z
+ else f(head, tail.foldRight(z)(f));
- def reduceRight(op: (a, a) => a): a =
- if (isEmpty) error("reduce of empty stream")
- else if (tail.isEmpty) head
- else op(head, tail.reduceRight(op));
+ def /:[b](z: b)(f: (b, a) => b): b = foldLeft(z)(f);
+ def :/[b](z: b)(f: (a, b) => b): b = foldRight(z)(f);
- def fold[b](op: (b, a) => b)(z: b): b =
- if (isEmpty) z
- else tail.fold(op)(op(z, head));
+ def reduceLeft[b >: a](f: (b, b) => b): b =
+ if (isEmpty) error("Stream.empty.reduceLeft")
+ else ((tail: Stream[b]) foldLeft (head: b))(f);
- def foldRight[b](op: (a, b) => b)(z: b): b =
- if (isEmpty) z
- else op(head, tail.foldRight(op)(z));
+ def reduceRight[b >: a](f: (b, b) => b): b =
+ if (isEmpty) error("Stream.empty.reduceRight")
+ else if (tail.isEmpty) head: b
+ else f(head, tail.reduceRight(f));
def flatMap[b](f: a => Stream[b]): Stream[b] =
if (isEmpty) Stream.empty[b]
@@ -84,7 +85,7 @@ trait Stream[a] {
def reverse: Stream[a] = {
def snoc(xs: Stream[a], x: a): Stream[a] = Stream.cons(x, xs);
- fold(snoc)(Stream.empty[a])
+ foldLeft(Stream.empty[a])(snoc)
}
// The following method is not compilable without run-time type
@@ -96,7 +97,7 @@ trait Stream[a] {
// xs
// }
- def copyToArray(xs: Array[a], start: Int): Int = {
+ def copyToArray[b >: a](xs: Array[b], start: Int): Int = {
xs(start) = head;
tail.copyToArray(xs, start + 1)
}
diff --git a/sources/scalac/symtab/Symbol.java b/sources/scalac/symtab/Symbol.java
index 53a77fb2bf..4ca5e6501d 100644
--- a/sources/scalac/symtab/Symbol.java
+++ b/sources/scalac/symtab/Symbol.java
@@ -712,7 +712,7 @@ public abstract class Symbol implements Modifiers, Kinds {
/** Get base types of this symbol */
public Type[] parents() {
- return type().parents();
+ return info().parents();
}
// ToString -------------------------------------------------------------------
diff --git a/sources/scalac/symtab/Type.java b/sources/scalac/symtab/Type.java
index bce1cb8ea4..4289498818 100644
--- a/sources/scalac/symtab/Type.java
+++ b/sources/scalac/symtab/Type.java
@@ -1337,8 +1337,8 @@ public class Type implements Modifiers, Kinds, TypeTags {
for (int i = 0; i < these.length; i++) {
if ((tparams[i].flags & COVARIANT) != 0) {
if (!these[i].isSubType(those[i])) return false;
- } else if ((tparams[i].flags & CONTRAVARIANT) != 0) {
- if (!those[i].isSubType(these[i])) return false;
+ //} else if ((tparams[i].flags & CONTRAVARIANT) != 0) {
+ //if (!those[i].isSubType(these[i])) return false;
} else {
if (!these[i].isSameAs(those[i])) return false;
}
@@ -1701,7 +1701,7 @@ public class Type implements Modifiers, Kinds, TypeTags {
}
if (agree) {
Type mintype;
- mintype = commonType(mintypes);
+ mintype = commonType(mintypes);
if (mintype == NoType)
mintype = arglub(mintypes);
if (mintype.symbol().kind == CLASS) {
@@ -1715,6 +1715,9 @@ public class Type implements Modifiers, Kinds, TypeTags {
return result;
}
+ /** same as lub, but all types are instances of the same class,
+ * possibly with different prefixes and arguments.
+ */
//todo: catch lubs not within bounds.
static Type arglub(Type[] types) {
Type pre = types[0].prefix();
@@ -1730,6 +1733,7 @@ public class Type implements Modifiers, Kinds, TypeTags {
if (!pre.isSameAs(pre1)) return NoType;
for (int j = 0; j < args1.length; j++)
argss[j][i] = args1[j];
+ break;
case ErrorType:
return ErrorType;
default:
@@ -1768,45 +1772,45 @@ public class Type implements Modifiers, Kinds, TypeTags {
}
/** Return the least upper bound of non-empty array of types `tps'.
- * todo: do we need to consider refinements as well?
*/
public static Type lub(Type[] tps) {
//System.out.println("lub" + ArrayApply.toString(tps));//DEBUG
- // remove All and AllRef types
- boolean all = false;
- boolean allref = false;
+ // remove types that are subtypes of some other type.
+ Type.List tl = Type.List.EMPTY;
+ int nredundant = 0;
+ boolean[] redundant = new boolean[tps.length];
for (int i = 0; i < tps.length; i++) {
- if (!tps[i].isObjectType()) {
+ if (tps[i] == ErrorType)
+ return ErrorType;
+ else if (!tps[i].isObjectType()) {
System.out.println("not an object type");
return Type.NoType;//todo: change
+ } else {
+ for (int j = 0; j < i && !redundant[i]; j++) {
+ if (!redundant[j]) {
+ if (tps[i].isSubType(tps[j])) {
+ redundant[i] = true;
+ nredundant++;
+ } else if (tps[j].isSubType(tps[i])) {
+ redundant[j] = true;
+ nredundant++;
+ }
+ }
+ }
}
- all |= tps[i].symbol() == Global.instance.definitions.ALL_CLASS;
- allref |= tps[i].symbol() == Global.instance.definitions.ALLREF_CLASS;
}
- if (all | allref) {
- Type.List tl = Type.List.EMPTY;
+ if (nredundant != 0) {
+ Type[] tps1 = new Type[tps.length - nredundant];
+ int n = 0;
for (int i = 0; i < tps.length; i++) {
- if (tps[i].symbol() != Global.instance.definitions.ALL_CLASS &&
- tps[i].symbol() != Global.instance.definitions.ALLREF_CLASS) {
- if (allref &&
- !tps[i].isSubType(Global.instance.definitions.ANYREF_TYPE))
- return Global.instance.definitions.ANY_TYPE;
- else
- tl = new Type.List(tps[i], tl);
- }
- }
- if (tl == Type.List.EMPTY) {
- return allref ? Global.instance.definitions.ALLREF_TYPE
- : Global.instance.definitions.ALL_TYPE;
+ if (!redundant[i]) tps1[n++] = tps[i];
}
- tps = tl.toArrayReverse();
+ tps = tps1;
}
- // fast path if all types agree.
- Type lubType = commonType(tps);
- if (lubType != NoType) return lubType;
+ if (tps.length == 1) return tps[0];
// intersect closures and build frontier.
Type[][] closures = new Type[tps.length][];
@@ -1822,7 +1826,7 @@ public class Type implements Modifiers, Kinds, TypeTags {
// add refinements where necessary
Scope members = new Scope();
- lubType = compoundType(leastBaseTypes, members);
+ Type lubType = compoundType(leastBaseTypes, members);
Type lubThisType = lubType.narrow();
//System.out.println("lubtype = " + lubType);//DEBUG
@@ -1862,8 +1866,8 @@ public class Type implements Modifiers, Kinds, TypeTags {
private static Type commonType(Type[] tps) {
Type tp = tps[0];
if (tp.isSameAsAll(tps)) return tp;
- tp = tp.widen();
- if (tp.isSameAsAll(widen(tps))) return tp;
+ //tp = tp.widen();
+ //if (tp.isSameAsAll(widen(tps))) return tp;
return NoType;
}
diff --git a/sources/scalac/transformer/LambdaLift.java b/sources/scalac/transformer/LambdaLift.java
index 9194c32848..b7a9699e51 100644
--- a/sources/scalac/transformer/LambdaLift.java
+++ b/sources/scalac/transformer/LambdaLift.java
@@ -541,25 +541,19 @@ public class LambdaLift extends OwnerTransformer
}
}
+ //todo: remove type parameters
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);
+ if (start == args.length) return mkNil(pos);
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 mkNil(int pos) {
+ return gen.mkRef(pos, global.definitions.getModule(Names.scala_Nil));
}
Tree mkCons(int pos, Type elemtpe, Tree hd, Tree tl) {
@@ -569,7 +563,7 @@ public class LambdaLift extends OwnerTransformer
gen.mkRef(
pos,
global.definitions.getClass(Names.scala_COLONCOLON).constructor()),
- new Tree[]{gen.mkType(pos, elemtpe)}),
+ new Tree[]{gen.mkType(pos, elemtpe), gen.mkType(pos, elemtpe)}),
new Tree[]{hd, tl}));
}
}
diff --git a/sources/scalac/typechecker/Analyzer.java b/sources/scalac/typechecker/Analyzer.java
index 5190f2da97..f4d2ed8fa0 100644
--- a/sources/scalac/typechecker/Analyzer.java
+++ b/sources/scalac/typechecker/Analyzer.java
@@ -213,9 +213,9 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
// Name resolution -----------------------------------------------------------
String decode(Name name) {
- if (name.isTypeName()) return "type " + name;
- else if (name.isConstrName()) return "constructor " + name;
- else return "value " + name.toString();
+ if (name.isTypeName()) return "type " + NameTransformer.decode(name);
+ else if (name.isConstrName()) return "constructor " + NameTransformer.decode(name);
+ else return "value " + NameTransformer.decode(name);
}
/** Is `sym' accessible as a member of tree `site' in current context?
@@ -692,9 +692,10 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
*/
int flip(Symbol base, Symbol tvar) {
Symbol clazz = tvar.owner().primaryConstructorClass();
- Symbol sym = clazz;
+ Symbol sym = base;
int flip = CoVariance;
while (sym != clazz && flip != AnyVariance) {
+ //System.out.println("flip: " + sym + " " + sym.isParameter());//DEBUG
if (sym.isParameter()) flip = -flip;
else if (sym.owner().kind != CLASS) flip = AnyVariance;
else if (sym.kind == ALIAS) flip = NoVariance;
@@ -723,10 +724,11 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
if (sym.variance() != 0) {
int f = flip(base, sym);
if (f != AnyVariance && sym.variance() != f * variance) {
- error(sym.pos,
+ //System.out.println("flip(" + base + "," + sym + ") = " + f);//DEBUG
+ error(base.pos,
varianceString(sym.variance()) + " " + sym +
- " occurs in " + f * variance +
- " position in type " + all);
+ " occurs in " + varianceString(f * variance) +
+ " position in type " + all + " of " + base);
}
}
validateVariance(base, all, pre, variance);
@@ -753,7 +755,8 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
void validateVariance(Symbol base, Type all, Type[] tps, int variance, Symbol[] tparams) {
for (int i = 0; i < tps.length; i++)
- validateVariance(base, all, tps[i], variance * tparams[i].variance());
+ if (tps[i] != tparams[i].type())
+ validateVariance(base, all, tps[i], variance * tparams[i].variance());
}
// Entering Symbols ----------------------------------------------------------
@@ -1108,8 +1111,6 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
// enter all members
Scope members = new Scope();
pushContext(templ, clazz, members);
- if ((clazz.flags & CASE) != 0)
- templ.body = desugarize.addCaseMethods(templ.body, clazz, parents);
templ.body = desugarize.Statements(templ.body, false);
enterSyms(templ.body);
popContext();
@@ -1954,11 +1955,15 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
case TypeDef(_, _, Tree rhs, Tree lobound):
pushContext(tree, sym, new Scope(context.scope));
int mode = TYPEmode;
- if (sym.kind == ALIAS) mode |= FUNmode;
+ int variance = CoVariance;
+ if (sym.kind == ALIAS) {
+ mode |= FUNmode;
+ variance = NoVariance;
+ }
Tree rhs1 = transform(rhs, mode);
Tree lobound1 = transform(lobound, TYPEmode);
popContext();
- validateVariance(sym, sym.info(), NoVariance);
+ validateVariance(sym, sym.info(), variance);
return copy.TypeDef(tree, sym, rhs1, lobound1)
.setType(definitions.UNIT_TYPE);
diff --git a/sources/scalac/typechecker/DeSugarize.java b/sources/scalac/typechecker/DeSugarize.java
index 07c2e4a234..fdf4b0b542 100644
--- a/sources/scalac/typechecker/DeSugarize.java
+++ b/sources/scalac/typechecker/DeSugarize.java
@@ -701,31 +701,6 @@ public class DeSugarize implements Kinds, Modifiers {
return stats.toArray();
}
- /** Does list of types inherit from class scala.Algebraic?
- */
- boolean inheritsAlgebraic(Type[] tps) {
- Type algebraic = global.definitions.getType(Names.scala_Algebraic);
- for (int i = 0; i < tps.length; i++) {
- if (tps[i].isSubType(algebraic)) return true;
- }
- return false;
- }
-
- /** Add toString, hashCode and == if class inherts from scala.Algebraic.
- */
- Tree[] addCaseMethods(Tree[] body, Symbol clazz, Type[] parents) {
- if (inheritsAlgebraic(parents)) {
- /* todo uncomment and implement
- TreeList stats = new TreeList(body);
- Symbol[] params = clazz.constructor().firstParams();
- stats.append(toStringMethod(clazz, params));
- stats.append(hashcodeMethod(clazz, params));
- stats.append(equalsMethod(clazz, params));
- */
- }
- return body;
- }
-
//debug
void print(Tree tree, String conv, Tree result) {
if (global.log()) {
diff --git a/sources/scalac/typechecker/Infer.java b/sources/scalac/typechecker/Infer.java
index ab8c98e544..0ccbcc1e8d 100644
--- a/sources/scalac/typechecker/Infer.java
+++ b/sources/scalac/typechecker/Infer.java
@@ -214,7 +214,6 @@ public class Infer implements Modifiers, Kinds {
}
}
-
/** Do type arguments `targs' conform to formal parameters `tparams'?
*/
private boolean isWithinBounds(Symbol[] tparams, Type[] targs) {
@@ -298,14 +297,47 @@ public class Infer implements Modifiers, Kinds {
private void minimizeVar(Type tp) {
switch (tp) {
case TypeVar(Type origin, Type.Constraint constr):
- if (constr.inst == Type.NoType && constr.lobounds != Type.List.EMPTY)
- constr.inst = Type.lub(constr.lobounds.toArray());
+ if (constr.inst == Type.NoType)
+ if (constr.lobounds != Type.List.EMPTY) {
+ constr.inst = Type.lub(constr.lobounds.toArray());
+ } else {
+ constr.inst = global.definitions.ALL_TYPE;
+ }
return;
default:
throw new ApplicationError();
}
}
+ private void maximizeVars(Symbol[] tparams, Type[] tvars, int i)
+ throws NoInstance {
+ if (tvars[i] != Type.NoType) {
+ switch (tvars[i]) {
+ case TypeVar(Type origin, Type.Constraint constr):
+ if (constr.inst != Type.NoType) {
+ constr.inst = tvars[i] = instantiate(constr.inst);
+ } else {
+ Type tvar = tvars[i];
+ tvars[i] = Type.NoType;
+ Type bound = tparams[i].info();
+ boolean cyclic = false;
+ for (int j = 0; j < tvars.length; j++) {
+ if (bound.contains(tparams[j])) {
+ cyclic |= tvars[j] == Type.NoType;
+ maximizeVars(tparams, tvars, j);
+ }
+ }
+ if (!cyclic)
+ constr.hibounds = new Type.List(
+ bound.subst(tparams, tvars), constr.hibounds);
+ maximizeVar(tvar);
+ tvars[i] = ((Type.TypeVar) tvar).constr.inst;
+ }
+ if (tvars[i] == Type.AnyType) tvars[i] = definitions.ANY_TYPE;
+ }
+ }
+ }
+
private Type[] freshVars(Symbol[] tparams) {
Type[] tvars = new Type[tparams.length];
for (int i = 0; i < tvars.length; i++) {
@@ -373,7 +405,7 @@ public class Infer implements Modifiers, Kinds {
* If no maximal type variables exists that make the
* instantiated type a subtype of `pt' and `lastTry' is true, return `null'.
*/
- private Type[] instTypeArgs(Symbol[] tparams, Type restype, Type pt) {
+ private Type[] exprTypeArgs(Symbol[] tparams, Type restype, Type pt) {
Type[] tvars = freshVars(tparams);
// add all bounds except F-bounds to upper bounds of type variable.
for (int i = 0; i < tvars.length; i++) {
@@ -389,7 +421,7 @@ public class Infer implements Modifiers, Kinds {
try {
Type[] targs = new Type[tvars.length];
for (int i = 0; i < tvars.length; i++) {
- maximizeVar(tvars[i]);
+ minimizeVar(tvars[i]);
targs[i] = instantiate(tvars[i]);
}
return targs;
@@ -399,7 +431,7 @@ public class Infer implements Modifiers, Kinds {
return null;
}
- /** As before, but: don't maximize. Instead map all unistantiated
+ /** As before, but: don't minimize. Instead map all unistantiated
* type vars to AnyType.
*/
public Type[] protoTypeArgs(Symbol[] tparams, Type restype, Type pt,
@@ -556,7 +588,8 @@ public class Infer implements Modifiers, Kinds {
Type[] targs = new Type[tvars.length];
for (int i = 0; i < tvars.length; i++) {
minimizeVar(tvars[i]);
- targs[i] = (((Type.TypeVar) tvars[i]).constr.inst == Type.NoType)
+ Type instType = ((Type.TypeVar) tvars[i]).constr.inst;
+ targs[i] = (instType == Type.NoType || instType == global.definitions.ALL_TYPE)
? Type.NoType
: instantiate(tvars[i]);
}
@@ -611,9 +644,9 @@ public class Infer implements Modifiers, Kinds {
return argumentTypeInstance(tparams2, restype1, pt1, pt2);
default:
if (tparams.length != 0) {
- Type[] targs = instTypeArgs(tparams, restype, pt1);
+ Type[] targs = exprTypeArgs(tparams, restype, pt1);
if (targs == null)
- targs = instTypeArgs(tparams, restype, pt2);
+ targs = exprTypeArgs(tparams, restype, pt2);
if (targs == null)
throw new Type.Error(
typeErrorMsg(
@@ -639,7 +672,7 @@ public class Infer implements Modifiers, Kinds {
System.arraycopy(tparams1, 0, tparams2, tparams.length, tparams1.length);
return exprInstance(tree, tparams2, restype1, pt);
}
- Type[] targs = instTypeArgs(tparams, restype, pt);
+ Type[] targs = exprTypeArgs(tparams, restype, pt);
if (targs == null)
throw new Type.Error(
"polymorphic expression of type " + tree.type +
@@ -703,23 +736,20 @@ public class Infer implements Modifiers, Kinds {
Type restype1 = restype.subst(tparams, tvars);
Type ctpe1 = restype1.resultType();
if (ctpe1.isSubType(pt)) {
- Type[] targs = new Type[tparams.length];
- for (int i = 0; i < tvars.length; i++) {
- try {
- targs[i] = instantiateUpper(tvars[i], true);
- if (targs[i] == Type.AnyType)
- targs[i] = definitions.ANY_TYPE;
- } catch (NoInstance ex) {
- throw new Type.Error(
- "constructor of type " + ctpe1 +
- " can be instantiated in more than one way to expected type " +
- pt +
- "\n --- because ---\n" + ex.getMessage());
+ try {
+ for (int i = 0; i < tvars.length; i++) {
+ maximizeVars(tparams, tvars, i);
}
+ checkBounds(tparams, tvars, "inferred ");
+ tree.setType(restype.subst(tparams, tvars));
+ //System.out.println("inferred constructor type: " + tree.type);//DEBUG
+ } catch (NoInstance ex) {
+ throw new Type.Error(
+ "constructor of type " + ctpe1 +
+ " can be instantiated in more than one way to expected type " +
+ pt +
+ "\n --- because ---\n" + ex.getMessage());
}
- checkBounds(tparams, targs, "inferred ");
- tree.setType(restype.subst(tparams, targs));
- //System.out.println("inferred constructor type: " + tree.type);//DEBUG
} else {
throw new Type.Error(
typeErrorMsg(
@@ -749,7 +779,7 @@ public class Infer implements Modifiers, Kinds {
Symbol[] uninstantiated = normalizeArgs(targs, tparams);
return
isWithinBounds(tparams, targs) &&
- instTypeArgs(uninstantiated, restpe.subst(tparams, targs), pt)
+ exprTypeArgs(uninstantiated, restpe.subst(tparams, targs), pt)
!= null;
}
} catch (NoInstance ex) {