Skip to content

Commit 4b31518

Browse files
committed
Constrain anyValArray check to primitives
1 parent af85ccb commit 4b31518

File tree

3 files changed

+15
-39
lines changed

3 files changed

+15
-39
lines changed

compiler/src/dotty/tools/dotc/transform/IsInstanceOfEvaluator.scala

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -134,11 +134,13 @@ class IsInstanceOfEvaluator extends MiniPhaseTransform { thisTransformer =>
134134
val selClassNonFinal = selClass && !(selector.typeSymbol is Final)
135135
val selFinalClass = selClass && (selector.typeSymbol is Final)
136136

137-
/** Check if the selector's potential type parameters will be erased, and if so warn */
137+
// Check if the selector's potential type parameters will be erased, and if so warn
138138
val selTypeParam = tree.args.head.tpe.widen match {
139139
case tp @ AppliedType(_, arg :: _) =>
140-
// If the type is `Array[X]` where `X` extends AnyVal
141-
val anyValArray = tp.isRef(defn.ArrayClass) && arg.derivesFrom(defn.AnyValClass)
140+
// If the type is `Array[X]` where `X` is a primitive value
141+
// class. In the future, when we have a solid implementation of
142+
// Arrays of value classes, we might be able to relax this check.
143+
val anyValArray = tp.isRef(defn.ArrayClass) && arg.typeSymbol.isPrimitiveValueClass
142144
// param is: Any | AnyRef | java.lang.Object
143145
val topType = defn.ObjectType <:< arg
144146
// has @unchecked annotation to suppress warnings

tests/repl/erasure.check

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
scala> def unsafeCast[S](a: Any) = a match { case s: S => s; case _ => ??? }
2-
-- [E037] Erased Type Unchecked Warning: <console> -----------------------------
2+
-- [E048] Erased Type Unchecked Warning: <console> -----------------------------
33
4 |def unsafeCast[S](a: Any) = a match { case s: S => s; case _ => ??? }
44
| ^
55
| abstract type pattern is unchecked since it is eliminated by erasure
66

77
longer explanation available when compiling with `-explain`
8-
def unsafeCast[S](a: Any): [S] => (a: Any)S
8+
def unsafeCast[S](a: Any): [S](a: Any)S
99
scala> unsafeCast[String](1)
1010
java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
1111
at .<init>(<console>:6)
@@ -16,36 +16,36 @@ java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.Stri
1616
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
1717
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.jav...
1818
scala> class A; def unsafeCast2[S <: A](a: Any) = a match { case s: S => s; case _ => ??? }
19-
-- [E037] Erased Type Unchecked Warning: <console> -----------------------------
19+
-- [E048] Erased Type Unchecked Warning: <console> -----------------------------
2020
4 |class A; def unsafeCast2[S <: A](a: Any) = a match { case s: S => s; case _ => ??? }
2121
| ^
2222
| abstract type pattern is unchecked since it is eliminated by erasure
2323

2424
longer explanation available when compiling with `-explain`
2525
defined class A
26-
def unsafeCast2[S <: A](a: Any): [S <: A] => (a: Any)S
26+
def unsafeCast2[S <: A](a: Any): [S <: A](a: Any)S
2727
scala> def matchArray1[A](xs: Array[A]) = xs match { case xs: Array[Int] => xs; case xs: Array[A] => ??? }
28-
def matchArray1[A](xs: Array[A]): [A] => (xs: Array[A])Array[Int]
28+
def matchArray1[A](xs: Array[A]): [A](xs: Array[A])Array[Int]
2929
scala> def matchArray2[A](xs: Array[Any]) = xs match { case xs: Array[Int] => xs; case xs: Array[A] => ??? }
30-
-- [E037] Erased Type Unchecked Warning: <console> -----------------------------
30+
-- [E048] Erased Type Unchecked Warning: <console> -----------------------------
3131
5 |def matchArray2[A](xs: Array[Any]) = xs match { case xs: Array[Int] => xs; case xs: Array[A] => ??? }
3232
| ^
3333
| abstract type pattern is unchecked since it is eliminated by erasure
3434

3535
longer explanation available when compiling with `-explain`
36-
def matchArray2[A](xs: Array[Any]): [A] => (xs: Array[Any])Array[Int]
36+
def matchArray2[A](xs: Array[Any]): [A](xs: Array[Any])Array[Int]
3737
scala> def matchArray3[A](xs: Array[A]) = xs match { case xs: Array[Int] => xs; case xs: Array[AnyRef] => ???; case xs: Array[Any] => ??? }
38-
def matchArray3[A](xs: Array[A]): [A] => (xs: Array[A])Array[Int]
38+
def matchArray3[A](xs: Array[A]): [A](xs: Array[A])Array[Int]
3939
scala> def matchArray4(xs: Array[Any]) = xs match { case xs: Array[Int] => xs; case xs: Array[A] => ???; case xs: Array[Any] => ??? }
40-
-- [E037] Erased Type Unchecked Warning: <console> -----------------------------
40+
-- [E048] Erased Type Unchecked Warning: <console> -----------------------------
4141
5 |def matchArray4(xs: Array[Any]) = xs match { case xs: Array[Int] => xs; case xs: Array[A] => ???; case xs: Array[Any] => ??? }
4242
| ^
4343
| abstract type pattern is unchecked since it is eliminated by erasure
4444

4545
longer explanation available when compiling with `-explain`
4646
def matchArray4(xs: Array[Any]): Array[Int]
4747
scala> def matchArray5[A](xs: Array[Any]) = xs match { case xs: Array[Int] => xs; case xs: Array[A @unchecked] => ??? }
48-
def matchArray5[A](xs: Array[Any]): [A] => (xs: Array[Any])Array[Int]
48+
def matchArray5[A](xs: Array[Any]): [A](xs: Array[Any])Array[Int]
4949
scala> def matchList1(xs: List[Any]) = xs match { case xs: List[Int @unchecked] => ??? }
5050
def matchList1(xs: List[Any]): Nothing
5151
scala> def matchList2(xs: List[Any]) = xs match { case List() => ???; case _ => ??? }

tests/repl/errmsgs.check

Lines changed: 0 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -92,30 +92,4 @@ scala> { def f: Int = g; val x: Int = 1; def g: Int = 5; }
9292
| `g` is a forward reference extending over the definition of `x`
9393

9494
longer explanation available when compiling with `-explain`
95-
scala> def unsafeCast[S](a: Any) = a match { case s: S => s; case _ => ??? }
96-
-- [E034] Erased Type Unchecked Warning: <console> -----------------------------
97-
4 |def unsafeCast[S](a: Any) = a match { case s: S => s; case _ => ??? }
98-
| ^
99-
| abstract type pattern is unchecked since it is eliminated by erasure
100-
101-
longer explanation available when compiling with `-explain`
102-
def unsafeCast[S](a: Any): [S] => (a: Any)S
103-
scala> unsafeCast[String](1)
104-
java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
105-
at .<init>(<console>:6)
106-
at .<clinit>(<console>)
107-
at RequestResult$.<init>(<console>:3)
108-
at RequestResult$.<clinit>(<console>)
109-
at RequestResult$result(<console>)
110-
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
111-
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.jav...
112-
scala> class A; def unsafeCast2[S <: A](a: Any) = a match { case s: S => s; case _ => ??? }
113-
-- [E034] Erased Type Unchecked Warning: <console> -----------------------------
114-
4 |class A; def unsafeCast2[S <: A](a: Any) = a match { case s: S => s; case _ => ??? }
115-
| ^
116-
| abstract type pattern is unchecked since it is eliminated by erasure
117-
118-
longer explanation available when compiling with `-explain`
119-
defined class A
120-
def unsafeCast2[S <: A](a: Any): [S <: A] => (a: Any)S
12195
scala> :quit

0 commit comments

Comments
 (0)