[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