-
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
Closes #4300 adds better worded pattern match unreachability warning #4552
Conversation
…ning - Used when isInstanceOf is called inside a match case - The new message is "this case will always be taken because the scrutinee has type `<type>`" - Highlights the position of `x: Int` instead of `x`
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.
Hello, and thank you for opening this PR! 🎉
All contributors have signed the CLA, thank you! ❤️
Have an awesome day! ☀️
if (inMatch) | ||
ctx.warning( | ||
em"this case will always be taken because the scrutinee has type `$testType`", | ||
tree.pos) |
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.
This error message doesn't make sense for the following test case:
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 }
}
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.
- To address both @zoltanelek and @liufengyun's concerns, I'd at least say "this pattern will always succeed", where "this" refers to
x: Int
(as shown by the position) — I'd prefer in fact "the highlighted pattern match".
I think both this message and the current one can still be a bit confusing because they might only refer to one pattern out of many nested ones, but maybe that can be clarified in the message explanation.
-
I'd also please keep showing both
$foundCls
and$testCls
, since in the presence of type aliases they might be nontrivial to deduce from the scrutinee type and the pattern match. -
Separately, "since
$foundCls
is a subclass of$testCls
" says more than "because the scrutinee has type$testType
": who wrote the code and fixes the warning might know the scrutinee's type, but what they probably missed is that$foundCls
is a subclass of$testCls
.
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.
This must be revised to address the comments. @zoltanelek do you think you can give it a try?
@Blaisorblade sure! |
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.
It should probably be a proper message case class. See https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala
Hey guys! I went with I think this is much more meaningful when matching on tuples.
And 'the type check in the highlighted part' would not imply that there can't be an unapply behind the scenes, which will fail to match.
|
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.
LGTM, thanks a lot @zoltanelek 🎉
BTW, could you please squash the history to keep one commit?
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.
@liufengyun @Blaisorblade Why not something like:
The highlighted type test will always succeed since the scrutiny type (${expr.tpe}) is a subtype of ${testType}
This wording is applicable to both isIntanceOf
test and type test in pattern match. One could go into more detail (if needed) in the explanation part of the message
else | ||
ctx.warning( | ||
em"this will always yield true, since `$foundCls` is a subclass of `$testCls`", | ||
expr.pos) |
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.
I would merge the two together by making inMatch
a parameter of the message class and name the class something like TypeTestAlwaysSucceeds
@@ -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 = |
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
hl""" | ||
|The type check in the highlighted part of the pattern match case statement will always succeed, | ||
|since `$foundCls` is a subclass of `$testCls`. | ||
""" |
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.
Rewrite as:
hl"""...
|..."""
Otherwise the resulting string has unnecessary line breaks before and after
|since `$foundCls` is a subclass of `$testCls`. | ||
""" | ||
val codeExampleValidWarning = "def foo(a: Int) = a match { case x: Int => x }" | ||
val codeExampleDisregardWarning = |
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.
The user should not disregard the warning. The warning is legitimate, he should have written case Foo(x)
instead of case Foo(x: Int)
| def foo(a: Int) = a match { case Foo(x: Int) => x } | ||
|} | ||
""" | ||
val explanation: String = |
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.
I would remove the current explanation. I don't think it gives you more information than the msg
.
@liufengyun sure, I'll squash them when everybody approves. |
@Blaisorblade @allanrenucci I think it looks good now, do you have more comments? |
Thanks @zoltanelek! |
Cool! Thanks for the help guys! |
<type>
"x: Int
instead ofx