Skip to content
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

Check exhaustivity of pattern matches with "if" guards and custom extractors (by default) and of unsealed types (by opt-in). #9140

Merged
merged 13 commits into from Oct 23, 2020

Commits on Oct 8, 2020

  1. SI-5365 Check exhaustivity with guards, extractors

    Rather than disabling the analysis altogether, rewrite
    guard to `true` (by default) or to `false` under a new
    compiler option.
    
    The default option errs on the side of avoiding spurious
    warnings where the guard writer knows better. However,
    there was a convincing argument made in the ticket that
    in these cases it would not be to onerous to require
    the code to be rewritten from
    
        case P if g1 =>
        case P if g2 =>
    
    to:
    
        case P if g1 =>
        case P       =>
    
    Or to:
    
        (scrut: @unchecked) match {
          case P if g1 =>
          case P if g2 =>
    
    So perhaps we can turn on the strict version by
    default, after running against the community build
    as a sanity check.
    
    Extractor patterns had the same limitation as guards.
    This commit also enables the analysis for them in the
    same way as done for guards. However, this still not
    done for `unapplySeq` extractors, as the counter example
    generator can't handle these yet.
    retronym authored and dwijnand committed Oct 8, 2020
    Configuration menu
    Copy the full SHA
    c7ebfdb View commit details
    Browse the repository at this point in the history
  2. Configuration menu
    Copy the full SHA
    c02a234 View commit details
    Browse the repository at this point in the history
  3. Update exhaustivity checking.

    Handle exhaustivity for `unapplySeq` extractors and restrict a
    `WildcardExample` case to when strict pattern matching is enabled.
    sellout authored and dwijnand committed Oct 8, 2020
    Configuration menu
    Copy the full SHA
    2da20d4 View commit details
    Browse the repository at this point in the history
  4. Configuration menu
    Copy the full SHA
    e8734c1 View commit details
    Browse the repository at this point in the history
  5. Check exhaustivity of case class unapplySeq extractors too

    ProductExtractorTreeMaker handles non-custom extractors, i.e. the
    synthetic ones generates for case classes.  I think this case was just
    accidentally missing from the original commit.
    
    The change to run/virtpatmat_unapplyprod makes sense to me - it's an
    inexhaustive match, albeit with complicated counter-examples... :(
    
    This is the actually the last remaining tree maker, so none will back
    off after this, from my reading - but I kept the back-off stuff as is,
    keeping the diff minimal, to try to land this as easily as possible.
    dwijnand committed Oct 8, 2020
    Configuration menu
    Copy the full SHA
    03574d8 View commit details
    Browse the repository at this point in the history
  6. Fix the List rewrite in patmat to use 2.13's UnapplySeqWrapper

    I didn't double-check, but what I expect happened is that all the
    pattern matches that included a "case List()" stopped producing any
    exhaustivity/unreachable warnings.  And then my guess is the impact
    wasn't understood and the checkfiles were just updated?
    
    In the next commit strict pattern matching becomes the default, which,
    when bootstrapping, found a pattern match in the compiler that uses
    "case List()" (with -Werror enabled).
    dwijnand committed Oct 8, 2020
    Configuration menu
    Copy the full SHA
    df6b7f2 View commit details
    Browse the repository at this point in the history
  7. Configuration menu
    Copy the full SHA
    c54081e View commit details
    Browse the repository at this point in the history
  8. Configuration menu
    Copy the full SHA
    9519ebe View commit details
    Browse the repository at this point in the history

Commits on Oct 9, 2020

  1. Make sure counter-examples are distinct

    With exhaustivity not being skipped for TreeMakers, we're running into
    more counter-examples which seem to be getting by our
    CounterExample.prune, so add an extra string distinct to keep
    run/patmatnew.scala stable.
    dwijnand committed Oct 9, 2020
    Configuration menu
    Copy the full SHA
    cb391c2 View commit details
    Browse the repository at this point in the history

Commits on Oct 22, 2020

  1. Configuration menu
    Copy the full SHA
    0416c57 View commit details
    Browse the repository at this point in the history
  2. Avoid spurious custom extractor warnings

    The pattern matcher converts code like:
    
        Box(Option("hello")) match {
          case Box(Some(s)) =>
          case Box(None)    =>
        }
    
    into two invocations of Box.unapply, because it can't trust that
    Box.unapply is idempotent.  For case classes (like Some) it can, and
    moreso it can just access the underlying values directly ("x1.value").
    The exhaustivity/unreachability analysis builds on this (e.g
    "pointsToBound.exists(sym => t.exists(_.symbol == sym)").
    
    With the previous commits making the exhaustivity/unreachability checker
    consider custom extractors this would result in multiple symbols for
    each extraction (instead of all being "x1.value", for example) which
    results in multiple SAT variables which results, basically, in  warnings
    that the value returned from the first extraction could None and the
    second value could be Some - which is only true for a non-idempotent
    Box.unapply.  The intent of the previous commits (and the whole PR) is
    to make the exhaustivity checker provide warnings that were previous
    missing, but warning for fear of non-idempotent custom extractors would
    produce more noise than signal.
    
    Now, within a minor release like 2.13.4 we can't go and change the code
    generation and thus the code semantics (Dotty can and apparently does),
    but we can do the analysis with the assumption of idempotency.  That's
    what this does: in MatchApproximator's TreeMakersToProps use a cache for
    the binders so when we see two extractions that are equivalent we reuse
    the same binder, so it translates into the same SAT variable.
    dwijnand committed Oct 22, 2020
    Configuration menu
    Copy the full SHA
    4ef23e4 View commit details
    Browse the repository at this point in the history

Commits on Oct 23, 2020

  1. Configuration menu
    Copy the full SHA
    ac2c3c8 View commit details
    Browse the repository at this point in the history
  2. Configuration menu
    Copy the full SHA
    3808a6a View commit details
    Browse the repository at this point in the history