-
Notifications
You must be signed in to change notification settings - Fork 1.1k
[Deprecated] exhaustivity & redundancy check for pattern matching #1261
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
Conversation
Not super important, but if possible it's nice to put the tests in the same commit than the changes that make the tests pass. |
|
||
// scala implementation of space logic | ||
class SpaceEngine(implicit ctx: Context) extends SpaceLogic { | ||
def debug(s: String): Unit = { |
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.
There's ctx.debuglog
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.
But you might want to add a Printer
to https://github.com/lampepfl/dotty/blob/master/src/dotty/tools/dotc/config/Printers.scala and use that instead, this way you can take advantage of ctx.traceIndented
too.
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'll eventually remove the debug
code when everything works. I tried ctx.debuglog
, but it seems I can't make it print in the console even if I used the flag -Ydebug -Ylog:patternmatcher
.
For consistency, we tend to denotes type arguments with |
} | ||
|
||
// widen a type and eliminate anonymous class | ||
private def widen(t: Type): Type = t.widen 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.
Looks like this method is adapted from PatternMatcher#elimAnonymousClass
, instead of copying code it would be better to share it between this and the PatternMatcher, you could for example put elimAnonymousClass
in object PatternMatcher
@smarter thanks a lot for many good points, I'll address them in following commits. |
} | ||
|
||
// scala implementation of space logic | ||
class SpaceEngine(implicit ctx: Context) extends SpaceLogic { |
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.
do import tpd._
here so that you can use Tree
instead of tpd.Tree
below, a lot of phases do this.
In https://gist.github.com/liufengyun/66bf0c1bc44cdad12e45dd6db689e9b3 you said:
I think this is not what we want, unless the guard evaluates to true in all cases, the space covered should just be |
|
||
|
||
// space definition | ||
sealed trait Space |
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 is pretty cool: you're using the exhaustiveness algorithm to test its own exhaustivity! 💥
@smarter Guards can be very tricky, generally we can do nothing with them. However, some ad-hoc heuristics is possible, e.g. the case you mentioned in scalac. But the ad-hoc strategy is very limited and may cause problems: def foo(l: List[int]): Boolean = l match {
case x if x.length > 0 => true
case None => false
} |
@liufengyun : Yes, you can do tricky things with them, but our response should be: don't do that :) def foo(l: List[int]): Boolean = l match {
case Nil => false
case _ => true
} People should either rewrite their code or add |
I left some comments on https://gist.github.com/liufengyun/66bf0c1bc44cdad12e45dd6db689e9b3 |
def isSubType(t1: Type, t2: Type): Boolean | ||
def isEqualType(t1: Type, t2: Type): Boolean | ||
def isCaseClass(t: Type): Boolean | ||
/** is `tp1` a subtype of `tp2` */ |
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.
Sorry for being pedantic, but please start comments with a capital letter :). And put ?
at the end if it's a question.
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.
That's fine, I'm very grateful to your detailed feedback, thanks a lot :)
@smarter I just responded to your comments on the algorithm. |
Kon(pat.tpe, pats.map(project _)) | ||
else if (roundUp) Typ(pat.tpe) | ||
else Empty | ||
case Typed(pat@UnApply(_, _, _), _) => project(pat) |
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 style we use is to put spaces around @
: pat @ UnApply(_, _, _)
// if roundUp, approximate extractors to its type | ||
// else approximate extractors to Empty | ||
def project(pat: tpd.Tree)(implicit ctx: Context, roundUp: Boolean = true): Space = pat match { | ||
/** If roundUp, approximate extractors to its type, else approximate extractors to Empty */ |
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.
If
roundUpis true, approximate an extractor to its type, otherwise approximate it to
Empty``
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.
Also the first line of this comment should explain what this method does, I guess it's something like Return the space that represents the pattern
pat``
if (ktor.isInstanceOf[MethodType]) ktor | ||
else | ||
tp match { | ||
case AppliedType(_, params) => |
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.
ping @odersky, this kind-of reimplements asSeenFrom for constructor. I guess there should be a better way to do it but @liufengyun says it does not work.
2dc873a
to
d11b14f
Compare
scala.Nil refines scala.collection.immutable.Nil, this commit follows redefinition of case objects.
It would be good to know where the various open Scala GADT bugs stand wrt this, in particular SI-5195. |
@milessabin SI-5195 is about GADT type checking & inference in patmat, which is not covered by this PR. Exhaustivity & redundancy check happens after typer and only generate warnings. |
I obviously read too much into "add GADT test". |
closing in favor of #1364 |
This is a work in process, it basically works. The test examples are currently put under
tests/patmat/
.Following things need to be done:
transform.patmat
packageexamples/
totests/neg/patmat/
A summary is below.