diff options
Diffstat (limited to 'src')
9 files changed, 115 insertions, 72 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 |