-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Closes #4300 adds better worded pattern match unreachability warning #4552
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 4 commits
becafe4
6834571
f55d497
215f0bf
bf7c85c
1370dd1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2117,4 +2117,38 @@ object messages { | |
| val explanation: String = "" | ||
| } | ||
|
|
||
| case class PatternMatchAlwaysSucceeds(foundCls: Symbol, testCls: Symbol)(implicit ctx: Context) extends Message(PatternMatchAlwaysSucceedsID) { | ||
| val kind = "Syntax" | ||
| val msg: String = | ||
| hl""" | ||
| |The type check in the highlighted part of the pattern match case statement will always succeed, | ||
| |since `$foundCls` is a subclass of `$testCls`. | ||
| """ | ||
|
||
| val codeExampleValidWarning = "def foo(a: Int) = a match { case x: Int => x }" | ||
| val codeExampleDisregardWarning = | ||
|
||
| hl""" | ||
| |object Foo { | ||
| | def unapply(x: Int): Option[Int] = if (x % 2 == 0) Some(x) else None | ||
| |} | ||
| | | ||
| |class Test { | ||
| | def foo(a: Int) = a match { case Foo(x: Int) => x } | ||
| |} | ||
| """ | ||
| val explanation: String = | ||
|
||
| hl""" | ||
| |The highlighted typecheck will always match. | ||
| |For example: | ||
| | | ||
| |$codeExampleValidWarning | ||
| | | ||
| |The type of the scrutinee 'a' will always be 'Int', so a the 'case x: Int' | ||
| |match will always be successful. Maybe a guard clause was forgotten. | ||
| | | ||
| |In the following counter-example, because of the unapply method, the | ||
| |whole match will not be always successful, only the type check. | ||
| |$codeExampleDisregardWarning | ||
| | | ||
| """ | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -10,6 +10,7 @@ import ValueClasses._ | |
| import SymUtils._ | ||
| import core.Flags._ | ||
| import util.Positions._ | ||
| import reporting.diagnostic.messages.PatternMatchAlwaysSucceeds | ||
| import reporting.trace | ||
|
|
||
|
|
||
|
|
@@ -90,9 +91,12 @@ object TypeTestsCasts { | |
|
|
||
| if (expr.tpe <:< testType) | ||
| if (expr.tpe.isNotNull) { | ||
| ctx.warning( | ||
| em"this will always yield true, since `$foundCls` is a subclass of `$testCls`", | ||
| expr.pos) | ||
| if (inMatch) | ||
| ctx.warning(PatternMatchAlwaysSucceeds(foundCls, testCls), tree.pos) | ||
| else | ||
| ctx.warning( | ||
| em"this will always yield true, since `$foundCls` is a subclass of `$testCls`", | ||
| expr.pos) | ||
|
||
| constant(expr, Literal(Constant(true))) | ||
| } | ||
| else expr.testNotNull | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
type annotation not needed