Fix #4225: always do reachability check#4253
Conversation
| Text() | ||
|
|
||
| nodeName ~ "(" ~ elems ~ tpSuffix ~ ")" ~ (Str(node.pos.toString) provided ctx.settings.YprintPos.value) | ||
| case _ => |
There was a problem hiding this comment.
Tree extends Positioned so we don't even need a pattern match at all here.
| """.stripMargin | ||
| ctx.error(msg, pos) | ||
| None | ||
| case ex: Throwable => throw ex |
There was a problem hiding this comment.
This looks wrong to me, a try/catch can always catch a Throwable.
There was a problem hiding this comment.
Yes, we could keep it, and no warning will be reported. I removed it because the compiler will generate a default case anyway.
| Typ(ConstantType(c), false) | ||
| case _: BackquotedIdent => Typ(pat.tpe, false) | ||
| case Ident(nme.WILDCARD) => | ||
| Or(Typ(pat.tpe.stripAnnots, false) :: Typ(ConstantType(Constant(null))) :: Nil) |
There was a problem hiding this comment.
Would be cleaner to have val nullType = ConstantType(Constant(null)) somewhere.
| def test(x: String) = | ||
| x match { | ||
| case Bar(a) => a | ||
| case _ => x // this case is reachable, i.e. test(null) |
There was a problem hiding this comment.
Suggestion; maybe if the only way to reach a case is through null, we should suggest the user writes case null instead of case _ ?
There was a problem hiding this comment.
This is a good idea, it's implemented in the latest commit.
| /** Is `tp1` a subtype of `tp2`? */ | ||
| def isSubType(tp1: Type, tp2: Type): Boolean = { | ||
| val res = tp1 <:< tp2 && (tp1 != ConstantType(Constant(null)) || tp2 == ConstantType(Constant(null))) | ||
| val res = tp1 <:< tp2 && (tp1 != nullType || tp2 == nullType) |
There was a problem hiding this comment.
the nullType checks could be moved before the subtype checks since they're cheaper.
| // if last case is `_` and only matches `null`, produce a warning | ||
| if (i == cases.length - 1) { | ||
| simplify(minus(covered, prevs)) match { | ||
| case Typ(ConstantType(Constant(null)), _) => |
|
test performance please |
|
performance test scheduled: 2 job(s) in queue, 1 running. |
| case class MatchCaseUnreachable()(implicit ctx: Context) | ||
| extends Message(MatchCaseUnreachableID) { | ||
| val kind = s"""Match ${hl"case"} Unreachable""" | ||
| val kind = s"""Match case Unreachable""" |
There was a problem hiding this comment.
interpolator not needed
|
|
||
| case class MatchCaseOnlyNullWarning()(implicit ctx: Context) | ||
| extends Message(MatchCaseOnlyNullWarningID) { | ||
| val kind = s"""Only null matched""" |
There was a problem hiding this comment.
interpolator not needed
| case class MatchCaseOnlyNullWarning()(implicit ctx: Context) | ||
| extends Message(MatchCaseOnlyNullWarningID) { | ||
| val kind = s"""Only null matched""" | ||
| val msg = s"Only ${hl"null"} is matched. Consider use `case null =>` instead." |
|
Performance test finished successfully: Visit http://dotty-bench.epfl.ch/4253/ to see the changes. Benchmarks is based on merging with master (b1d9162) |
Note that we only handle null in reachability check,
while ignore null in exhaustivity check. Otherwise,
the following pattern match will report a warning
about `null`, which is annoying:
(Some(3): Option[Int]) match {
case Some(x) =>
case None =>
}
|
The performance regression on
|
Fix #4225
Note that we only handle null in reachability check, while ignore null in exhaustivity check. Otherwise, the following pattern match will report a warning about
null, which is annoying: