{-
(c) The University of Glasgow 2006
(c) The GRASP/AQUA Project, Glasgow University, 1992-1998


Pattern-matching constructors
-}

{-# LANGUAGE CPP #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE ViewPatterns #-}

module MatchCon ( matchConFamily, matchPatSyn ) where

#include "HsVersions.h"

import GhcPrelude

import {-# SOURCE #-} Match     ( match )

import GHC.Hs
import DsBinds
import ConLike
import BasicTypes ( Origin(..) )
import TcType
import DsMonad
import DsUtils
import MkCore   ( mkCoreLets )
import Util
import Id
import NameEnv
import FieldLabel ( flSelector )
import SrcLoc
import Outputable
import Control.Monad(liftM)
import Data.List (groupBy)

{-
We are confronted with the first column of patterns in a set of
equations, all beginning with constructors from one ``family'' (e.g.,
@[]@ and @:@ make up the @List@ ``family'').  We want to generate the
alternatives for a @Case@ expression.  There are several choices:
\begin{enumerate}
\item
Generate an alternative for every constructor in the family, whether
they are used in this set of equations or not; this is what the Wadler
chapter does.
\begin{description}
\item[Advantages:]
(a)~Simple.  (b)~It may also be that large sparsely-used constructor
families are mainly handled by the code for literals.
\item[Disadvantages:]
(a)~Not practical for large sparsely-used constructor families, e.g.,
the ASCII character set.  (b)~Have to look up a list of what
constructors make up the whole family.
\end{description}

\item
Generate an alternative for each constructor used, then add a default
alternative in case some constructors in the family weren't used.
\begin{description}
\item[Advantages:]
(a)~Alternatives aren't generated for unused constructors.  (b)~The
STG is quite happy with defaults.  (c)~No lookup in an environment needed.
\item[Disadvantages:]
(a)~A spurious default alternative may be generated.
\end{description}

\item
``Do it right:'' generate an alternative for each constructor used,
and add a default alternative if all constructors in the family
weren't used.
\begin{description}
\item[Advantages:]
(a)~You will get cases with only one alternative (and no default),
which should be amenable to optimisation.  Tuples are a common example.
\item[Disadvantages:]
(b)~Have to look up constructor families in TDE (as above).
\end{description}
\end{enumerate}

We are implementing the ``do-it-right'' option for now.  The arguments
to @matchConFamily@ are the same as to @match@; the extra @Int@
returned is the number of constructors in the family.

The function @matchConFamily@ is concerned with this
have-we-used-all-the-constructors? question; the local function
@match_cons_used@ does all the real work.
-}

matchConFamily :: [Id]
               -> Type
               -> [[EquationInfo]]
               -> DsM MatchResult
-- Each group of eqns is for a single constructor
matchConFamily :: [Id] -> Type -> [[EquationInfo]] -> DsM MatchResult
matchConFamily (Id
var:[Id]
vars) Type
ty [[EquationInfo]]
groups
  = do [CaseAlt DataCon]
alts <- ([EquationInfo] -> IOEnv (Env DsGblEnv DsLclEnv) (CaseAlt DataCon))
-> [[EquationInfo]]
-> IOEnv (Env DsGblEnv DsLclEnv) [CaseAlt DataCon]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM ((CaseAlt ConLike -> CaseAlt DataCon)
-> IOEnv (Env DsGblEnv DsLclEnv) (CaseAlt ConLike)
-> IOEnv (Env DsGblEnv DsLclEnv) (CaseAlt DataCon)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap CaseAlt ConLike -> CaseAlt DataCon
toRealAlt (IOEnv (Env DsGblEnv DsLclEnv) (CaseAlt ConLike)
 -> IOEnv (Env DsGblEnv DsLclEnv) (CaseAlt DataCon))
-> ([EquationInfo]
    -> IOEnv (Env DsGblEnv DsLclEnv) (CaseAlt ConLike))
-> [EquationInfo]
-> IOEnv (Env DsGblEnv DsLclEnv) (CaseAlt DataCon)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Id]
-> Type
-> [EquationInfo]
-> IOEnv (Env DsGblEnv DsLclEnv) (CaseAlt ConLike)
matchOneConLike [Id]
vars Type
ty) [[EquationInfo]]
groups
       MatchResult -> DsM MatchResult
forall (m :: * -> *) a. Monad m => a -> m a
return (Id -> Type -> [CaseAlt DataCon] -> MatchResult
mkCoAlgCaseMatchResult Id
var Type
ty [CaseAlt DataCon]
alts)
  where
    toRealAlt :: CaseAlt ConLike -> CaseAlt DataCon
toRealAlt CaseAlt ConLike
alt = case CaseAlt ConLike -> ConLike
forall a. CaseAlt a -> a
alt_pat CaseAlt ConLike
alt of
        RealDataCon DataCon
dcon -> CaseAlt ConLike
alt{ alt_pat :: DataCon
alt_pat = DataCon
dcon }
        ConLike
_ -> String -> CaseAlt DataCon
forall a. String -> a
panic String
"matchConFamily: not RealDataCon"
matchConFamily [] Type
_ [[EquationInfo]]
_ = String -> DsM MatchResult
forall a. String -> a
panic String
"matchConFamily []"

matchPatSyn :: [Id]
            -> Type
            -> [EquationInfo]
            -> DsM MatchResult
matchPatSyn :: [Id] -> Type -> [EquationInfo] -> DsM MatchResult
matchPatSyn (Id
var:[Id]
vars) Type
ty [EquationInfo]
eqns
  = do CaseAlt PatSyn
alt <- (CaseAlt ConLike -> CaseAlt PatSyn)
-> IOEnv (Env DsGblEnv DsLclEnv) (CaseAlt ConLike)
-> IOEnv (Env DsGblEnv DsLclEnv) (CaseAlt PatSyn)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap CaseAlt ConLike -> CaseAlt PatSyn
toSynAlt (IOEnv (Env DsGblEnv DsLclEnv) (CaseAlt ConLike)
 -> IOEnv (Env DsGblEnv DsLclEnv) (CaseAlt PatSyn))
-> IOEnv (Env DsGblEnv DsLclEnv) (CaseAlt ConLike)
-> IOEnv (Env DsGblEnv DsLclEnv) (CaseAlt PatSyn)
forall a b. (a -> b) -> a -> b
$ [Id]
-> Type
-> [EquationInfo]
-> IOEnv (Env DsGblEnv DsLclEnv) (CaseAlt ConLike)
matchOneConLike [Id]
vars Type
ty [EquationInfo]
eqns
       MatchResult -> DsM MatchResult
forall (m :: * -> *) a. Monad m => a -> m a
return (Id -> Type -> CaseAlt PatSyn -> MatchResult
mkCoSynCaseMatchResult Id
var Type
ty CaseAlt PatSyn
alt)
  where
    toSynAlt :: CaseAlt ConLike -> CaseAlt PatSyn
toSynAlt CaseAlt ConLike
alt = case CaseAlt ConLike -> ConLike
forall a. CaseAlt a -> a
alt_pat CaseAlt ConLike
alt of
        PatSynCon PatSyn
psyn -> CaseAlt ConLike
alt{ alt_pat :: PatSyn
alt_pat = PatSyn
psyn }
        ConLike
_ -> String -> CaseAlt PatSyn
forall a. String -> a
panic String
"matchPatSyn: not PatSynCon"
matchPatSyn [Id]
_ Type
_ [EquationInfo]
_ = String -> DsM MatchResult
forall a. String -> a
panic String
"matchPatSyn []"

type ConArgPats = HsConDetails (LPat GhcTc) (HsRecFields GhcTc (LPat GhcTc))

matchOneConLike :: [Id]
                -> Type
                -> [EquationInfo]
                -> DsM (CaseAlt ConLike)
matchOneConLike :: [Id]
-> Type
-> [EquationInfo]
-> IOEnv (Env DsGblEnv DsLclEnv) (CaseAlt ConLike)
matchOneConLike [Id]
vars Type
ty (EquationInfo
eqn1 : [EquationInfo]
eqns)   -- All eqns for a single constructor
  = do  { let inst_tys :: [Type]
inst_tys = ASSERT( all tcIsTcTyVar ex_tvs )
                           -- ex_tvs can only be tyvars as data types in source
                           -- Haskell cannot mention covar yet (Aug 2018).
                         ASSERT( tvs1 `equalLength` ex_tvs )
                         [Type]
arg_tys [Type] -> [Type] -> [Type]
forall a. [a] -> [a] -> [a]
++ [Id] -> [Type]
mkTyVarTys [Id]
tvs1

              val_arg_tys :: [Type]
val_arg_tys = ConLike -> [Type] -> [Type]
conLikeInstOrigArgTys SrcSpanLess (Located ConLike)
ConLike
con1 [Type]
inst_tys
        -- dataConInstOrigArgTys takes the univ and existential tyvars
        -- and returns the types of the *value* args, which is what we want

              match_group :: [Id]
                          -> [(ConArgPats, EquationInfo)] -> DsM MatchResult
              -- All members of the group have compatible ConArgPats
              match_group :: [Id] -> [(ConArgPats, EquationInfo)] -> DsM MatchResult
match_group [Id]
arg_vars [(ConArgPats, EquationInfo)]
arg_eqn_prs
                = ASSERT( notNull arg_eqn_prs )
                  do { ([CoreExpr -> CoreExpr]
wraps, [EquationInfo]
eqns') <- ([(CoreExpr -> CoreExpr, EquationInfo)]
 -> ([CoreExpr -> CoreExpr], [EquationInfo]))
-> IOEnv
     (Env DsGblEnv DsLclEnv) [(CoreExpr -> CoreExpr, EquationInfo)]
-> IOEnv
     (Env DsGblEnv DsLclEnv) ([CoreExpr -> CoreExpr], [EquationInfo])
forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
liftM [(CoreExpr -> CoreExpr, EquationInfo)]
-> ([CoreExpr -> CoreExpr], [EquationInfo])
forall a b. [(a, b)] -> ([a], [b])
unzip (((HsConDetails
    (Located (Pat (GhcPass 'Typechecked)))
    (HsRecFields
       (GhcPass 'Typechecked) (Located (Pat (GhcPass 'Typechecked)))),
  EquationInfo)
 -> IOEnv
      (Env DsGblEnv DsLclEnv) (CoreExpr -> CoreExpr, EquationInfo))
-> [(HsConDetails
       (Located (Pat (GhcPass 'Typechecked)))
       (HsRecFields
          (GhcPass 'Typechecked) (Located (Pat (GhcPass 'Typechecked)))),
     EquationInfo)]
-> IOEnv
     (Env DsGblEnv DsLclEnv) [(CoreExpr -> CoreExpr, EquationInfo)]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM (HsConDetails
   (Located (Pat (GhcPass 'Typechecked)))
   (HsRecFields
      (GhcPass 'Typechecked) (Located (Pat (GhcPass 'Typechecked)))),
 EquationInfo)
-> IOEnv
     (Env DsGblEnv DsLclEnv) (CoreExpr -> CoreExpr, EquationInfo)
shift [(HsConDetails
    (Located (Pat (GhcPass 'Typechecked)))
    (HsRecFields
       (GhcPass 'Typechecked) (Located (Pat (GhcPass 'Typechecked)))),
  EquationInfo)]
[(ConArgPats, EquationInfo)]
arg_eqn_prs)
                     ; let group_arg_vars :: [Id]
group_arg_vars = [Id] -> [(ConArgPats, EquationInfo)] -> [Id]
select_arg_vars [Id]
arg_vars [(ConArgPats, EquationInfo)]
arg_eqn_prs
                     ; MatchResult
match_result <- [Id] -> Type -> [EquationInfo] -> DsM MatchResult
match ([Id]
group_arg_vars [Id] -> [Id] -> [Id]
forall a. [a] -> [a] -> [a]
++ [Id]
vars) Type
ty [EquationInfo]
eqns'
                     ; MatchResult -> DsM MatchResult
forall (m :: * -> *) a. Monad m => a -> m a
return ((CoreExpr -> CoreExpr) -> MatchResult -> MatchResult
adjustMatchResult (((CoreExpr -> CoreExpr)
 -> (CoreExpr -> CoreExpr) -> CoreExpr -> CoreExpr)
-> [CoreExpr -> CoreExpr] -> CoreExpr -> CoreExpr
forall (t :: * -> *) a. Foldable t => (a -> a -> a) -> t a -> a
foldr1 (CoreExpr -> CoreExpr)
-> (CoreExpr -> CoreExpr) -> CoreExpr -> CoreExpr
forall b c a. (b -> c) -> (a -> b) -> a -> c
(.) [CoreExpr -> CoreExpr]
wraps) MatchResult
match_result) }

              shift :: (HsConDetails
   (Located (Pat (GhcPass 'Typechecked)))
   (HsRecFields
      (GhcPass 'Typechecked) (Located (Pat (GhcPass 'Typechecked)))),
 EquationInfo)
-> IOEnv
     (Env DsGblEnv DsLclEnv) (CoreExpr -> CoreExpr, EquationInfo)
shift (HsConDetails
  (Located (Pat (GhcPass 'Typechecked)))
  (HsRecFields
     (GhcPass 'Typechecked) (Located (Pat (GhcPass 'Typechecked))))
_, eqn :: EquationInfo
eqn@(EqnInfo { eqn_pats :: EquationInfo -> [Pat (GhcPass 'Typechecked)]
eqn_pats = ConPatOut{ pat_tvs :: forall p. Pat p -> [Id]
pat_tvs = [Id]
tvs, pat_dicts :: forall p. Pat p -> [Id]
pat_dicts = [Id]
ds,
                                                             pat_binds :: forall p. Pat p -> TcEvBinds
pat_binds = TcEvBinds
bind, pat_args :: forall p. Pat p -> HsConPatDetails p
pat_args = ConArgPats
args
                                                  } : [Pat (GhcPass 'Typechecked)]
pats }))
                = do [CoreBind]
ds_bind <- TcEvBinds -> DsM [CoreBind]
dsTcEvBinds TcEvBinds
bind
                     (CoreExpr -> CoreExpr, EquationInfo)
-> IOEnv
     (Env DsGblEnv DsLclEnv) (CoreExpr -> CoreExpr, EquationInfo)
forall (m :: * -> *) a. Monad m => a -> m a
return ( [(Id, Id)] -> CoreExpr -> CoreExpr
wrapBinds ([Id]
tvs [Id] -> [Id] -> [(Id, Id)]
forall a b. [a] -> [b] -> [(a, b)]
`zip` [Id]
tvs1)
                            (CoreExpr -> CoreExpr)
-> (CoreExpr -> CoreExpr) -> CoreExpr -> CoreExpr
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [(Id, Id)] -> CoreExpr -> CoreExpr
wrapBinds ([Id]
ds  [Id] -> [Id] -> [(Id, Id)]
forall a b. [a] -> [b] -> [(a, b)]
`zip` [Id]
dicts1)
                            (CoreExpr -> CoreExpr)
-> (CoreExpr -> CoreExpr) -> CoreExpr -> CoreExpr
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [CoreBind] -> CoreExpr -> CoreExpr
mkCoreLets [CoreBind]
ds_bind
                            , EquationInfo
eqn { eqn_orig :: Origin
eqn_orig = Origin
Generated
                                  , eqn_pats :: [Pat (GhcPass 'Typechecked)]
eqn_pats = [Type] -> ConArgPats -> [Pat (GhcPass 'Typechecked)]
conArgPats [Type]
val_arg_tys ConArgPats
args [Pat (GhcPass 'Typechecked)]
-> [Pat (GhcPass 'Typechecked)] -> [Pat (GhcPass 'Typechecked)]
forall a. [a] -> [a] -> [a]
++ [Pat (GhcPass 'Typechecked)]
pats }
                            )
              shift (HsConDetails
  (Located (Pat (GhcPass 'Typechecked)))
  (HsRecFields
     (GhcPass 'Typechecked) (Located (Pat (GhcPass 'Typechecked))))
_, (EqnInfo { eqn_pats :: EquationInfo -> [Pat (GhcPass 'Typechecked)]
eqn_pats = [Pat (GhcPass 'Typechecked)]
ps })) = String
-> SDoc
-> IOEnv
     (Env DsGblEnv DsLclEnv) (CoreExpr -> CoreExpr, EquationInfo)
forall a. HasCallStack => String -> SDoc -> a
pprPanic String
"matchOneCon/shift" ([Pat (GhcPass 'Typechecked)] -> SDoc
forall a. Outputable a => a -> SDoc
ppr [Pat (GhcPass 'Typechecked)]
ps)

        ; [Id]
arg_vars <- [Type] -> ConArgPats -> DsM [Id]
selectConMatchVars [Type]
val_arg_tys ConArgPats
args1
                -- Use the first equation as a source of
                -- suggestions for the new variables

        -- Divide into sub-groups; see Note [Record patterns]
        ; let groups :: [[(ConArgPats, EquationInfo)]]
              groups :: [[(ConArgPats, EquationInfo)]]
groups = ((HsConDetails
    (Located (Pat (GhcPass 'Typechecked)))
    (HsRecFields
       (GhcPass 'Typechecked) (Located (Pat (GhcPass 'Typechecked)))),
  EquationInfo)
 -> (HsConDetails
       (Located (Pat (GhcPass 'Typechecked)))
       (HsRecFields
          (GhcPass 'Typechecked) (Located (Pat (GhcPass 'Typechecked)))),
     EquationInfo)
 -> Bool)
-> [(HsConDetails
       (Located (Pat (GhcPass 'Typechecked)))
       (HsRecFields
          (GhcPass 'Typechecked) (Located (Pat (GhcPass 'Typechecked)))),
     EquationInfo)]
-> [[(HsConDetails
        (Located (Pat (GhcPass 'Typechecked)))
        (HsRecFields
           (GhcPass 'Typechecked) (Located (Pat (GhcPass 'Typechecked)))),
      EquationInfo)]]
forall a. (a -> a -> Bool) -> [a] -> [[a]]
groupBy (HsConDetails
   (Located (Pat (GhcPass 'Typechecked)))
   (HsRecFields
      (GhcPass 'Typechecked) (Located (Pat (GhcPass 'Typechecked)))),
 EquationInfo)
-> (HsConDetails
      (Located (Pat (GhcPass 'Typechecked)))
      (HsRecFields
         (GhcPass 'Typechecked) (Located (Pat (GhcPass 'Typechecked)))),
    EquationInfo)
-> Bool
forall a. (ConArgPats, a) -> (ConArgPats, a) -> Bool
compatible_pats [ (Pat (GhcPass 'Typechecked) -> ConArgPats
forall p. Pat p -> HsConPatDetails p
pat_args (EquationInfo -> Pat (GhcPass 'Typechecked)
firstPat EquationInfo
eqn), EquationInfo
eqn)
                                               | EquationInfo
eqn <- EquationInfo
eqn1EquationInfo -> [EquationInfo] -> [EquationInfo]
forall a. a -> [a] -> [a]
:[EquationInfo]
eqns ]

        ; [MatchResult]
match_results <- ([(HsConDetails
     (Located (Pat (GhcPass 'Typechecked)))
     (HsRecFields
        (GhcPass 'Typechecked) (Located (Pat (GhcPass 'Typechecked)))),
   EquationInfo)]
 -> DsM MatchResult)
-> [[(HsConDetails
        (Located (Pat (GhcPass 'Typechecked)))
        (HsRecFields
           (GhcPass 'Typechecked) (Located (Pat (GhcPass 'Typechecked)))),
      EquationInfo)]]
-> IOEnv (Env DsGblEnv DsLclEnv) [MatchResult]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM ([Id] -> [(ConArgPats, EquationInfo)] -> DsM MatchResult
match_group [Id]
arg_vars) [[(HsConDetails
     (Located (Pat (GhcPass 'Typechecked)))
     (HsRecFields
        (GhcPass 'Typechecked) (Located (Pat (GhcPass 'Typechecked)))),
   EquationInfo)]]
[[(ConArgPats, EquationInfo)]]
groups

        ; CaseAlt ConLike -> IOEnv (Env DsGblEnv DsLclEnv) (CaseAlt ConLike)
forall (m :: * -> *) a. Monad m => a -> m a
return (CaseAlt ConLike
 -> IOEnv (Env DsGblEnv DsLclEnv) (CaseAlt ConLike))
-> CaseAlt ConLike
-> IOEnv (Env DsGblEnv DsLclEnv) (CaseAlt ConLike)
forall a b. (a -> b) -> a -> b
$ MkCaseAlt :: forall a. a -> [Id] -> HsWrapper -> MatchResult -> CaseAlt a
MkCaseAlt{ alt_pat :: ConLike
alt_pat = SrcSpanLess (Located ConLike)
ConLike
con1,
                              alt_bndrs :: [Id]
alt_bndrs = [Id]
tvs1 [Id] -> [Id] -> [Id]
forall a. [a] -> [a] -> [a]
++ [Id]
dicts1 [Id] -> [Id] -> [Id]
forall a. [a] -> [a] -> [a]
++ [Id]
arg_vars,
                              alt_wrapper :: HsWrapper
alt_wrapper = HsWrapper
wrapper1,
                              alt_result :: MatchResult
alt_result = (MatchResult -> MatchResult -> MatchResult)
-> [MatchResult] -> MatchResult
forall (t :: * -> *) a. Foldable t => (a -> a -> a) -> t a -> a
foldr1 MatchResult -> MatchResult -> MatchResult
combineMatchResults [MatchResult]
match_results } }
  where
    ConPatOut { pat_con :: forall p. Pat p -> Located ConLike
pat_con = (Located ConLike -> Located (SrcSpanLess (Located ConLike))
forall a. HasSrcSpan a => a -> Located (SrcSpanLess a)
dL->L SrcSpan
_ SrcSpanLess (Located ConLike)
con1)
              , pat_arg_tys :: forall p. Pat p -> [Type]
pat_arg_tys = [Type]
arg_tys, pat_wrap :: forall p. Pat p -> HsWrapper
pat_wrap = HsWrapper
wrapper1,
                pat_tvs :: forall p. Pat p -> [Id]
pat_tvs = [Id]
tvs1, pat_dicts :: forall p. Pat p -> [Id]
pat_dicts = [Id]
dicts1, pat_args :: forall p. Pat p -> HsConPatDetails p
pat_args = ConArgPats
args1 }
              = EquationInfo -> Pat (GhcPass 'Typechecked)
firstPat EquationInfo
eqn1
    fields1 :: [Name]
fields1 = (FieldLbl Name -> Name) -> [FieldLbl Name] -> [Name]
forall a b. (a -> b) -> [a] -> [b]
map FieldLbl Name -> Name
forall a. FieldLbl a -> a
flSelector (ConLike -> [FieldLbl Name]
conLikeFieldLabels SrcSpanLess (Located ConLike)
ConLike
con1)

    ex_tvs :: [Id]
ex_tvs = ConLike -> [Id]
conLikeExTyCoVars SrcSpanLess (Located ConLike)
ConLike
con1

    -- Choose the right arg_vars in the right order for this group
    -- Note [Record patterns]
    select_arg_vars :: [Id] -> [(ConArgPats, EquationInfo)] -> [Id]
    select_arg_vars :: [Id] -> [(ConArgPats, EquationInfo)] -> [Id]
select_arg_vars [Id]
arg_vars ((ConArgPats
arg_pats, EquationInfo
_) : [(ConArgPats, EquationInfo)]
_)
      | RecCon HsRecFields (GhcPass 'Typechecked) (LPat (GhcPass 'Typechecked))
flds <- ConArgPats
arg_pats
      , let rpats :: [LHsRecField
   (GhcPass 'Typechecked) (Located (Pat (GhcPass 'Typechecked)))]
rpats = HsRecFields
  (GhcPass 'Typechecked) (Located (Pat (GhcPass 'Typechecked)))
-> [LHsRecField
      (GhcPass 'Typechecked) (Located (Pat (GhcPass 'Typechecked)))]
forall p arg. HsRecFields p arg -> [LHsRecField p arg]
rec_flds HsRecFields
  (GhcPass 'Typechecked) (Located (Pat (GhcPass 'Typechecked)))
HsRecFields (GhcPass 'Typechecked) (LPat (GhcPass 'Typechecked))
flds
      , Bool -> Bool
not ([LHsRecField
   (GhcPass 'Typechecked) (Located (Pat (GhcPass 'Typechecked)))]
-> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [LHsRecField
   (GhcPass 'Typechecked) (Located (Pat (GhcPass 'Typechecked)))]
rpats)     -- Treated specially; cf conArgPats
      = ASSERT2( fields1 `equalLength` arg_vars,
                 ppr con1 $$ ppr fields1 $$ ppr arg_vars )
        (LHsRecField
   (GhcPass 'Typechecked) (Located (Pat (GhcPass 'Typechecked)))
 -> Id)
-> [LHsRecField
      (GhcPass 'Typechecked) (Located (Pat (GhcPass 'Typechecked)))]
-> [Id]
forall a b. (a -> b) -> [a] -> [b]
map LHsRecField
  (GhcPass 'Typechecked) (Located (Pat (GhcPass 'Typechecked)))
-> Id
lookup_fld [LHsRecField
   (GhcPass 'Typechecked) (Located (Pat (GhcPass 'Typechecked)))]
rpats
      | Bool
otherwise
      = [Id]
arg_vars
      where
        fld_var_env :: NameEnv Id
fld_var_env = [(Name, Id)] -> NameEnv Id
forall a. [(Name, a)] -> NameEnv a
mkNameEnv ([(Name, Id)] -> NameEnv Id) -> [(Name, Id)] -> NameEnv Id
forall a b. (a -> b) -> a -> b
$ String -> [Name] -> [Id] -> [(Name, Id)]
forall a b. String -> [a] -> [b] -> [(a, b)]
zipEqual String
"get_arg_vars" [Name]
fields1 [Id]
arg_vars
        lookup_fld :: LHsRecField
  (GhcPass 'Typechecked) (Located (Pat (GhcPass 'Typechecked)))
-> Id
lookup_fld (LHsRecField
  (GhcPass 'Typechecked) (Located (Pat (GhcPass 'Typechecked)))
-> Located
     (SrcSpanLess
        (LHsRecField
           (GhcPass 'Typechecked) (Located (Pat (GhcPass 'Typechecked)))))
forall a. HasSrcSpan a => a -> Located (SrcSpanLess a)
dL->L SrcSpan
_ SrcSpanLess
  (LHsRecField
     (GhcPass 'Typechecked) (Located (Pat (GhcPass 'Typechecked))))
rpat) = NameEnv Id -> Name -> Id
forall a. NameEnv a -> Name -> a
lookupNameEnv_NF NameEnv Id
fld_var_env
                                            (Id -> Name
idName (Located Id -> SrcSpanLess (Located Id)
forall a. HasSrcSpan a => a -> SrcSpanLess a
unLoc (HsRecField
  (GhcPass 'Typechecked) (Located (Pat (GhcPass 'Typechecked)))
-> Located Id
forall arg. HsRecField (GhcPass 'Typechecked) arg -> Located Id
hsRecFieldId SrcSpanLess
  (LHsRecField
     (GhcPass 'Typechecked) (Located (Pat (GhcPass 'Typechecked))))
HsRecField
  (GhcPass 'Typechecked) (Located (Pat (GhcPass 'Typechecked)))
rpat)))
    select_arg_vars [Id]
_ [] = String -> [Id]
forall a. String -> a
panic String
"matchOneCon/select_arg_vars []"
matchOneConLike [Id]
_ Type
_ [] = String -> IOEnv (Env DsGblEnv DsLclEnv) (CaseAlt ConLike)
forall a. String -> a
panic String
"matchOneCon []"

-----------------
compatible_pats :: (ConArgPats,a) -> (ConArgPats,a) -> Bool
-- Two constructors have compatible argument patterns if the number
-- and order of sub-matches is the same in both cases
compatible_pats :: (ConArgPats, a) -> (ConArgPats, a) -> Bool
compatible_pats (RecCon HsRecFields (GhcPass 'Typechecked) (LPat (GhcPass 'Typechecked))
flds1, a
_) (RecCon HsRecFields (GhcPass 'Typechecked) (LPat (GhcPass 'Typechecked))
flds2, a
_) = HsRecFields (GhcPass 'Typechecked) (LPat (GhcPass 'Typechecked))
-> HsRecFields (GhcPass 'Typechecked) (LPat (GhcPass 'Typechecked))
-> Bool
same_fields HsRecFields (GhcPass 'Typechecked) (LPat (GhcPass 'Typechecked))
flds1 HsRecFields (GhcPass 'Typechecked) (LPat (GhcPass 'Typechecked))
flds2
compatible_pats (RecCon HsRecFields (GhcPass 'Typechecked) (LPat (GhcPass 'Typechecked))
flds1, a
_) (ConArgPats, a)
_                 = [LHsRecField
   (GhcPass 'Typechecked) (Located (Pat (GhcPass 'Typechecked)))]
-> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null (HsRecFields
  (GhcPass 'Typechecked) (Located (Pat (GhcPass 'Typechecked)))
-> [LHsRecField
      (GhcPass 'Typechecked) (Located (Pat (GhcPass 'Typechecked)))]
forall p arg. HsRecFields p arg -> [LHsRecField p arg]
rec_flds HsRecFields
  (GhcPass 'Typechecked) (Located (Pat (GhcPass 'Typechecked)))
HsRecFields (GhcPass 'Typechecked) (LPat (GhcPass 'Typechecked))
flds1)
compatible_pats (ConArgPats, a)
_                 (RecCon HsRecFields (GhcPass 'Typechecked) (LPat (GhcPass 'Typechecked))
flds2, a
_) = [LHsRecField
   (GhcPass 'Typechecked) (Located (Pat (GhcPass 'Typechecked)))]
-> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null (HsRecFields
  (GhcPass 'Typechecked) (Located (Pat (GhcPass 'Typechecked)))
-> [LHsRecField
      (GhcPass 'Typechecked) (Located (Pat (GhcPass 'Typechecked)))]
forall p arg. HsRecFields p arg -> [LHsRecField p arg]
rec_flds HsRecFields
  (GhcPass 'Typechecked) (Located (Pat (GhcPass 'Typechecked)))
HsRecFields (GhcPass 'Typechecked) (LPat (GhcPass 'Typechecked))
flds2)
compatible_pats (ConArgPats, a)
_                 (ConArgPats, a)
_                 = Bool
True -- Prefix or infix con

same_fields :: HsRecFields GhcTc (LPat GhcTc) -> HsRecFields GhcTc (LPat GhcTc)
            -> Bool
same_fields :: HsRecFields (GhcPass 'Typechecked) (LPat (GhcPass 'Typechecked))
-> HsRecFields (GhcPass 'Typechecked) (LPat (GhcPass 'Typechecked))
-> Bool
same_fields HsRecFields (GhcPass 'Typechecked) (LPat (GhcPass 'Typechecked))
flds1 HsRecFields (GhcPass 'Typechecked) (LPat (GhcPass 'Typechecked))
flds2
  = (LHsRecField
   (GhcPass 'Typechecked) (Located (Pat (GhcPass 'Typechecked)))
 -> LHsRecField
      (GhcPass 'Typechecked) (Located (Pat (GhcPass 'Typechecked)))
 -> Bool)
-> [LHsRecField
      (GhcPass 'Typechecked) (Located (Pat (GhcPass 'Typechecked)))]
-> [LHsRecField
      (GhcPass 'Typechecked) (Located (Pat (GhcPass 'Typechecked)))]
-> Bool
forall a b. (a -> b -> Bool) -> [a] -> [b] -> Bool
all2 (\(LHsRecField
  (GhcPass 'Typechecked) (Located (Pat (GhcPass 'Typechecked)))
-> Located
     (SrcSpanLess
        (LHsRecField
           (GhcPass 'Typechecked) (Located (Pat (GhcPass 'Typechecked)))))
forall a. HasSrcSpan a => a -> Located (SrcSpanLess a)
dL->L SrcSpan
_ SrcSpanLess
  (LHsRecField
     (GhcPass 'Typechecked) (Located (Pat (GhcPass 'Typechecked))))
f1) (LHsRecField
  (GhcPass 'Typechecked) (Located (Pat (GhcPass 'Typechecked)))
-> Located
     (SrcSpanLess
        (LHsRecField
           (GhcPass 'Typechecked) (Located (Pat (GhcPass 'Typechecked)))))
forall a. HasSrcSpan a => a -> Located (SrcSpanLess a)
dL->L SrcSpan
_ SrcSpanLess
  (LHsRecField
     (GhcPass 'Typechecked) (Located (Pat (GhcPass 'Typechecked))))
f2)
                          -> Located Id -> SrcSpanLess (Located Id)
forall a. HasSrcSpan a => a -> SrcSpanLess a
unLoc (HsRecField
  (GhcPass 'Typechecked) (Located (Pat (GhcPass 'Typechecked)))
-> Located Id
forall arg. HsRecField (GhcPass 'Typechecked) arg -> Located Id
hsRecFieldId SrcSpanLess
  (LHsRecField
     (GhcPass 'Typechecked) (Located (Pat (GhcPass 'Typechecked))))
HsRecField
  (GhcPass 'Typechecked) (Located (Pat (GhcPass 'Typechecked)))
f1) Id -> Id -> Bool
forall a. Eq a => a -> a -> Bool
== Located Id -> SrcSpanLess (Located Id)
forall a. HasSrcSpan a => a -> SrcSpanLess a
unLoc (HsRecField
  (GhcPass 'Typechecked) (Located (Pat (GhcPass 'Typechecked)))
-> Located Id
forall arg. HsRecField (GhcPass 'Typechecked) arg -> Located Id
hsRecFieldId SrcSpanLess
  (LHsRecField
     (GhcPass 'Typechecked) (Located (Pat (GhcPass 'Typechecked))))
HsRecField
  (GhcPass 'Typechecked) (Located (Pat (GhcPass 'Typechecked)))
f2))
         (HsRecFields
  (GhcPass 'Typechecked) (Located (Pat (GhcPass 'Typechecked)))
-> [LHsRecField
      (GhcPass 'Typechecked) (Located (Pat (GhcPass 'Typechecked)))]
forall p arg. HsRecFields p arg -> [LHsRecField p arg]
rec_flds HsRecFields
  (GhcPass 'Typechecked) (Located (Pat (GhcPass 'Typechecked)))
HsRecFields (GhcPass 'Typechecked) (LPat (GhcPass 'Typechecked))
flds1) (HsRecFields
  (GhcPass 'Typechecked) (Located (Pat (GhcPass 'Typechecked)))
-> [LHsRecField
      (GhcPass 'Typechecked) (Located (Pat (GhcPass 'Typechecked)))]
forall p arg. HsRecFields p arg -> [LHsRecField p arg]
rec_flds HsRecFields
  (GhcPass 'Typechecked) (Located (Pat (GhcPass 'Typechecked)))
HsRecFields (GhcPass 'Typechecked) (LPat (GhcPass 'Typechecked))
flds2)


-----------------
selectConMatchVars :: [Type] -> ConArgPats -> DsM [Id]
selectConMatchVars :: [Type] -> ConArgPats -> DsM [Id]
selectConMatchVars [Type]
arg_tys (RecCon {})      = [Type] -> DsM [Id]
newSysLocalsDsNoLP [Type]
arg_tys
selectConMatchVars [Type]
_       (PrefixCon [LPat (GhcPass 'Typechecked)]
ps)   = [Pat (GhcPass 'Typechecked)] -> DsM [Id]
selectMatchVars ((Located (Pat (GhcPass 'Typechecked))
 -> Pat (GhcPass 'Typechecked))
-> [Located (Pat (GhcPass 'Typechecked))]
-> [Pat (GhcPass 'Typechecked)]
forall a b. (a -> b) -> [a] -> [b]
map Located (Pat (GhcPass 'Typechecked)) -> Pat (GhcPass 'Typechecked)
forall a. HasSrcSpan a => a -> SrcSpanLess a
unLoc [Located (Pat (GhcPass 'Typechecked))]
[LPat (GhcPass 'Typechecked)]
ps)
selectConMatchVars [Type]
_       (InfixCon LPat (GhcPass 'Typechecked)
p1 LPat (GhcPass 'Typechecked)
p2) = [Pat (GhcPass 'Typechecked)] -> DsM [Id]
selectMatchVars [Located (Pat (GhcPass 'Typechecked))
-> SrcSpanLess (Located (Pat (GhcPass 'Typechecked)))
forall a. HasSrcSpan a => a -> SrcSpanLess a
unLoc Located (Pat (GhcPass 'Typechecked))
LPat (GhcPass 'Typechecked)
p1, Located (Pat (GhcPass 'Typechecked))
-> SrcSpanLess (Located (Pat (GhcPass 'Typechecked)))
forall a. HasSrcSpan a => a -> SrcSpanLess a
unLoc Located (Pat (GhcPass 'Typechecked))
LPat (GhcPass 'Typechecked)
p2]

conArgPats :: [Type]      -- Instantiated argument types
                          -- Used only to fill in the types of WildPats, which
                          -- are probably never looked at anyway
           -> ConArgPats
           -> [Pat GhcTc]
conArgPats :: [Type] -> ConArgPats -> [Pat (GhcPass 'Typechecked)]
conArgPats [Type]
_arg_tys (PrefixCon [LPat (GhcPass 'Typechecked)]
ps)   = (Located (Pat (GhcPass 'Typechecked))
 -> Pat (GhcPass 'Typechecked))
-> [Located (Pat (GhcPass 'Typechecked))]
-> [Pat (GhcPass 'Typechecked)]
forall a b. (a -> b) -> [a] -> [b]
map Located (Pat (GhcPass 'Typechecked)) -> Pat (GhcPass 'Typechecked)
forall a. HasSrcSpan a => a -> SrcSpanLess a
unLoc [Located (Pat (GhcPass 'Typechecked))]
[LPat (GhcPass 'Typechecked)]
ps
conArgPats [Type]
_arg_tys (InfixCon LPat (GhcPass 'Typechecked)
p1 LPat (GhcPass 'Typechecked)
p2) = [Located (Pat (GhcPass 'Typechecked))
-> SrcSpanLess (Located (Pat (GhcPass 'Typechecked)))
forall a. HasSrcSpan a => a -> SrcSpanLess a
unLoc Located (Pat (GhcPass 'Typechecked))
LPat (GhcPass 'Typechecked)
p1, Located (Pat (GhcPass 'Typechecked))
-> SrcSpanLess (Located (Pat (GhcPass 'Typechecked)))
forall a. HasSrcSpan a => a -> SrcSpanLess a
unLoc Located (Pat (GhcPass 'Typechecked))
LPat (GhcPass 'Typechecked)
p2]
conArgPats  [Type]
arg_tys (RecCon (HsRecFields { rec_flds :: forall p arg. HsRecFields p arg -> [LHsRecField p arg]
rec_flds = [LHsRecField (GhcPass 'Typechecked) (LPat (GhcPass 'Typechecked))]
rpats }))
  | [LHsRecField
   (GhcPass 'Typechecked) (Located (Pat (GhcPass 'Typechecked)))]
-> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [LHsRecField
   (GhcPass 'Typechecked) (Located (Pat (GhcPass 'Typechecked)))]
[LHsRecField (GhcPass 'Typechecked) (LPat (GhcPass 'Typechecked))]
rpats = (Type -> Pat (GhcPass 'Typechecked))
-> [Type] -> [Pat (GhcPass 'Typechecked)]
forall a b. (a -> b) -> [a] -> [b]
map Type -> Pat (GhcPass 'Typechecked)
forall p. XWildPat p -> Pat p
WildPat [Type]
arg_tys
        -- Important special case for C {}, which can be used for a
        -- datacon that isn't declared to have fields at all
  | Bool
otherwise  = (LHsRecField
   (GhcPass 'Typechecked) (Located (Pat (GhcPass 'Typechecked)))
 -> Pat (GhcPass 'Typechecked))
-> [LHsRecField
      (GhcPass 'Typechecked) (Located (Pat (GhcPass 'Typechecked)))]
-> [Pat (GhcPass 'Typechecked)]
forall a b. (a -> b) -> [a] -> [b]
map (Located (Pat (GhcPass 'Typechecked)) -> Pat (GhcPass 'Typechecked)
forall a. HasSrcSpan a => a -> SrcSpanLess a
unLoc (Located (Pat (GhcPass 'Typechecked))
 -> Pat (GhcPass 'Typechecked))
-> (LHsRecField
      (GhcPass 'Typechecked) (Located (Pat (GhcPass 'Typechecked)))
    -> Located (Pat (GhcPass 'Typechecked)))
-> LHsRecField
     (GhcPass 'Typechecked) (Located (Pat (GhcPass 'Typechecked)))
-> Pat (GhcPass 'Typechecked)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. HsRecField
  (GhcPass 'Typechecked) (Located (Pat (GhcPass 'Typechecked)))
-> Located (Pat (GhcPass 'Typechecked))
forall id arg. HsRecField' id arg -> arg
hsRecFieldArg (HsRecField
   (GhcPass 'Typechecked) (Located (Pat (GhcPass 'Typechecked)))
 -> Located (Pat (GhcPass 'Typechecked)))
-> (LHsRecField
      (GhcPass 'Typechecked) (Located (Pat (GhcPass 'Typechecked)))
    -> HsRecField
         (GhcPass 'Typechecked) (Located (Pat (GhcPass 'Typechecked))))
-> LHsRecField
     (GhcPass 'Typechecked) (Located (Pat (GhcPass 'Typechecked)))
-> Located (Pat (GhcPass 'Typechecked))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. LHsRecField
  (GhcPass 'Typechecked) (Located (Pat (GhcPass 'Typechecked)))
-> HsRecField
     (GhcPass 'Typechecked) (Located (Pat (GhcPass 'Typechecked)))
forall a. HasSrcSpan a => a -> SrcSpanLess a
unLoc) [LHsRecField
   (GhcPass 'Typechecked) (Located (Pat (GhcPass 'Typechecked)))]
[LHsRecField (GhcPass 'Typechecked) (LPat (GhcPass 'Typechecked))]
rpats

{-
Note [Record patterns]
~~~~~~~~~~~~~~~~~~~~~~
Consider
         data T = T { x,y,z :: Bool }

         f (T { y=True, x=False }) = ...

We must match the patterns IN THE ORDER GIVEN, thus for the first
one we match y=True before x=False.  See #246; or imagine
matching against (T { y=False, x=undefined }): should fail without
touching the undefined.

Now consider:

         f (T { y=True, x=False }) = ...
         f (T { x=True, y= False}) = ...

In the first we must test y first; in the second we must test x
first.  So we must divide even the equations for a single constructor
T into sub-goups, based on whether they match the same field in the
same order.  That's what the (groupBy compatible_pats) grouping.

All non-record patterns are "compatible" in this sense, because the
positional patterns (T a b) and (a `T` b) all match the arguments
in order.  Also T {} is special because it's equivalent to (T _ _).
Hence the (null rpats) checks here and there.


Note [Existentials in shift_con_pat]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Consider
        data T = forall a. Ord a => T a (a->Int)

        f (T x f) True  = ...expr1...
        f (T y g) False = ...expr2..

When we put in the tyvars etc we get

        f (T a (d::Ord a) (x::a) (f::a->Int)) True =  ...expr1...
        f (T b (e::Ord b) (y::a) (g::a->Int)) True =  ...expr2...

After desugaring etc we'll get a single case:

        f = \t::T b::Bool ->
            case t of
               T a (d::Ord a) (x::a) (f::a->Int)) ->
            case b of
                True  -> ...expr1...
                False -> ...expr2...

*** We have to substitute [a/b, d/e] in expr2! **
Hence
                False -> ....((/\b\(e:Ord b).expr2) a d)....

Originally I tried to use
        (\b -> let e = d in expr2) a
to do this substitution.  While this is "correct" in a way, it fails
Lint, because e::Ord b but d::Ord a.

-}