Skip to content

Commit f5baf26

Browse files
authored
Merge pull request scala#6648 from szeiger/issue/10851
Remove element type from mutable.ArraySeq.(elemTag|array)
2 parents 6b988b1 + 1e21c91 commit f5baf26

File tree

5 files changed

+86
-36
lines changed

5 files changed

+86
-36
lines changed

src/library/scala/collection/ArrayOps.scala

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1362,7 +1362,7 @@ final class ArrayOps[A](val xs: Array[A]) extends AnyVal {
13621362
* ''n'' times in `that`, then the first ''n'' occurrences of `x` will not form
13631363
* part of the result, but any following occurrences will.
13641364
*/
1365-
def diff(that: Seq[_ >: A]): Array[A] = mutable.ArraySeq.make(xs).diff(that).array
1365+
def diff(that: Seq[_ >: A]): Array[A] = mutable.ArraySeq.make(xs).diff(that).array.asInstanceOf[Array[A]]
13661366

13671367
/** Computes the multiset intersection between this array and another sequence.
13681368
*
@@ -1373,7 +1373,7 @@ final class ArrayOps[A](val xs: Array[A]) extends AnyVal {
13731373
* ''n'' times in `that`, then the first ''n'' occurrences of `x` will be retained
13741374
* in the result, but any following occurrences will be omitted.
13751375
*/
1376-
def intersect(that: Seq[_ >: A]): Array[A] = mutable.ArraySeq.make(xs).intersect(that).array
1376+
def intersect(that: Seq[_ >: A]): Array[A] = mutable.ArraySeq.make(xs).intersect(that).array.asInstanceOf[Array[A]]
13771377

13781378
/** Groups chars in fixed size blocks by passing a "sliding window"
13791379
* over them (as opposed to partitioning them, as is done in grouped.)
@@ -1385,7 +1385,7 @@ final class ArrayOps[A](val xs: Array[A]) extends AnyVal {
13851385
* last element (which may be the only element) will be truncated
13861386
* if there are fewer than `size` chars remaining to be grouped.
13871387
*/
1388-
def sliding(size: Int, step: Int = 1): Iterator[Array[A]] = mutable.ArraySeq.make(xs).sliding(size, step).map(_.array)
1388+
def sliding(size: Int, step: Int = 1): Iterator[Array[A]] = mutable.ArraySeq.make(xs).sliding(size, step).map(_.array.asInstanceOf[Array[A]])
13891389

13901390
/** Iterates over combinations. A _combination_ of length `n` is a subsequence of
13911391
* the original string, with the chars taken in order. Thus, `"xy"` and `"yy"`
@@ -1400,14 +1400,14 @@ final class ArrayOps[A](val xs: Array[A]) extends AnyVal {
14001400
* @return An Iterator which traverses the possible n-element combinations of this string.
14011401
* @example `"abbbc".combinations(2) = Iterator(ab, ac, bb, bc)`
14021402
*/
1403-
def combinations(n: Int): Iterator[Array[A]] = mutable.ArraySeq.make(xs).combinations(n).map(_.array)
1403+
def combinations(n: Int): Iterator[Array[A]] = mutable.ArraySeq.make(xs).combinations(n).map(_.array.asInstanceOf[Array[A]])
14041404

14051405
/** Iterates over distinct permutations.
14061406
*
14071407
* @return An Iterator which traverses the distinct permutations of this string.
14081408
* @example `"abb".permutations = Iterator(abb, bab, bba)`
14091409
*/
1410-
def permutations: Iterator[Array[A]] = mutable.ArraySeq.make(xs).permutations.map(_.array)
1410+
def permutations: Iterator[Array[A]] = mutable.ArraySeq.make(xs).permutations.map(_.array.asInstanceOf[Array[A]])
14111411

14121412
// we have another overload here, so we need to duplicate this method
14131413
/** Tests whether this array contains the given sequence at a given index.

src/library/scala/collection/immutable/ArraySeq.scala

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -25,20 +25,22 @@ sealed abstract class ArraySeq[+A]
2525
with IndexedSeqOps[A, ArraySeq, ArraySeq[A]]
2626
with StrictOptimizedSeqOps[A, ArraySeq, ArraySeq[A]] {
2727

28-
/** The tag of the element type */
29-
protected def elemTag: ClassTag[A] @uncheckedVariance
28+
/** The tag of the element type. This does not have to be equal to the element type of this ArraySeq. A primitive
29+
* ArraySeq can be backed by an array of boxed values and a reference ArraySeq can be backed by an array of a supertype
30+
* or subtype of the element type. */
31+
protected def elemTag: ClassTag[_]
3032

3133
override def iterableFactory: SeqFactory[ArraySeq] = ArraySeq.untagged
3234

3335
/** The wrapped mutable `Array` that backs this `ArraySeq`. Any changes to this array will break
34-
* the expected immutability. */
35-
def unsafeArray: Array[A @uncheckedVariance]
36-
// uncheckedVariance should be safe: Array[A] for reference types A is covariant at the JVM level. Array[A] for
37-
// primitive types A can only be widened to Array[Any] which erases to Object.
36+
* the expected immutability. Its element type does not have to be equal to the element type of this ArraySeq.
37+
* A primitive ArraySeq can be backed by an array of boxed values and a reference ArraySeq can be backed by an
38+
* array of a supertype or subtype of the element type. */
39+
def unsafeArray: Array[_]
3840

39-
override protected def fromSpecificIterable(coll: scala.collection.Iterable[A] @uncheckedVariance): ArraySeq[A] = ArraySeq.from[A](coll)(elemTag)
41+
override protected def fromSpecificIterable(coll: scala.collection.Iterable[A] @uncheckedVariance): ArraySeq[A] = ArraySeq.from(coll)(elemTag.asInstanceOf[ClassTag[A]])
4042

41-
override protected def newSpecificBuilder: Builder[A, ArraySeq[A]] @uncheckedVariance = ArraySeq.newBuilder[A](elemTag)
43+
override protected def newSpecificBuilder: Builder[A, ArraySeq[A]] @uncheckedVariance = ArraySeq.newBuilder[A](elemTag.asInstanceOf[ClassTag[A]])
4244

4345
@throws[ArrayIndexOutOfBoundsException]
4446
def apply(i: Int): A
@@ -95,19 +97,19 @@ sealed abstract class ArraySeq[+A]
9597
fromIterable(new View.Zip(toIterable, that))
9698
}
9799

98-
override def take(n: Int): ArraySeq[A] = ArraySeq.unsafeWrapArray(new ArrayOps(unsafeArray).take(n))
100+
override def take(n: Int): ArraySeq[A] = ArraySeq.unsafeWrapArray(new ArrayOps(unsafeArray).take(n)).asInstanceOf[ArraySeq[A]]
99101

100-
override def takeRight(n: Int): ArraySeq[A] = ArraySeq.unsafeWrapArray(new ArrayOps(unsafeArray).takeRight(n))
102+
override def takeRight(n: Int): ArraySeq[A] = ArraySeq.unsafeWrapArray(new ArrayOps(unsafeArray).takeRight(n)).asInstanceOf[ArraySeq[A]]
101103

102-
override def drop(n: Int): ArraySeq[A] = ArraySeq.unsafeWrapArray(new ArrayOps(unsafeArray).drop(n))
104+
override def drop(n: Int): ArraySeq[A] = ArraySeq.unsafeWrapArray(new ArrayOps(unsafeArray).drop(n)).asInstanceOf[ArraySeq[A]]
103105

104-
override def dropRight(n: Int): ArraySeq[A] = ArraySeq.unsafeWrapArray(new ArrayOps(unsafeArray).dropRight(n))
106+
override def dropRight(n: Int): ArraySeq[A] = ArraySeq.unsafeWrapArray(new ArrayOps(unsafeArray).dropRight(n)).asInstanceOf[ArraySeq[A]]
105107

106-
override def slice(from: Int, until: Int): ArraySeq[A] = ArraySeq.unsafeWrapArray(new ArrayOps(unsafeArray).slice(from, until))
108+
override def slice(from: Int, until: Int): ArraySeq[A] = ArraySeq.unsafeWrapArray(new ArrayOps(unsafeArray).slice(from, until)).asInstanceOf[ArraySeq[A]]
107109

108-
override def tail: ArraySeq[A] = ArraySeq.unsafeWrapArray(new ArrayOps(unsafeArray).tail)
110+
override def tail: ArraySeq[A] = ArraySeq.unsafeWrapArray(new ArrayOps(unsafeArray).tail).asInstanceOf[ArraySeq[A]]
109111

110-
override def reverse: ArraySeq[A] = ArraySeq.unsafeWrapArray(new ArrayOps(unsafeArray).reverse)
112+
override def reverse: ArraySeq[A] = ArraySeq.unsafeWrapArray(new ArrayOps(unsafeArray).reverse).asInstanceOf[ArraySeq[A]]
111113

112114
override def className = "ArraySeq"
113115

src/library/scala/collection/mutable/ArraySeq.scala

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -34,22 +34,26 @@ abstract class ArraySeq[T]
3434
override def iterableFactory: scala.collection.SeqFactory[ArraySeq] = ArraySeq.untagged
3535

3636
override protected def fromSpecificIterable(coll: scala.collection.Iterable[T]): ArraySeq[T] = {
37-
val b = ArrayBuilder.make(elemTag)
37+
val b = ArrayBuilder.make(elemTag).asInstanceOf[ArrayBuilder[T]]
3838
val s = coll.knownSize
3939
if(s > 0) b.sizeHint(s)
4040
b ++= coll
4141
ArraySeq.make(b.result())
4242
}
43-
override protected def newSpecificBuilder: Builder[T, ArraySeq[T]] = ArraySeq.newBuilder(elemTag)
43+
override protected def newSpecificBuilder: Builder[T, ArraySeq[T]] = ArraySeq.newBuilder(elemTag).asInstanceOf[Builder[T, ArraySeq[T]]]
4444

45-
/** The tag of the element type */
46-
def elemTag: ClassTag[T]
45+
/** The tag of the element type. This does not have to be equal to the element type of this ArraySeq. A primitive
46+
* ArraySeq can be backed by an array of boxed values and a reference ArraySeq can be backed by an array of a supertype
47+
* or subtype of the element type. */
48+
def elemTag: ClassTag[_]
4749

4850
/** Update element at given index */
4951
def update(index: Int, elem: T): Unit
5052

51-
/** The underlying array */
52-
def array: Array[T]
53+
/** The underlying array. Its element type does not have to be equal to the element type of this ArraySeq. A primitive
54+
* ArraySeq can be backed by an array of boxed values and a reference ArraySeq can be backed by an array of a supertype
55+
* or subtype of the element type. */
56+
def array: Array[_]
5357

5458
override def toArray[U >: T : ClassTag]: Array[U] = {
5559
val thatElementClass = implicitly[ClassTag[U]].runtimeClass
@@ -62,7 +66,7 @@ abstract class ArraySeq[T]
6266
override def className = "ArraySeq"
6367

6468
/** Clones this object, including the underlying Array. */
65-
override def clone(): ArraySeq[T] = ArraySeq.make(array.clone())
69+
override def clone(): ArraySeq[T] = ArraySeq.make(array.clone()).asInstanceOf[ArraySeq[T]]
6670

6771
override def copyToArray[B >: T](xs: Array[B], start: Int = 0): xs.type = copyToArray[B](xs, start, length)
6872

test/junit/scala/collection/immutable/ArraySeqTest.scala

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
package scala.collection.immutable
22

3-
import org.junit.Assert
3+
import org.junit.Assert._
44
import org.junit.Test
55
import org.junit.runner.RunWith
66
import org.junit.runners.JUnit4
@@ -44,20 +44,26 @@ class ArraySeqTest {
4444

4545
def unit1(): Unit = {}
4646
def unit2(): Unit = {}
47-
Assert.assertEquals(unit1(), unit2())
47+
assertEquals(unit1(), unit2())
4848
// unitArray is actually an instance of Immutable[BoxedUnit], the check to which is actually checked slice
4949
// implementation of ofRef
5050
val unitArray: ArraySeq[Unit] = Array(unit1(), unit2(), unit1(), unit2())
5151
check(unitArray, Array(unit1(), unit1()), Array(unit1(), unit1()))
5252
}
5353

54+
@Test
55+
def t10851(): Unit = {
56+
val s1 = collection.immutable.ArraySeq.untagged(1,2,3)
57+
assertTrue(s1.unsafeArray.getClass == classOf[Array[AnyRef]])
58+
}
59+
5460
private def check[T : ClassTag](array: ArraySeq[T], expectedSliceResult1: ArraySeq[T], expectedSliceResult2: ArraySeq[T]) {
55-
Assert.assertEquals(array, array.slice(-1, 4))
56-
Assert.assertEquals(array, array.slice(0, 5))
57-
Assert.assertEquals(array, array.slice(-1, 5))
58-
Assert.assertEquals(expectedSliceResult1, array.slice(0, 2))
59-
Assert.assertEquals(expectedSliceResult2, array.slice(1, 3))
60-
Assert.assertEquals(ArraySeq.empty[T], array.slice(1, 1))
61-
Assert.assertEquals(ArraySeq.empty[T], array.slice(2, 1))
61+
assertEquals(array, array.slice(-1, 4))
62+
assertEquals(array, array.slice(0, 5))
63+
assertEquals(array, array.slice(-1, 5))
64+
assertEquals(expectedSliceResult1, array.slice(0, 2))
65+
assertEquals(expectedSliceResult2, array.slice(1, 3))
66+
assertEquals(ArraySeq.empty[T], array.slice(1, 1))
67+
assertEquals(ArraySeq.empty[T], array.slice(2, 1))
6268
}
6369
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package scala.collection.mutable
2+
3+
import org.junit.Assert._
4+
import org.junit.Test
5+
import org.junit.runner.RunWith
6+
import org.junit.runners.JUnit4
7+
8+
import scala.reflect.ClassTag
9+
10+
@RunWith(classOf[JUnit4])
11+
class ArraySeqTest {
12+
@Test
13+
def t10851(): Unit = {
14+
val s1 = ArraySeq.untagged(1,2,3)
15+
assertTrue(s1.array.getClass == classOf[Array[AnyRef]])
16+
val s2 = ArraySeq.make(Array(1))
17+
assertTrue(s2.array.getClass == classOf[Array[Int]])
18+
val s3 = ArraySeq.make(Array(1): Array[Any]).asInstanceOf[ArraySeq[Int]]
19+
assertTrue(s3.array.getClass == classOf[Array[AnyRef]])
20+
}
21+
}
22+
23+
/*
24+
scala> import scala.collection.mutable.WrappedArray
25+
import scala.collection.mutable.WrappedArray
26+
27+
scala> val a = WrappedArray.make(Array(1))
28+
a: scala.collection.mutable.WrappedArray[Int] = WrappedArray(1)
29+
30+
scala> a.array.getClass
31+
res0: Class[_ <: Array[Int]] = class [I
32+
33+
scala> val a = WrappedArray.make(Array(1): Array[Any]).asInstanceOf[WrappedArray[Int]]
34+
a: scala.collection.mutable.WrappedArray[Int] = WrappedArray(1)
35+
36+
scala> a.array.getClass
37+
res1: Class[_ <: Array[Int]] = class [Ljava.lang.Object;
38+
*/

0 commit comments

Comments
 (0)