[GHC] #15681: Take {-# COMPLETE #-} pragma into consideration when using MonadFailDesugaring

GHC ghc-devs at haskell.org
Thu Sep 27 20:05:05 UTC 2018


#15681: Take {-# COMPLETE #-} pragma into consideration when using
MonadFailDesugaring
-------------------------------------+-------------------------------------
        Reporter:  chshersh          |                Owner:  (none)
            Type:  bug               |               Status:  new
        Priority:  normal            |            Milestone:  8.6.1
       Component:  Compiler          |              Version:  8.6.1
      Resolution:                    |             Keywords:  pattern-
                                     |  matching,monadfail,desugaring
Operating System:  Unknown/Multiple  |         Architecture:
                                     |  Unknown/Multiple
 Type of failure:  None/Unknown      |            Test Case:
      Blocked By:                    |             Blocking:
 Related Tickets:                    |  Differential Rev(s):
       Wiki Page:                    |
-------------------------------------+-------------------------------------

Comment (by RyanGlScott):

 Ah. This is because `isIrrefutableHsPat`, which determines is a pattern
 warrants a `MonadFail` constraint when matched upon in `do`-notation,
 [http://git.haskell.org/ghc.git/blob/1d7b61f97f9ec3780a1b7b5bf95a880d56224f4f:/compiler/hsSyn/HsPat.hs#l694
 treats pattern synonyms quite conservatively]:

 {{{#!hs
 isIrrefutableHsPat pat
   = go pat
   where
     go (L _ pat) = go1 pat
     ...
     go1 (ConPatOut{ pat_con = L _ (PatSynCon _pat) })
         = False -- Conservative
     ...
 }}}

 Compare the
 [http://git.haskell.org/ghc.git/blob/1d7b61f97f9ec3780a1b7b5bf95a880d56224f4f:/compiler/hsSyn/HsPat.hs#l689
 treatment] for plain old data constructors:

 {{{#!hs
     go1 (ConPatOut{ pat_con = L _ (RealDataCon con), pat_args = details })
         =  isJust (tyConSingleDataCon_maybe (dataConTyCon con))
         && all go (hsConPatArgs details)
 }}}

 This essentially says that a plain old data-constructor pattern match is
 irrefutable if its corresponding data type is inhabited by only one
 constructor.

 Could we do the same for pattern synonyms? We certainly could adapt the
 code for the `RealDataCon` case and reuse it for `PatSynCon`:

 {{{#!diff
 diff --git a/compiler/hsSyn/HsPat.hs b/compiler/hsSyn/HsPat.hs
 index 6f65487..c23c479 100644
 --- a/compiler/hsSyn/HsPat.hs
 +++ b/compiler/hsSyn/HsPat.hs
 @@ -57,6 +57,7 @@ import Var
  import RdrName ( RdrName )
  import ConLike
  import DataCon
 +import PatSyn
  import TyCon
  import Outputable
  import Type
 @@ -691,8 +692,13 @@ isIrrefutableHsPat pat
             -- NB: tyConSingleDataCon_maybe, *not* isProductTyCon, because
             -- the latter is false of existentials. See Trac #4439
          && all go (hsConPatArgs details)
 -    go1 (ConPatOut{ pat_con = L _ (PatSynCon _pat) })
 -        = False -- Conservative
 +    go1 (ConPatOut{ pat_con = L _ (PatSynCon pat), pat_args = details })
 +        |  (_, _, _, _, _, res_ty) <- patSynSig pat
 +        ,  Just tc <- tyConAppTyCon_maybe res_ty
 +        =  isJust (tyConSingleDataCon_maybe tc)
 +        && all go (hsConPatArgs details)
 +        |  otherwise
 +        =  False -- Conservative

      go1 (LitPat {})         = False
      go1 (NPat {})           = False
 }}}

 While this fixes the particular example in this ticket, it's a bit dodgy.
 That's because it's determining if a pattern synonym is irrefutable by
 consulting the plain old data constructors that correspond to the type
 constructor that heads its return type. This is a bit of an impedance
 mismatch since exhaustiveness checking for pattern synonyms can only ever
 really be done in the context of one or more user-defined `COMPLETE` sets.

 It's not clear to me if `isIrrefutableHsPat` could be changed to take
 `COMPLETE` sets into account. The code to look up `COMPLETE` sets,
 [http://git.haskell.org/ghc.git/blob/d00c308633fe7d216d31a1087e00e63532d87d6d:/compiler/deSugar/DsMonad.hs#l530
 dsGetCompleteMatches], lives in the `DsM` monad, while
 `isIrrefutableHsPat` is pure. Moreover, `isIrrefutableHsPat` has call
 sites that are outside of `DsM`, so it's unclear to me if we could factor
 out the monadic parts of `dsGetCompleteMatches`.

-- 
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/15681#comment:1>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler


More information about the ghc-tickets mailing list