Skip to content

Commit 3dd2eb7

Browse files
committed
Fix matching on top types
1 parent 015217f commit 3dd2eb7

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
@@ -1004,7 +1004,7 @@ object messages {
10041004
|"""
10051005
}
10061006

1007-
case class ErasedType()(implicit ctx: Context)
1007+
case class ErasedType(val explanation: String = "")(implicit ctx: Context)
10081008
extends Message(37) {
10091009
val kind = "Erased Type"
10101010
val msg =

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

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