Skip to content

Commit ae5655a

Browse files
committed
Don't warn for erasure on arrays with value types
1 parent cd69dcb commit ae5655a

File tree

3 files changed

+61
-28
lines changed

3 files changed

+61
-28
lines changed

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

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -128,8 +128,14 @@ class IsInstanceOfEvaluator extends MiniPhaseTransform { thisTransformer =>
128128
val selClassNonFinal = selClass && !(selector.typeSymbol is Final)
129129
val selFinalClass = selClass && (selector.typeSymbol is Final)
130130
val selTypeParam = tree.args.head.tpe.widen match {
131-
case AppliedType(tycon, args) =>
132-
ctx.uncheckedWarning(
131+
case tp @ AppliedType(tycon, args) =>
132+
// If the type is Array[X] where x extends AnyVal, this shouldn't yield a warning:
133+
val illegalComparison = !(tp.isRef(defn.ArrayClass) && {
134+
args.head.derivesFrom(defn.AnyValClass) ||
135+
args.head.isRef(defn.AnyClass)
136+
})
137+
138+
if (illegalComparison) ctx.uncheckedWarning(
133139
ErasedType(hl"""|Since type parameters are erased, you should not match on them in
134140
|${"match"} expressions."""),
135141
tree.pos

tests/repl/erasure.check

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
scala> def unsafeCast[S](a: Any) = a match { case s: S => s; case _ => ??? }
2+
-- [E035] Erased Type Unchecked Warning: <console> -----------------------------
3+
4 |def unsafeCast[S](a: Any) = a match { case s: S => s; case _ => ??? }
4+
| ^
5+
| abstract type pattern is unchecked since it is eliminated by erasure
6+
7+
longer explanation available when compiling with `-explain`
8+
def unsafeCast[S](a: Any): [S] => (a: Any)S
9+
scala> unsafeCast[String](1)
10+
java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
11+
at .<init>(<console>:6)
12+
at .<clinit>(<console>)
13+
at RequestResult$.<init>(<console>:3)
14+
at RequestResult$.<clinit>(<console>)
15+
at RequestResult$result(<console>)
16+
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
17+
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.jav...
18+
scala> class A; def unsafeCast2[S <: A](a: Any) = a match { case s: S => s; case _ => ??? }
19+
-- [E035] Erased Type Unchecked Warning: <console> -----------------------------
20+
4 |class A; def unsafeCast2[S <: A](a: Any) = a match { case s: S => s; case _ => ??? }
21+
| ^
22+
| abstract type pattern is unchecked since it is eliminated by erasure
23+
24+
longer explanation available when compiling with `-explain`
25+
defined class A
26+
def unsafeCast2[S <: A](a: Any): [S <: A] => (a: Any)S
27+
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]
29+
scala> def matchArray2[A](xs: Array[Any]) = xs match { case xs: Array[Int] => xs; case xs: Array[A] => ??? }
30+
-- [E035] Erased Type Unchecked Warning: <console> -----------------------------
31+
5 |def matchArray2[A](xs: Array[Any]) = xs match { case xs: Array[Int] => xs; case xs: Array[A] => ??? }
32+
| ^
33+
| abstract type pattern is unchecked since it is eliminated by erasure
34+
35+
longer explanation available when compiling with `-explain`
36+
def matchArray2[A](xs: Array[Any]): [A] => (xs: Array[Any])Array[Int]
37+
scala> def matchArray3[A](xs: Array[A]) = xs match { case xs: Array[Int] => xs; case xs: Array[AnyRef] => ???; case xs: Array[Any] => ??? }
38+
-- [E035] Erased Type Unchecked Warning: <console> -----------------------------
39+
5 |def matchArray3[A](xs: Array[A]) = xs match { case xs: Array[Int] => xs; case xs: Array[AnyRef] => ???; case xs: Array[Any] => ??? }
40+
| ^
41+
| abstract type pattern is unchecked since it is eliminated by erasure
42+
43+
longer explanation available when compiling with `-explain`
44+
def matchArray3[A](xs: Array[A]): [A] => (xs: Array[A])Array[Int]
45+
scala> def matchArray4(xs: Array[Any]) = xs match { case xs: Array[Int] => xs; case xs: Array[A] => ???; case xs: Array[Any] => ??? }
46+
-- [E035] Erased Type Unchecked Warning: <console> -----------------------------
47+
5 |def matchArray4(xs: Array[Any]) = xs match { case xs: Array[Int] => xs; case xs: Array[A] => ???; case xs: Array[Any] => ??? }
48+
| ^
49+
| abstract type pattern is unchecked since it is eliminated by erasure
50+
51+
longer explanation available when compiling with `-explain`
52+
def matchArray4(xs: Array[Any]): Array[Int]
53+
scala> :quit

tests/repl/errmsgs.check

Lines changed: 0 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -78,30 +78,4 @@ scala> class Foo() { def bar: Int = 1 }; val foo = new Foo(); foo.barr
7878
4 |class Foo() { def bar: Int = 1 }; val foo = new Foo(); foo.barr
7979
| ^^^^^^^^
8080
| value `barr` is not a member of Foo(foo) - did you mean `foo.bar`?
81-
scala> def unsafeCast[S](a: Any) = a match { case s: S => s; case _ => ??? }
82-
-- [E034] Erased Type Unchecked Warning: <console> -----------------------------
83-
4 |def unsafeCast[S](a: Any) = a match { case s: S => s; case _ => ??? }
84-
| ^
85-
| abstract type pattern is unchecked since it is eliminated by erasure
86-
87-
longer explanation available when compiling with `-explain`
88-
def unsafeCast[S](a: Any): [S] => (a: Any)S
89-
scala> unsafeCast[String](1)
90-
java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
91-
at .<init>(<console>:6)
92-
at .<clinit>(<console>)
93-
at RequestResult$.<init>(<console>:3)
94-
at RequestResult$.<clinit>(<console>)
95-
at RequestResult$result(<console>)
96-
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
97-
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.jav...
98-
scala> class A; def unsafeCast2[S <: A](a: Any) = a match { case s: S => s; case _ => ??? }
99-
-- [E034] Erased Type Unchecked Warning: <console> -----------------------------
100-
4 |class A; def unsafeCast2[S <: A](a: Any) = a match { case s: S => s; case _ => ??? }
101-
| ^
102-
| abstract type pattern is unchecked since it is eliminated by erasure
103-
104-
longer explanation available when compiling with `-explain`
105-
defined class A
106-
def unsafeCast2[S <: A](a: Any): [S <: A] => (a: Any)S
10781
scala> :quit

0 commit comments

Comments
 (0)