Skip to content

Commit af85ccb

Browse files
committed
Fix matching on top types
1 parent 22803e5 commit af85ccb

File tree

3 files changed

+15
-18
lines changed

3 files changed

+15
-18
lines changed

compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1222,7 +1222,7 @@ object messages {
12221222
|""".stripMargin
12231223
}
12241224

1225-
case class ErasedType()(implicit ctx: Context)
1225+
case class ErasedType(val explanation: String = "")(implicit ctx: Context)
12261226
extends Message(ErasedTypeID) {
12271227
val kind = "Erased Type"
12281228
val msg =

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

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -137,13 +137,14 @@ class IsInstanceOfEvaluator extends MiniPhaseTransform { thisTransformer =>
137137
/** 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 or `X =:=
141-
// Any`, this shouldn't yield a warning:
142-
val isArray = tp.isRef(defn.ArrayClass)
143-
val unerased = arg.derivesFrom(defn.AnyValClass) || arg.isRef(defn.AnyClass)
144-
val hasAnnot = arg.hasAnnotation(defn.UncheckedAnnot)
145-
146-
if (!hasAnnot && !(isArray && unerased)) ctx.uncheckedWarning(
140+
// If the type is `Array[X]` where `X` extends AnyVal
141+
val anyValArray = tp.isRef(defn.ArrayClass) && arg.derivesFrom(defn.AnyValClass)
142+
// param is: Any | AnyRef | java.lang.Object
143+
val topType = defn.ObjectType <:< arg
144+
// has @unchecked annotation to suppress warnings
145+
val hasUncheckedAnnot = arg.hasAnnotation(defn.UncheckedAnnot)
146+
147+
if (!topType && !hasUncheckedAnnot && !anyValArray) ctx.uncheckedWarning(
147148
ErasedType(hl"""|Since type parameters are erased, you should not match on them in
148149
|${"match"} expressions."""),
149150
tree.pos

tests/repl/erasure.check

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
scala> def unsafeCast[S](a: Any) = a match { case s: S => s; case _ => ??? }
2-
-- [E035] Erased Type Unchecked Warning: <console> -----------------------------
2+
-- [E037] 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
@@ -16,7 +16,7 @@ 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-
-- [E035] Erased Type Unchecked Warning: <console> -----------------------------
19+
-- [E037] 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
@@ -27,23 +27,17 @@ 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] => ??? }
2828
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-
-- [E035] Erased Type Unchecked Warning: <console> -----------------------------
30+
-- [E037] 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`
3636
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-
-- [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`
4438
def matchArray3[A](xs: Array[A]): [A] => (xs: Array[A])Array[Int]
4539
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> -----------------------------
40+
-- [E037] Erased Type Unchecked Warning: <console> -----------------------------
4741
5 |def matchArray4(xs: Array[Any]) = xs match { case xs: Array[Int] => xs; case xs: Array[A] => ???; case xs: Array[Any] => ??? }
4842
| ^
4943
| abstract type pattern is unchecked since it is eliminated by erasure
@@ -56,4 +50,6 @@ scala> def matchList1(xs: List[Any]) = xs match { case xs: List[Int @unchecked]
5650
def matchList1(xs: List[Any]): Nothing
5751
scala> def matchList2(xs: List[Any]) = xs match { case List() => ???; case _ => ??? }
5852
def matchList2(xs: List[Any]): Nothing
53+
scala> def matchList3(xs: Seq[_]) = xs match { case List() => ???; case _ => ??? }
54+
def matchList3(xs: Seq[_]): Nothing
5955
scala> :quit

0 commit comments

Comments
 (0)