[commit: ghc] master: Improve exhaustiveness checking for literal values and patterns, fix #14546 (1f88f54)

git at git.haskell.org git at git.haskell.org
Sun Jun 3 05:40:46 UTC 2018

Repository : ssh://git@git.haskell.org/ghc

On branch  : master
Link       : http://ghc.haskell.org/trac/ghc/changeset/1f88f541aad1e36d01f22f9e71dfbc247e6558e2/ghc


commit 1f88f541aad1e36d01f22f9e71dfbc247e6558e2
Author: HE, Tao <sighingnow at gmail.com>
Date:   Sun Jun 3 00:38:30 2018 -0400

    Improve exhaustiveness checking for literal values and patterns, fix #14546
    Currently, we parse both the **integral literal** value and the patterns
    as `OverLit HsIntegral`.  For example:
      case 0::Int of
          0 -> putStrLn "A"
          1 -> putStrLn "B"
          _ -> putStrLn "C"
    When checking the exhaustiveness of pattern matching, we translate the
    `0` in value position as `PmOLit`, but translate the `0` and `1` in
    pattern position as `PmSLit`. The inconsistency leads to the failure of
    `eqPmLit` to detect the equality and report warning of "Pattern match is
    redundant" on pattern `0`, as reported in #14546. In this patch we
    remove the specialization of `OverLit` patterns, and keep the overloaded
    number literal in pattern as it is to maintain the consistency.  Now we
    can capture the exhaustiveness of pattern `0` and the redundancy of
    pattern `1` and `_`.
    For **string literals**, we parse the string literals as `HsString`.
    When  `OverloadedStrings` is enabled, it further be turned as `HsOverLit
    HsIsString`, whether it's type is `String` or not. For example:
      case "foo" of
          "foo" -> putStrLn "A"
          "bar" -> putStrLn "B"
          "baz" -> putStrLn "C"
    Previously, the overloaded string values are translated to `PmOLit` and
    the non-overloaded string values are translated to `PmSLit`. However the
    string patterns, both overloaded and non-overloaded, are translated to
    list of characters. The inconsistency leads to wrong warnings about
    redundant and non-exhaustive pattern matching warnings, as reported
    in #14546.
    In order to catch the redundant pattern in following case:
      case "foo" of
          ('f':_) -> putStrLn "A"
          "bar" -> putStrLn "B"
    In this patch, we translate non-overloaded string literals, both in
    value position and pattern position, as list of characters. For
    overloaded string literals, we only translate it to list of characters
    only when it's type is `stringTy`, since we know nothing about the
    `toString` methods.  But we know that if two overloaded strings are
    syntax equal, then they are equal. Then if it's type is not `stringTy`,
    we just translate it to `PmOLit`. We can still capture the
    exhaustiveness of pattern `"foo"` and the redundancy of pattern `"bar"`
    and `"baz"` in the following code:
    {-# LANGUAGE OverloadedStrings #-}
    main = do
      case "foo" of
          "foo" -> putStrLn "A"
          "bar" -> putStrLn "B"
          "baz" -> putStrLn "C"
    Test Plan: make test TEST="T14546"
    Reviewers: bgamari, simonpj
    Reviewed By: bgamari, simonpj
    Subscribers: simonpj, thomie, carter
    GHC Trac Issues: #14546
    Differential Revision: https://phabricator.haskell.org/D4571


 compiler/deSugar/Check.hs                          | 163 ++++++++++++++-------
 compiler/deSugar/Match.hs                          |   2 +-
 compiler/deSugar/MatchLit.hs                       |  13 +-
 compiler/deSugar/PmExpr.hs                         |  35 ++++-
 testsuite/tests/deSugar/should_compile/T14546a.hs  |  29 ++++
 .../tests/deSugar/should_compile/T14546a.stderr    |  56 +++++++
 testsuite/tests/deSugar/should_compile/T14546b.hs  |  11 ++
 .../tests/deSugar/should_compile/T14546b.stderr    |  16 ++
 testsuite/tests/deSugar/should_compile/T14546c.hs  |  20 +++
 .../tests/deSugar/should_compile/T14546c.stderr    |  24 +++
 testsuite/tests/deSugar/should_compile/all.T       |   3 +
 .../tests/simplCore/should_compile/T9400.stderr    |   8 +
 12 files changed, 308 insertions(+), 72 deletions(-)

Diff suppressed because of size. To see it, use:

    git diff-tree --root --patch-with-stat --no-color --find-copies-harder --ignore-space-at-eol --cc 1f88f541aad1e36d01f22f9e71dfbc247e6558e2

More information about the ghc-commits mailing list