From 6f062616e25ccc18848b0e86ba999202bc20a6a2 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Thu, 8 May 2003 14:53:48 +0000 Subject: *** empty log message *** --- sources/meta/scala/MetaFunction.java | 2 +- sources/meta/scala/MetaTuple.java | 2 +- sources/scala/$colon$colon.scala | 8 +-- sources/scala/BufferedIterator.scala | 2 +- sources/scala/Cell.scala | 5 +- sources/scala/Iterator.scala | 2 +- sources/scala/Labelled.scala | 2 +- sources/scala/List.scala | 45 ++++++++-------- sources/scala/Nil.scala | 6 +-- sources/scala/None.scala | 9 +--- sources/scala/Option.scala | 25 +++++++-- sources/scala/PartialFunction.scala | 2 +- sources/scala/Seq.scala | 2 +- sources/scala/Some.scala | 10 ++-- sources/scala/Stream.scala | 35 ++++++------- sources/scalac/symtab/Symbol.java | 2 +- sources/scalac/symtab/Type.java | 66 +++++++++++++----------- sources/scalac/transformer/LambdaLift.java | 16 ++---- sources/scalac/typechecker/Analyzer.java | 29 ++++++----- sources/scalac/typechecker/DeSugarize.java | 25 --------- sources/scalac/typechecker/Infer.java | 82 ++++++++++++++++++++---------- 21 files changed, 198 insertions(+), 179 deletions(-) (limited to 'sources') 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 x 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 prefix 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 n 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 f 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 xs 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. ==) to elem. */ - 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 that. */ - 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 that. */ - 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 that. */ - 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 == * 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 [] as syntactic sugar * for Nil. */ - 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) { -- cgit v1.2.3