Skip to content

Commit ed5bb8b

Browse files
committed
Relax unchecked warnings for underscore matches
1 parent 5c6a529 commit ed5bb8b

File tree

2 files changed

+22
-8
lines changed

2 files changed

+22
-8
lines changed

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

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ class IsInstanceOfEvaluator extends MiniPhaseTransform { thisTransformer =>
136136

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 {
139-
case tp @ AppliedType(_, arg :: _) =>
139+
case tp @ AppliedType(_, args @ (arg :: _)) =>
140140
// If the type is `Array[X]` where `X` is a primitive value
141141
// class. In the future, when we have a solid implementation of
142142
// Arrays of value classes, we might be able to relax this check.
@@ -146,6 +146,13 @@ class IsInstanceOfEvaluator extends MiniPhaseTransform { thisTransformer =>
146146
// has @unchecked annotation to suppress warnings
147147
val hasUncheckedAnnot = arg.hasAnnotation(defn.UncheckedAnnot)
148148

149+
// Shouldn't warn when matching on a subclass with underscore params
150+
val matchingUnderscores = args.forall(_ match {
151+
case TypeBounds(lo, hi) =>
152+
(lo eq defn.NothingType) && (hi eq defn.AnyType)
153+
case _ => false
154+
}) && selector <:< scrutinee
155+
149156
// we don't want to warn when matching on `List` from `Seq` e.g:
150157
// (xs: Seq[Int]) match { case xs: List[Int] => ??? }
151158
val matchingSeqToList = {
@@ -160,13 +167,15 @@ class IsInstanceOfEvaluator extends MiniPhaseTransform { thisTransformer =>
160167
hasSameTypeArgs
161168
}
162169

163-
if (!topType && !hasUncheckedAnnot && !matchingSeqToList && !anyValArray) {
164-
ctx.uncheckedWarning(
165-
ErasedType(hl"""|Since type parameters are erased, you should not match on them in
166-
|${"match"} expressions."""),
167-
tree.pos
168-
)
169-
}
170+
val shouldWarn =
171+
!topType && !hasUncheckedAnnot && !matchingUnderscores &&
172+
!matchingSeqToList && !anyValArray
173+
174+
if (shouldWarn) ctx.uncheckedWarning(
175+
ErasedType(hl"""|Since type parameters are erased, you should not match on them in
176+
|${"match"} expressions."""),
177+
tree.pos
178+
)
170179
true
171180
case _ =>
172181
if (tree.args.head.symbol.is(TypeParam)) {

tests/repl/erasure.check

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,4 +56,9 @@ scala> val xs: Seq[Int] = Seq(1,2,3)
5656
val xs: scala.collection.Seq[Int] = List(1, 2, 3)
5757
scala> val xsMatch = xs match { case ss: List[Int] => 1 }
5858
val xsMatch: Int = 1
59+
scala> trait Foo[X]; trait Bar[X,Y]
60+
defined trait Foo
61+
defined trait Bar
62+
scala> val underScoreMatch = (Nil: Any) match { case _: Foo[_] => ???; case _: Bar[_,_] => ???; case _ => 0 }
63+
val underScoreMatch: Int = 0
5964
scala> :quit

0 commit comments

Comments
 (0)