Skip to content

[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

Closed
wants to merge 11 commits into from

Conversation

liufengyun
Copy link
Contributor

@liufengyun liufengyun commented May 18, 2016

This is a work in process, it basically works. The test examples are currently put under tests/patmat/.

Following things need to be done:

  • test framework for checking warnings (use check files for now)
  • handling of constants and backquote pattern in patterns
  • more testing & bug fix
    • build test set from scala issues
    • fix test set
  • java enums (SI-8700, SI-2442)
    • java enums from classfiles
    • java enums from source files
  • code cleanup:
    • put all patmat-related code into the transform.patmat package
    • move test examples from examples/ to tests/neg/patmat/
  • disable checking for top-level matching in partial functions
  • suppress unreachable warning in for-comprehension
  • disable checking for try/catch
  • false warning about Nil
  • auto tupling
  • special handling of Array
  • bounded type members (SI-9657)

A summary is below.

@smarter
Copy link
Member

smarter commented May 18, 2016

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 = {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's ctx.debuglog

Copy link
Member

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.

Copy link
Contributor Author

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.

@smarter
Copy link
Member

smarter commented May 18, 2016

For consistency, we tend to denotes type arguments with tp: Type, not t: Type

}

// widen a type and eliminate anonymous class
private def widen(t: Type): Type = t.widen match {
Copy link
Member

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

@liufengyun
Copy link
Contributor Author

@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 {
Copy link
Member

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.

@smarter
Copy link
Member

smarter commented May 18, 2016

In https://gist.github.com/liufengyun/66bf0c1bc44cdad12e45dd6db689e9b3 you said:

The space covered by a pattern p is defined as follows:
...
if p is pat guard, space(pat)

I think this is not what we want, unless the guard evaluates to true in all cases, the space covered should just be Empty, you should always have a case without a guard if you want the pattern match to be considered exhaustive. This is not the current scalac behavior but it is the one that it will soon have: scala/scala#4929



// space definition
sealed trait Space
Copy link
Member

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! 💥

@liufengyun
Copy link
Contributor Author

liufengyun commented May 18, 2016

@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
}

@smarter
Copy link
Member

smarter commented May 18, 2016

@liufengyun : Yes, you can do tricky things with them, but our response should be: don't do that :)
Your code can easily be rewritten as:

def foo(l: List[int]): Boolean = l match {
  case Nil => false
  case _ => true
}

People should either rewrite their code or add @unchecked

@smarter
Copy link
Member

smarter commented May 18, 2016

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` */
Copy link
Member

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.

Copy link
Contributor Author

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 :)

@liufengyun
Copy link
Contributor Author

@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)
Copy link
Member

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 */
Copy link
Member

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 toEmpty``

Copy link
Member

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) =>
Copy link
Contributor

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.

@liufengyun liufengyun force-pushed the exhaustivity branch 4 times, most recently from 2dc873a to d11b14f Compare July 5, 2016 14:14
@milessabin
Copy link
Contributor

It would be good to know where the various open Scala GADT bugs stand wrt this, in particular SI-5195.

@liufengyun
Copy link
Contributor Author

@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.

@milessabin
Copy link
Contributor

milessabin commented Jul 6, 2016

I obviously read too much into "add GADT test".

@liufengyun liufengyun changed the title [WIP] exhaustivity & redundancy check for pattern matching [Deprecated] exhaustivity & redundancy check for pattern matching Jul 6, 2016
@DarkDimius
Copy link
Contributor

closing in favor of #1364

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants