Skip to content

Commit

Permalink
Relax unchecked warnings for underscore matches
Browse files Browse the repository at this point in the history
  • Loading branch information
felixmulder committed Apr 7, 2017
1 parent 5c6a529 commit ed5bb8b
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ class IsInstanceOfEvaluator extends MiniPhaseTransform { thisTransformer =>

// Check if the selector's potential type parameters will be erased, and if so warn
val selTypeParam = tree.args.head.tpe.widen match {
case tp @ AppliedType(_, arg :: _) =>
case tp @ AppliedType(_, args @ (arg :: _)) =>
// If the type is `Array[X]` where `X` is a primitive value
// class. In the future, when we have a solid implementation of
// Arrays of value classes, we might be able to relax this check.
Expand All @@ -146,6 +146,13 @@ class IsInstanceOfEvaluator extends MiniPhaseTransform { thisTransformer =>
// has @unchecked annotation to suppress warnings
val hasUncheckedAnnot = arg.hasAnnotation(defn.UncheckedAnnot)

// Shouldn't warn when matching on a subclass with underscore params
val matchingUnderscores = args.forall(_ match {
case TypeBounds(lo, hi) =>
(lo eq defn.NothingType) && (hi eq defn.AnyType)
case _ => false
}) && selector <:< scrutinee

// we don't want to warn when matching on `List` from `Seq` e.g:
// (xs: Seq[Int]) match { case xs: List[Int] => ??? }
val matchingSeqToList = {
Expand All @@ -160,13 +167,15 @@ class IsInstanceOfEvaluator extends MiniPhaseTransform { thisTransformer =>
hasSameTypeArgs
}

if (!topType && !hasUncheckedAnnot && !matchingSeqToList && !anyValArray) {
ctx.uncheckedWarning(
ErasedType(hl"""|Since type parameters are erased, you should not match on them in
|${"match"} expressions."""),
tree.pos
)
}
val shouldWarn =
!topType && !hasUncheckedAnnot && !matchingUnderscores &&
!matchingSeqToList && !anyValArray

if (shouldWarn) ctx.uncheckedWarning(
ErasedType(hl"""|Since type parameters are erased, you should not match on them in
|${"match"} expressions."""),
tree.pos
)
true
case _ =>
if (tree.args.head.symbol.is(TypeParam)) {
Expand Down
5 changes: 5 additions & 0 deletions tests/repl/erasure.check
Original file line number Diff line number Diff line change
Expand Up @@ -56,4 +56,9 @@ scala> val xs: Seq[Int] = Seq(1,2,3)
val xs: scala.collection.Seq[Int] = List(1, 2, 3)
scala> val xsMatch = xs match { case ss: List[Int] => 1 }
val xsMatch: Int = 1
scala> trait Foo[X]; trait Bar[X,Y]
defined trait Foo
defined trait Bar
scala> val underScoreMatch = (Nil: Any) match { case _: Foo[_] => ???; case _: Bar[_,_] => ???; case _ => 0 }
val underScoreMatch: Int = 0
scala> :quit

0 comments on commit ed5bb8b

Please sign in to comment.