Skip to content

Commit 46b8d67

Browse files
committed
Fix isInstanceOf[Array[?]] returning true on non-Array
Before this commit, the `MultiArrayOf(elem, ndims)` extractor used to strip wildcards from the element type, this was surprising since it does not match what the `ArrayOf(elem)` extractor does, and lead to a bug in `TypeTestCasts.interceptTypeApply` which contains the following code: case defn.MultiArrayOf(elem, ndims) if isGenericArrayElement(elem, isScala2 = false) => `isGenericArrayElement` returns false for `Any` but true for `_ >: Nothing <: Any`, so the stripped wildcard means that this case was skipped, resulting in: x.isInstanceOf[Array[?]] being erased to: x.isInstanceOf[Object] instead of: scala.runtime.ScalaRunTime.isArray(x, 1) Fixed by tweaking `MultiArrayOf` to keep any final wildcard around like `ArrayOf` does.
1 parent f3c1468 commit 46b8d67

File tree

2 files changed

+10
-3
lines changed

2 files changed

+10
-3
lines changed

compiler/src/dotty/tools/dotc/core/Definitions.scala

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1030,21 +1030,22 @@ class Definitions {
10301030

10311031
/** An extractor for multi-dimensional arrays.
10321032
* Note that this will also extract the high bound if an
1033-
* element type is a wildcard. E.g.
1033+
* element type is a wildcard upper-bounded by an array. E.g.
10341034
*
10351035
* Array[? <: Array[? <: Number]]
10361036
*
10371037
* would match
10381038
*
1039-
* MultiArrayOf(<Number>, 2)
1039+
* MultiArrayOf(<? <: Number>, 2)
10401040
*/
10411041
object MultiArrayOf {
10421042
def apply(elem: Type, ndims: Int)(using Context): Type =
10431043
if (ndims == 0) elem else ArrayOf(apply(elem, ndims - 1))
10441044
def unapply(tp: Type)(using Context): Option[(Type, Int)] = tp match {
10451045
case ArrayOf(elemtp) =>
10461046
def recur(elemtp: Type): Option[(Type, Int)] = elemtp.dealias match {
1047-
case TypeBounds(lo, hi) => recur(hi)
1047+
case tp @ TypeBounds(lo, hi @ MultiArrayOf(finalElemTp, n)) =>
1048+
Some(finalElemTp, n)
10481049
case MultiArrayOf(finalElemTp, n) => Some(finalElemTp, n + 1)
10491050
case _ => Some(elemtp, 1)
10501051
}

tests/run/array-erasure.scala

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,5 +65,11 @@ object Test {
6565
arr4(x)
6666
arr5(x)
6767
arr6(x)
68+
69+
70+
val str: Any = ""
71+
assert(!str.isInstanceOf[Array[?]])
72+
assert(!str.isInstanceOf[Array[Array[?]]])
73+
assert(!str.isInstanceOf[Array[? <: Array[?]]])
6874
}
6975
}

0 commit comments

Comments
 (0)