summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Namers.scala60
-rwxr-xr-xsrc/library/scalax/collection/generic/MutableVectorView.scala2
-rwxr-xr-xsrc/library/scalax/collection/generic/OrderedIterableView.scala2
-rwxr-xr-xsrc/library/scalax/collection/generic/SequenceView.scala2
-rwxr-xr-xsrc/library/scalax/collection/generic/covartest/SequenceView.scala2
-rw-r--r--src/library/scalax/collection/immutable/HashMap.scala8
-rw-r--r--src/library/scalax/collection/mutable/ArrayBuffer.scala2
-rw-r--r--src/library/scalax/collection/mutable/ListBuffer.scala107
-rwxr-xr-xsrc/library/scalax/collection/mutable/Map.scala2
-rw-r--r--test/files/neg/bug692.check16
-rw-r--r--test/files/pos/cyclics.scala23
-rw-r--r--test/files/run/constrained-types.check2
12 files changed, 145 insertions, 83 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
index 6e648371ea..cd51fbce5f 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
@@ -21,28 +21,27 @@ trait Namers { self: Analyzer =>
import definitions._
import posAssigner.atPos
- /** Convert to corresponding type parameters all skolems which satisfy one
- * of the following two conditions:
- * 1. The skolem is a parameter of a class or alias type
- * 2. The skolem is a method parameter which appears in parameter `tparams'
+ /** Convert to corresponding type parameters all skolems of method parameters
+ * which appear in `tparams`.
*/
class DeSkolemizeMap(tparams: List[Symbol]) extends TypeMap {
- def apply(tp: Type): Type = if (tparams.isEmpty) tp
- else {
- tp match {
- case TypeRef(pre, sym, args)
- if (sym.isTypeSkolem && (tparams contains sym.deSkolemize)) =>
- mapOver(rawTypeRef(NoPrefix, sym.deSkolemize, args))
- case PolyType(tparams1, restpe) =>
- new DeSkolemizeMap(tparams1 ::: tparams).mapOver(tp)
- case ClassInfoType(parents, decls, clazz) =>
- val parents1 = List.mapConserve(parents)(this)
+ def apply(tp: Type): Type = tp match {
+ case TypeRef(pre, sym, args)
+ if (sym.isTypeSkolem && (tparams contains sym.deSkolemize)) =>
+// println("DESKOLEMIZING "+sym+" in "+sym.owner)
+ mapOver(rawTypeRef(NoPrefix, sym.deSkolemize, args))
+/*
+ case PolyType(tparams1, restpe) =>
+ new DeSkolemizeMap(tparams1 ::: tparams).mapOver(tp)
+ case ClassInfoType(parents, decls, clazz) =>
+ val parents1 = List.mapConserve(parents)(this)
if (parents1 eq parents) tp else ClassInfoType(parents1, decls, clazz)
- case _ =>
- mapOver(tp)
- }
+*/
+ case _ =>
+ mapOver(tp)
}
}
+
private class NormalNamer(context : Context) extends Namer(context)
def newNamer(context : Context) : Namer = new NormalNamer(context)
@@ -273,8 +272,9 @@ trait Namers { self: Analyzer =>
tskolems foreach (_.setInfo(ltp))
tskolems
}
+
/** Replace type parameters with their TypeSkolems, which can later be deskolemized to the original type param
- * (a skolem is a representation of a bound variable when viewed outside its scope)
+ * (a skolem is a representation of a bound variable when viewed inside its scope)
*/
def skolemize(tparams: List[TypeDef]) {
val tskolems = newTypeSkolems(tparams map (_.symbol))
@@ -286,9 +286,6 @@ trait Namers { self: Analyzer =>
else if (owner.isTerm || owner.isPackageClass) List()
else applicableTypeParams(owner.owner) ::: owner.typeParams
- def deSkolemize: TypeMap = new DeSkolemizeMap(applicableTypeParams(context.owner))
- // should be special path for IDE but maybe not....
-
def enterSym(tree: Tree): Context = try {
def finishWith(tparams: List[TypeDef]) {
@@ -921,7 +918,26 @@ trait Namers { self: Analyzer =>
typer.reportTypeError(tree.pos, ex)
ErrorType
}
- deSkolemize(result)
+ result match {
+ case PolyType(tparams, restpe)
+ if (!tparams.isEmpty && tparams.head.owner.isTerm ||
+ // Adriaan: The added conditon below is quite a hack. It seems that HK type parameters is relying
+ // on a pass that forces all infos in the type to get everything right.
+ // The problem is that the same pass causes cyclic reference errors in
+ // test pos/cyclics.scala. It turned out that deSkolemize is run way more often than necessary,
+ // ruinning it only when needed fixes the cuclic reference errors.
+ // But correcting deSkolemize broke HK types, because we don't do the traversal anymore.
+ // For the moment I made a special hack to do the traversal if we have HK type parameters.
+ // Maybe it's not a hack, then we need to document it better. But ideally, we should find
+ // a way to deal with HK types that's not dependent on accidental side
+ // effects like this.
+ tparams.exists(!_.typeParams.isEmpty)) =>
+ new DeSkolemizeMap(tparams) mapOver result
+ case _ =>
+// println("not skolemizing "+result+" in "+context.owner)
+// new DeSkolemizeMap(List()) mapOver result
+ result
+ }
}
/** Check that symbol's definition is well-formed. This means:
diff --git a/src/library/scalax/collection/generic/MutableVectorView.scala b/src/library/scalax/collection/generic/MutableVectorView.scala
index 450943f61d..d445ba336e 100755
--- a/src/library/scalax/collection/generic/MutableVectorView.scala
+++ b/src/library/scalax/collection/generic/MutableVectorView.scala
@@ -25,6 +25,8 @@ self =>
/** refined from Iterable.View */
val origin: Vector[_]
+ override def newBuilder[A] = underlying.newBuilder[A].asInstanceOf[Builder[Vector, A]]
+
trait Transformed[B] extends super.Transformed[B] with MutableVectorView[UC, B] {
override val origin = self
override def elements: Iterator[B] = new Elements(0, length)
diff --git a/src/library/scalax/collection/generic/OrderedIterableView.scala b/src/library/scalax/collection/generic/OrderedIterableView.scala
index fd04daa0b6..9f0d981f54 100755
--- a/src/library/scalax/collection/generic/OrderedIterableView.scala
+++ b/src/library/scalax/collection/generic/OrderedIterableView.scala
@@ -19,6 +19,8 @@ trait OrderedIterableView[+UC[/*+*/B] <: Iterable[B], /*+*/A] extends IterableVi
val origin: OrderedIterable[_]
+ override def newBuilder[A] = underlying.newBuilder[A].asInstanceOf[Builder[OrderedIterable, A]]
+
/** Builds a new view object. This method needs to be overridden in subclasses
* which refine in IterableView type
*/
diff --git a/src/library/scalax/collection/generic/SequenceView.scala b/src/library/scalax/collection/generic/SequenceView.scala
index aa6f1e50f8..4f70f8a9d8 100755
--- a/src/library/scalax/collection/generic/SequenceView.scala
+++ b/src/library/scalax/collection/generic/SequenceView.scala
@@ -27,6 +27,8 @@ self =>
/** refined from Iterable.View */
val origin: Sequence[_]
+ override def newBuilder[A] = underlying.newBuilder[A].asInstanceOf[Builder[Sequence, A]]
+
trait Transformed[/*+*/B] extends SequenceView[UC, B] {
val origin = self
protected def asCC = asInstanceOf[SequenceView[UC, B]]
diff --git a/src/library/scalax/collection/generic/covartest/SequenceView.scala b/src/library/scalax/collection/generic/covartest/SequenceView.scala
index 77b06b0b4f..e99ffaf652 100755
--- a/src/library/scalax/collection/generic/covartest/SequenceView.scala
+++ b/src/library/scalax/collection/generic/covartest/SequenceView.scala
@@ -27,6 +27,8 @@ self =>
/** refined from Iterable.View */
val origin: Sequence[_]
+ override def newBuilder[A] = underlying.newBuilder[A].asInstanceOf[Builder[Sequence, A]]
+
trait Transformed[+B] extends SequenceView[UC, B] {
val origin = self
protected def asCC = asInstanceOf[SequenceView[UC, B]]
diff --git a/src/library/scalax/collection/immutable/HashMap.scala b/src/library/scalax/collection/immutable/HashMap.scala
index 7d3595904d..8aaa0239c1 100644
--- a/src/library/scalax/collection/immutable/HashMap.scala
+++ b/src/library/scalax/collection/immutable/HashMap.scala
@@ -37,15 +37,17 @@ object HashMap extends MapFactory[HashMap] {
@serializable
class HashMap[A, B] extends Map[A,B]
with MapTemplate[A, B, HashMap]
- with mutable.HashTable[A] {
+ with collection.mutable.HashTable[A] {
- type Entry = mutable.DefaultEntry[A, Any]
+ type Entry = collection.mutable.DefaultEntry[A, Any]
protected var later: HashMap[A, B] = null
protected var oldKey: A = _
protected var oldValue: Option[B] = _
protected var deltaSize: Int = _
+ override def empty[B] = HashMap.empty[A, B]
+
def get(key: A): Option[B] = synchronized {
var m = this
var cnt = 0
@@ -141,7 +143,7 @@ class HashMap[A, B] extends Map[A,B]
}
val ltable = last.table
val s = ltable.length
- table = new scala.Array[mutable.HashEntry[A, Entry]](s)
+ table = new scala.Array[collection.mutable.HashEntry[A, Entry]](s)
var i = 0
while (i < s) {
table(i) = copy(ltable(i).asInstanceOf[Entry])
diff --git a/src/library/scalax/collection/mutable/ArrayBuffer.scala b/src/library/scalax/collection/mutable/ArrayBuffer.scala
index daf514c485..1692280e21 100644
--- a/src/library/scalax/collection/mutable/ArrayBuffer.scala
+++ b/src/library/scalax/collection/mutable/ArrayBuffer.scala
@@ -39,6 +39,8 @@ class ArrayBuffer[A](override protected val initialSize: Int)
def clear() { reduceToSize(0) }
+ override def newBuilder[B]: Builder[ArrayBuffer, B] = new ArrayBuffer[B]
+
/** Appends a single element to this buffer and returns
* the identity of the buffer. It takes constant time.
*
diff --git a/src/library/scalax/collection/mutable/ListBuffer.scala b/src/library/scalax/collection/mutable/ListBuffer.scala
index 4d0ad7ec80..faf897aef2 100644
--- a/src/library/scalax/collection/mutable/ListBuffer.scala
+++ b/src/library/scalax/collection/mutable/ListBuffer.scala
@@ -41,9 +41,17 @@ final class ListBuffer[A]
private var start: List[A] = Nil
private var last0: ::[A] = _
private var exported: Boolean = false
+ private var len = 0
protected def underlying: Sequence[A] = start
+ override def newBuilder[B]: Builder[ListBuffer, B] =
+ new AddableBuilder[ListBuffer, B](new ListBuffer[B]) // !!! Adriaan: inference failure here
+
+ /** The current length of the buffer
+ */
+ override def length = len
+
// Implementations of abstract methods in Buffer
/** Replaces element at index <code>n</code> with the new element
@@ -59,7 +67,10 @@ final class ListBuffer[A]
if (exported) copy()
if (n == 0) {
val newElem = new :: (x, start.tail);
- if (last0 eq start) last0 = newElem
+ if (last0 eq start) {
+ last0 = newElem
+ len += 1
+ }
start = newElem
} else {
var cursor = start
@@ -69,7 +80,10 @@ final class ListBuffer[A]
i += 1
}
val newElem = new :: (x, cursor.tail.tail)
- if (last0 eq cursor.tail) last0 = newElem
+ if (last0 eq cursor.tail) {
+ last0 = newElem
+ len += 1
+ }
cursor.asInstanceOf[::[A]].tl = newElem
}
} catch {
@@ -91,6 +105,7 @@ final class ListBuffer[A]
last0 = new :: (x, Nil)
last1.tl = last0
}
+ len += 1
}
/** Clears the buffer contents.
@@ -98,6 +113,7 @@ final class ListBuffer[A]
def clear() {
start = Nil
exported = false
+ len = 0
}
/** Prepends a single element to this buffer. This operation takes constant
@@ -111,6 +127,7 @@ final class ListBuffer[A]
val newElem = new :: (x, start)
if (start.isEmpty) last0 = newElem
start = newElem
+ len += 1
this
}
@@ -126,6 +143,7 @@ final class ListBuffer[A]
try {
if (exported) copy()
var elems = iter.elements.toList.reverse
+ len += elems.length
if (n == 0) {
while (!elems.isEmpty) {
val newElem = new :: (elems.head, start)
@@ -153,42 +171,39 @@ final class ListBuffer[A]
}
}
- /** Removes the element on a given index position. This operation takes time linear in
+ /** Removes a given number of elements on a given index position. May take time linear in
* the buffer size.
*
- * @param n the index which refers to the element to delete.
- * @return the updated array buffer.
- * @throws Predef.IndexOutOfBoundsException if <code>n</code> is out of bounds.
+ * @param n the index which refers to the first element to remove.
+ * @param count the number of elements to remove.
*/
def remove(n: Int, count: Int) {
- try {
- if (exported) copy()
- var old = start.head;
- if (n == 0) {
- var c = count
- while (c > 0) {
- start = start.tail
- c -= 1
- }
- } else {
- var cursor = start
- var i = 1
- while (i < n) {
- cursor = cursor.tail
- i += 1
- }
- var c = count
- while (c > 0) {
- if (last0 eq cursor.tail) last0 = cursor.asInstanceOf[::[A]]
- cursor.asInstanceOf[::[A]].tl = cursor.tail.tail
- c -= 1
- }
+ if (exported) copy()
+ val n1 = n max 0
+ val count1 = count min (len - n1)
+ var old = start.head;
+ if (n1 == 0) {
+ var c = count1
+ while (c > 0) {
+ start = start.tail
+ c -= 1
}
- old
- } catch {
- case ex: Exception =>
- throw new IndexOutOfBoundsException(n.toString())
- } }
+ } else {
+ var cursor = start
+ var i = 1
+ while (i < n1) {
+ cursor = cursor.tail
+ i += 1
+ }
+ var c = count1
+ while (c > 0) {
+ if (last0 eq cursor.tail) last0 = cursor.asInstanceOf[::[A]]
+ cursor.asInstanceOf[::[A]].tl = cursor.tail.tail
+ c -= 1
+ }
+ }
+ len -= count1
+ }
// Implementation of abstract method in Builder
@@ -214,9 +229,8 @@ final class ListBuffer[A]
// Overrides of methods in Buffer
- /** Removes the element on a given index position. Takes time linear in
- * the buffer size (except for the first element, which is removed in constant
- * time).
+ /** Removes the element on a given index position. May take time linear in
+ * the buffer size
*
* @param n the index which refers to the element to delete.
* @return n the element that was formerly at position <code>n</code>.
@@ -224,6 +238,7 @@ final class ListBuffer[A]
* @throws Predef.IndexOutOfBoundsException if <code>n</code> is out of bounds.
*/
override def remove(n: Int): A = try {
+ if (n < 0 || n >= len) throw new IndexOutOfBoundsException(n.toString())
if (exported) copy()
var old = start.head;
if (n == 0) {
@@ -239,29 +254,31 @@ final class ListBuffer[A]
if (last0 eq cursor.tail) last0 = cursor.asInstanceOf[::[A]]
cursor.asInstanceOf[::[A]].tl = cursor.tail.tail
}
+ len -= 1
old
- } catch {
- case ex: Exception =>
- throw new IndexOutOfBoundsException(n.toString())
}
- /** Remove a single element from this buffer. This operation takes linear time
- * (except removing the first element, which is done in constant time).
+ /** Remove a single element from this buffer. May take time linear in the buffer size.
*
* @param x the element to remove.
*/
- override def -= (x: A) {
+ override def -= (elem: A) {
if (exported) copy()
if (start.isEmpty) {}
- else if (start.head == x) start = start.tail
- else {
+ else if (start.head == elem) {
+ start = start.tail
+ len -= 1
+ } else {
var cursor = start
- while (!cursor.tail.isEmpty && cursor.tail.head != x) { cursor = cursor.tail }
+ while (!cursor.tail.isEmpty && cursor.tail.head != elem) {
+ cursor = cursor.tail
+ }
if (!cursor.tail.isEmpty) {
val z = cursor.asInstanceOf[::[A]]
if (z.tl == last0)
last0 = z
z.tl = cursor.tail.tail
+ len -= 1
}
}
}
diff --git a/src/library/scalax/collection/mutable/Map.scala b/src/library/scalax/collection/mutable/Map.scala
index 43f42df298..82fb6a5680 100755
--- a/src/library/scalax/collection/mutable/Map.scala
+++ b/src/library/scalax/collection/mutable/Map.scala
@@ -26,8 +26,6 @@ trait Map[A, B]
with Cloneable[Map[A, B]] {
self =>
- override def thisCC: Map[A, B] = this
-
/** This method allows one to add a new mapping from <code>key</code>
* to <code>value</code> to the map. If the map already contains a
* mapping for <code>key</code>, it will be overridden by this
diff --git a/test/files/neg/bug692.check b/test/files/neg/bug692.check
index 099a261f42..14df1917d9 100644
--- a/test/files/neg/bug692.check
+++ b/test/files/neg/bug692.check
@@ -1,19 +1,19 @@
bug692.scala:3: error: not found: type T
- trait Type[T0] extends Type0[T];
+ trait Type[T0] extends Type0[T];
^
bug692.scala:10: error: class Foo takes type parameters
- case class FooType() extends ClassType[Foo,AnyRef](ObjectType());
+ case class FooType() extends ClassType[Foo,AnyRef](ObjectType());
^
bug692.scala:13: error: class Foo takes type parameters
- case class BarType[T3 <: Foo](tpeT : RefType[T3]) extends ClassType[Bar[T3],Foo](FooType);
+ case class BarType[T3 <: Foo](tpeT : RefType[T3]) extends ClassType[Bar[T3],Foo](FooType);
^
bug692.scala:13: error: class Foo takes type parameters
- case class BarType[T3 <: Foo](tpeT : RefType[T3]) extends ClassType[Bar[T3],Foo](FooType);
+ case class BarType[T3 <: Foo](tpeT : RefType[T3]) extends ClassType[Bar[T3],Foo](FooType);
^
-bug692.scala:19: error: class Foo takes type parameters
- class Bar[A <: Foo](implicit tpeA : Type[A]) extends Foo;
- ^
bug692.scala:14: error: class Foo takes type parameters
- implicit def typeOfBar[T4 <: Foo](implicit elem : RefType[T4]) : RefType[Bar[T4]] =
+ implicit def typeOfBar[T4 <: Foo](implicit elem : RefType[T4]) : RefType[Bar[T4]] =
^
+bug692.scala:19: error: class Foo takes type parameters
+ class Bar[A <: Foo](implicit tpeA : Type[A]) extends Foo;
+ ^
6 errors found
diff --git a/test/files/pos/cyclics.scala b/test/files/pos/cyclics.scala
index 69092ce7ab..a49f4faaca 100644
--- a/test/files/pos/cyclics.scala
+++ b/test/files/pos/cyclics.scala
@@ -1,7 +1,26 @@
trait Param[T]
trait Abs { type T }
trait Cyclic1[A <: Param[A]] // works
-trait Cyclic2[A <: Abs { type T <: A }] // fails
-trait Cyclic3 { type A <: Abs { type T = A } } // fails
+trait Cyclic2[A <: Abs { type T <: A }]
+trait Cyclic3 { type A <: Abs { type T = A } }
trait Cyclic4 { type A <: Param[A] } // works
+trait Cyclic5 { type AA <: Abs; type A <: AA { type T = A } }
+
+trait IterableTemplate {
+ type Elem
+ type Constr <: IterableTemplate
+ type ConstrOf[A] = Constr { type Elem = A }
+
+ def elements: Iterator[Elem]
+
+ def map [B] (f: Elem => B): ConstrOf[B]
+
+ def foreach(f: Elem => Unit) = elements.foreach(f)
+}
+
+
+trait Iterable[A] extends IterableTemplate { self =>
+ type Elem
+ type Constr <: Iterable[A] { type Constr <: Iterable.this.Constr }
+}
diff --git a/test/files/run/constrained-types.check b/test/files/run/constrained-types.check
index c8f0a83ad3..d3c32b7a02 100644
--- a/test/files/run/constrained-types.check
+++ b/test/files/run/constrained-types.check
@@ -85,7 +85,7 @@ defined class peer
-----
class NPE[T <: NPE[T] @peer] // should not crash
-error: illegal cyclic reference involving class NPE
+defined class NPE
-----
def m = {