Skip to content

Commit 237cd34

Browse files
committed
Relax unchecked for underscore and type bindings
1 parent 1a8af58 commit 237cd34

File tree

2 files changed

+26
-8
lines changed

2 files changed

+26
-8
lines changed

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

Lines changed: 21 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,16 @@ 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
150+
// params or type binding
151+
val matchingUnderscoresOrTypeBindings = args.forall(_ match {
152+
case tr: TypeRef =>
153+
tr.symbol.is(BindDefinedType)
154+
case TypeBounds(lo, hi) =>
155+
(lo eq defn.NothingType) && (hi eq defn.AnyType)
156+
case _ => false
157+
}) && selector <:< scrutinee
158+
149159
// we don't want to warn when matching on `List` from `Seq` e.g:
150160
// (xs: Seq[Int]) match { case xs: List[Int] => ??? }
151161
val matchingSeqToList = {
@@ -160,13 +170,16 @@ class IsInstanceOfEvaluator extends MiniPhaseTransform { thisTransformer =>
160170
hasSameTypeArgs
161171
}
162172

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-
}
173+
val shouldWarn =
174+
!topType && !hasUncheckedAnnot &&
175+
!matchingUnderscoresOrTypeBindings && !matchingSeqToList &&
176+
!anyValArray
177+
178+
if (shouldWarn) ctx.uncheckedWarning(
179+
ErasedType(hl"""|Since type parameters are erased, you should not match on them in
180+
|${"match"} expressions."""),
181+
tree.pos
182+
)
170183
true
171184
case _ =>
172185
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)