{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE TypeFamilies #-}

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


Utilities for desugaring

This module exports some utility functions of no great interest.
-}

-- | Utility functions for constructing Core syntax, principally for desugaring
module GHC.HsToCore.Utils (
        EquationInfo(..),
        firstPat, shiftEqns,

        MatchResult (..), CaseAlt(..),
        cantFailMatchResult, alwaysFailMatchResult,
        extractMatchResult, combineMatchResults,
        adjustMatchResultDs,
        shareFailureHandler,
        dsHandleMonadicFailure,
        mkCoLetMatchResult, mkViewMatchResult, mkGuardedMatchResult,
        matchCanFail, mkEvalMatchResult,
        mkCoPrimCaseMatchResult, mkCoAlgCaseMatchResult, mkCoSynCaseMatchResult,
        wrapBind, wrapBinds,

        mkErrorAppDs, mkCoreAppDs, mkCoreAppsDs, mkCastDs,
        mkFailExpr,

        seqVar,

        -- LHs tuples
        mkLHsPatTup, mkVanillaTuplePat,
        mkBigLHsVarTupId, mkBigLHsTupId, mkBigLHsVarPatTupId, mkBigLHsPatTupId,

        mkSelectorBinds,

        selectSimpleMatchVarL, selectMatchVars, selectMatchVar,
        mkOptTickBox, mkBinaryTickBox, decideBangHood,
        isTrueLHsExpr
    ) where

import GHC.Prelude

import Language.Haskell.Syntax.Basic (Boxity(..))

import {-# SOURCE #-} GHC.HsToCore.Match ( matchSimply )
import {-# SOURCE #-} GHC.HsToCore.Expr  ( dsLExpr, dsSyntaxExpr )

import GHC.Hs
import GHC.Hs.Syn.Type
import GHC.Core
import GHC.HsToCore.Monad

import GHC.Core.Utils
import GHC.Core.Make
import GHC.Types.Id.Make
import GHC.Types.Id
import GHC.Types.Literal
import GHC.Core.TyCon
import GHC.Core.DataCon
import GHC.Core.PatSyn
import GHC.Core.Type
import GHC.Core.Coercion
import GHC.Builtin.Types
import GHC.Core.ConLike
import GHC.Types.Unique.Set
import GHC.Types.Unique.Supply
import GHC.Unit.Module
import GHC.Builtin.Names
import GHC.Types.Name( isInternalName )
import GHC.Utils.Outputable
import GHC.Utils.Panic
import GHC.Utils.Panic.Plain
import GHC.Types.SrcLoc
import GHC.Types.Tickish
import GHC.Utils.Misc
import GHC.Driver.Session
import GHC.Driver.Ppr
import GHC.Data.FastString
import qualified GHC.LanguageExtensions as LangExt

import GHC.Tc.Types.Evidence

import Control.Monad    ( zipWithM )
import Data.List.NonEmpty (NonEmpty(..))
import Data.Maybe (maybeToList)
import qualified Data.List.NonEmpty as NEL

{-
************************************************************************
*                                                                      *
\subsection{ Selecting match variables}
*                                                                      *
************************************************************************

We're about to match against some patterns.  We want to make some
@Ids@ to use as match variables.  If a pattern has an @Id@ readily at
hand, which should indeed be bound to the pattern as a whole, then use it;
otherwise, make one up. The multiplicity argument is chosen as the multiplicity
of the variable if it is made up.
-}

selectSimpleMatchVarL :: Mult -> LPat GhcTc -> DsM Id
-- Postcondition: the returned Id has an Internal Name
selectSimpleMatchVarL :: Mult -> XRec GhcTc (Pat GhcTc) -> DsM Var
selectSimpleMatchVarL Mult
w XRec GhcTc (Pat GhcTc)
pat = Mult -> Pat GhcTc -> DsM Var
selectMatchVar Mult
w (GenLocated SrcSpanAnnA (Pat GhcTc) -> Pat GhcTc
forall l e. GenLocated l e -> e
unLoc XRec GhcTc (Pat GhcTc)
GenLocated SrcSpanAnnA (Pat GhcTc)
pat)

-- (selectMatchVars ps tys) chooses variables of type tys
-- to use for matching ps against.  If the pattern is a variable,
-- we try to use that, to save inventing lots of fresh variables.
--
-- OLD, but interesting note:
--    But even if it is a variable, its type might not match.  Consider
--      data T a where
--        T1 :: Int -> T Int
--        T2 :: a   -> T a
--
--      f :: T a -> a -> Int
--      f (T1 i) (x::Int) = x
--      f (T2 i) (y::a)   = 0
--    Then we must not choose (x::Int) as the matching variable!
-- And nowadays we won't, because the (x::Int) will be wrapped in a CoPat

selectMatchVars :: [(Mult, Pat GhcTc)] -> DsM [Id]
-- Postcondition: the returned Ids have Internal Names
selectMatchVars :: [(Mult, Pat GhcTc)] -> DsM [Var]
selectMatchVars [(Mult, Pat GhcTc)]
ps = ((Mult, Pat GhcTc) -> DsM Var) -> [(Mult, Pat GhcTc)] -> DsM [Var]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [b]
mapM ((Mult -> Pat GhcTc -> DsM Var) -> (Mult, Pat GhcTc) -> DsM Var
forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry Mult -> Pat GhcTc -> DsM Var
selectMatchVar) [(Mult, Pat GhcTc)]
ps

selectMatchVar :: Mult -> Pat GhcTc -> DsM Id
-- Postcondition: the returned Id has an Internal Name
selectMatchVar :: Mult -> Pat GhcTc -> DsM Var
selectMatchVar Mult
w (BangPat XBangPat GhcTc
_ XRec GhcTc (Pat GhcTc)
pat)    = Mult -> Pat GhcTc -> DsM Var
selectMatchVar Mult
w (GenLocated SrcSpanAnnA (Pat GhcTc) -> Pat GhcTc
forall l e. GenLocated l e -> e
unLoc XRec GhcTc (Pat GhcTc)
GenLocated SrcSpanAnnA (Pat GhcTc)
pat)
selectMatchVar Mult
w (LazyPat XLazyPat GhcTc
_ XRec GhcTc (Pat GhcTc)
pat)    = Mult -> Pat GhcTc -> DsM Var
selectMatchVar Mult
w (GenLocated SrcSpanAnnA (Pat GhcTc) -> Pat GhcTc
forall l e. GenLocated l e -> e
unLoc XRec GhcTc (Pat GhcTc)
GenLocated SrcSpanAnnA (Pat GhcTc)
pat)
selectMatchVar Mult
w (ParPat XParPat GhcTc
_ LHsToken "(" GhcTc
_ XRec GhcTc (Pat GhcTc)
pat LHsToken ")" GhcTc
_) = Mult -> Pat GhcTc -> DsM Var
selectMatchVar Mult
w (GenLocated SrcSpanAnnA (Pat GhcTc) -> Pat GhcTc
forall l e. GenLocated l e -> e
unLoc XRec GhcTc (Pat GhcTc)
GenLocated SrcSpanAnnA (Pat GhcTc)
pat)
selectMatchVar Mult
_w (VarPat XVarPat GhcTc
_ LIdP GhcTc
var)    = Var -> DsM Var
forall a. a -> IOEnv (Env DsGblEnv DsLclEnv) a
forall (m :: * -> *) a. Monad m => a -> m a
return (Var -> Var
localiseId (GenLocated SrcSpanAnnN Var -> Var
forall l e. GenLocated l e -> e
unLoc LIdP GhcTc
GenLocated SrcSpanAnnN Var
var))
                                  -- Note [Localise pattern binders]
                                  --
                                  -- Remark: when the pattern is a variable (or
                                  -- an @-pattern), then w is the same as the
                                  -- multiplicity stored within the variable
                                  -- itself. It's easier to pull it from the
                                  -- variable, so we ignore the multiplicity.
selectMatchVar Mult
_w (AsPat XAsPat GhcTc
_ LIdP GhcTc
var LHsToken "@" GhcTc
_ XRec GhcTc (Pat GhcTc)
_) = Bool -> DsM Var -> DsM Var
forall a. HasCallStack => Bool -> a -> a
assert (Mult -> Bool
isManyTy Mult
_w ) (Var -> DsM Var
forall a. a -> IOEnv (Env DsGblEnv DsLclEnv) a
forall (m :: * -> *) a. Monad m => a -> m a
return (GenLocated SrcSpanAnnN Var -> Var
forall l e. GenLocated l e -> e
unLoc LIdP GhcTc
GenLocated SrcSpanAnnN Var
var))
selectMatchVar Mult
w Pat GhcTc
other_pat        = Mult -> Mult -> DsM Var
newSysLocalDs Mult
w (Pat GhcTc -> Mult
hsPatType Pat GhcTc
other_pat)

{- Note [Localise pattern binders]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Consider     module M where
               [Just a] = e
After renaming it looks like
             module M where
               [Just M.a] = e

We don't generalise, since it's a pattern binding, monomorphic, etc,
so after desugaring we may get something like
             M.a = case e of (v:_) ->
                   case v of Just M.a -> M.a
Notice the "M.a" in the pattern; after all, it was in the original
pattern.  However, after optimisation those pattern binders can become
let-binders, and then end up floated to top level.  They have a
different *unique* by then (the simplifier is good about maintaining
proper scoping), but it's BAD to have two top-level bindings with the
External Name M.a, because that turns into two linker symbols for M.a.
It's quite rare for this to actually *happen* -- the only case I know
of is tc003 compiled with the 'hpc' way -- but that only makes it
all the more annoying.

To avoid this, we craftily call 'localiseId' in the desugarer, which
simply turns the External Name for the Id into an Internal one, but
doesn't change the unique.  So the desugarer produces this:
             M.a{r8} = case e of (v:_) ->
                       case v of Just a{r8} -> M.a{r8}
The unique is still 'r8', but the binding site in the pattern
is now an Internal Name.  Now the simplifier's usual mechanisms
will propagate that Name to all the occurrence sites, as well as
un-shadowing it, so we'll get
             M.a{r8} = case e of (v:_) ->
                       case v of Just a{s77} -> a{s77}
In fact, even GHC.Core.Subst.simplOptExpr will do this, and simpleOptExpr
runs on the output of the desugarer, so all is well by the end of
the desugaring pass.

See also Note [Match Ids] in GHC.HsToCore.Match

************************************************************************
*                                                                      *
* type synonym EquationInfo and access functions for its pieces        *
*                                                                      *
************************************************************************
\subsection[EquationInfo-synonym]{@EquationInfo@: a useful synonym}

The ``equation info'' used by @match@ is relatively complicated and
worthy of a type synonym and a few handy functions.
-}

firstPat :: EquationInfo -> Pat GhcTc
firstPat :: EquationInfo -> Pat GhcTc
firstPat EquationInfo
eqn = Bool -> Pat GhcTc -> Pat GhcTc
forall a. HasCallStack => Bool -> a -> a
assert ([Pat GhcTc] -> Bool
forall (f :: * -> *) a. Foldable f => f a -> Bool
notNull (EquationInfo -> [Pat GhcTc]
eqn_pats EquationInfo
eqn)) (Pat GhcTc -> Pat GhcTc) -> Pat GhcTc -> Pat GhcTc
forall a b. (a -> b) -> a -> b
$ [Pat GhcTc] -> Pat GhcTc
forall a. HasCallStack => [a] -> a
head (EquationInfo -> [Pat GhcTc]
eqn_pats EquationInfo
eqn)

shiftEqns :: Functor f => f EquationInfo -> f EquationInfo
-- Drop the first pattern in each equation
shiftEqns :: forall (f :: * -> *). Functor f => f EquationInfo -> f EquationInfo
shiftEqns = (EquationInfo -> EquationInfo) -> f EquationInfo -> f EquationInfo
forall a b. (a -> b) -> f a -> f b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((EquationInfo -> EquationInfo)
 -> f EquationInfo -> f EquationInfo)
-> (EquationInfo -> EquationInfo)
-> f EquationInfo
-> f EquationInfo
forall a b. (a -> b) -> a -> b
$ \EquationInfo
eqn -> EquationInfo
eqn { eqn_pats = tail (eqn_pats eqn) }

-- Functions on MatchResult CoreExprs

matchCanFail :: MatchResult a -> Bool
matchCanFail :: forall a. MatchResult a -> Bool
matchCanFail (MR_Fallible {})  = Bool
True
matchCanFail (MR_Infallible {}) = Bool
False

alwaysFailMatchResult :: MatchResult CoreExpr
alwaysFailMatchResult :: MatchResult CoreExpr
alwaysFailMatchResult = (CoreExpr -> DsM CoreExpr) -> MatchResult CoreExpr
forall a. (CoreExpr -> DsM a) -> MatchResult a
MR_Fallible ((CoreExpr -> DsM CoreExpr) -> MatchResult CoreExpr)
-> (CoreExpr -> DsM CoreExpr) -> MatchResult CoreExpr
forall a b. (a -> b) -> a -> b
$ \CoreExpr
fail -> CoreExpr -> DsM CoreExpr
forall a. a -> IOEnv (Env DsGblEnv DsLclEnv) a
forall (m :: * -> *) a. Monad m => a -> m a
return CoreExpr
fail

cantFailMatchResult :: CoreExpr -> MatchResult CoreExpr
cantFailMatchResult :: CoreExpr -> MatchResult CoreExpr
cantFailMatchResult CoreExpr
expr = DsM CoreExpr -> MatchResult CoreExpr
forall a. DsM a -> MatchResult a
MR_Infallible (DsM CoreExpr -> MatchResult CoreExpr)
-> DsM CoreExpr -> MatchResult CoreExpr
forall a b. (a -> b) -> a -> b
$ CoreExpr -> DsM CoreExpr
forall a. a -> IOEnv (Env DsGblEnv DsLclEnv) a
forall (m :: * -> *) a. Monad m => a -> m a
return CoreExpr
expr

extractMatchResult :: MatchResult CoreExpr -> CoreExpr -> DsM CoreExpr
extractMatchResult :: MatchResult CoreExpr -> CoreExpr -> DsM CoreExpr
extractMatchResult MatchResult CoreExpr
match_result CoreExpr
failure_expr =
  CoreExpr -> MatchResult CoreExpr -> DsM CoreExpr
forall a. CoreExpr -> MatchResult a -> DsM a
runMatchResult
    CoreExpr
failure_expr
    (MatchResult CoreExpr -> MatchResult CoreExpr
shareFailureHandler MatchResult CoreExpr
match_result)

combineMatchResults :: MatchResult CoreExpr -> MatchResult CoreExpr -> MatchResult CoreExpr
combineMatchResults :: MatchResult CoreExpr
-> MatchResult CoreExpr -> MatchResult CoreExpr
combineMatchResults match_result1 :: MatchResult CoreExpr
match_result1@(MR_Infallible DsM CoreExpr
_) MatchResult CoreExpr
_
  = MatchResult CoreExpr
match_result1
combineMatchResults MatchResult CoreExpr
match_result1 MatchResult CoreExpr
match_result2 =
  -- if the first pattern needs a failure handler (i.e. if it is fallible),
  -- make it let-bind it bind it with `shareFailureHandler`.
  case MatchResult CoreExpr -> MatchResult CoreExpr
shareFailureHandler MatchResult CoreExpr
match_result1 of
    MR_Infallible DsM CoreExpr
_ -> MatchResult CoreExpr
match_result1
    MR_Fallible CoreExpr -> DsM CoreExpr
body_fn1 -> (CoreExpr -> DsM CoreExpr) -> MatchResult CoreExpr
forall a. (CoreExpr -> DsM a) -> MatchResult a
MR_Fallible ((CoreExpr -> DsM CoreExpr) -> MatchResult CoreExpr)
-> (CoreExpr -> DsM CoreExpr) -> MatchResult CoreExpr
forall a b. (a -> b) -> a -> b
$ \CoreExpr
fail_expr ->
      -- Before actually failing, try the next match arm.
      CoreExpr -> DsM CoreExpr
body_fn1 (CoreExpr -> DsM CoreExpr) -> DsM CoreExpr -> DsM CoreExpr
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< CoreExpr -> MatchResult CoreExpr -> DsM CoreExpr
forall a. CoreExpr -> MatchResult a -> DsM a
runMatchResult CoreExpr
fail_expr MatchResult CoreExpr
match_result2

adjustMatchResultDs :: (a -> DsM b) -> MatchResult a -> MatchResult b
adjustMatchResultDs :: forall a b. (a -> DsM b) -> MatchResult a -> MatchResult b
adjustMatchResultDs a -> DsM b
encl_fn = \case
  MR_Infallible DsM a
body_fn -> DsM b -> MatchResult b
forall a. DsM a -> MatchResult a
MR_Infallible (DsM b -> MatchResult b) -> DsM b -> MatchResult b
forall a b. (a -> b) -> a -> b
$
    a -> DsM b
encl_fn (a -> DsM b) -> DsM a -> DsM b
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< DsM a
body_fn
  MR_Fallible CoreExpr -> DsM a
body_fn -> (CoreExpr -> DsM b) -> MatchResult b
forall a. (CoreExpr -> DsM a) -> MatchResult a
MR_Fallible ((CoreExpr -> DsM b) -> MatchResult b)
-> (CoreExpr -> DsM b) -> MatchResult b
forall a b. (a -> b) -> a -> b
$ \CoreExpr
fail ->
    a -> DsM b
encl_fn (a -> DsM b) -> DsM a -> DsM b
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< CoreExpr -> DsM a
body_fn CoreExpr
fail

wrapBinds :: [(Var,Var)] -> CoreExpr -> CoreExpr
wrapBinds :: [(Var, Var)] -> CoreExpr -> CoreExpr
wrapBinds [] CoreExpr
e = CoreExpr
e
wrapBinds ((Var
new,Var
old):[(Var, Var)]
prs) CoreExpr
e = Var -> Var -> CoreExpr -> CoreExpr
wrapBind Var
new Var
old ([(Var, Var)] -> CoreExpr -> CoreExpr
wrapBinds [(Var, Var)]
prs CoreExpr
e)

wrapBind :: Var -> Var -> CoreExpr -> CoreExpr
wrapBind :: Var -> Var -> CoreExpr -> CoreExpr
wrapBind Var
new Var
old CoreExpr
body   -- NB: this function must deal with term
  | Var
newVar -> Var -> Bool
forall a. Eq a => a -> a -> Bool
==Var
old    = CoreExpr
body  -- variables, type variables or coercion variables
  | Bool
otherwise   = Bind Var -> CoreExpr -> CoreExpr
forall b. Bind b -> Expr b -> Expr b
Let (Var -> CoreExpr -> Bind Var
forall b. b -> Expr b -> Bind b
NonRec Var
new (Var -> CoreExpr
forall b. Var -> Expr b
varToCoreExpr Var
old)) CoreExpr
body

seqVar :: Var -> CoreExpr -> CoreExpr
seqVar :: Var -> CoreExpr -> CoreExpr
seqVar Var
var CoreExpr
body = CoreExpr -> Var -> CoreExpr -> CoreExpr
mkDefaultCase (Var -> CoreExpr
forall b. Var -> Expr b
Var Var
var) Var
var CoreExpr
body

mkCoLetMatchResult :: CoreBind -> MatchResult CoreExpr -> MatchResult CoreExpr
mkCoLetMatchResult :: Bind Var -> MatchResult CoreExpr -> MatchResult CoreExpr
mkCoLetMatchResult Bind Var
bind = (CoreExpr -> CoreExpr)
-> MatchResult CoreExpr -> MatchResult CoreExpr
forall a b. (a -> b) -> MatchResult a -> MatchResult b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (Bind Var -> CoreExpr -> CoreExpr
mkCoreLet Bind Var
bind)

-- (mkViewMatchResult var' viewExpr mr) makes the expression
-- let var' = viewExpr in mr
mkViewMatchResult :: Id -> CoreExpr -> MatchResult CoreExpr -> MatchResult CoreExpr
mkViewMatchResult :: Var -> CoreExpr -> MatchResult CoreExpr -> MatchResult CoreExpr
mkViewMatchResult Var
var' CoreExpr
viewExpr = (CoreExpr -> CoreExpr)
-> MatchResult CoreExpr -> MatchResult CoreExpr
forall a b. (a -> b) -> MatchResult a -> MatchResult b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((CoreExpr -> CoreExpr)
 -> MatchResult CoreExpr -> MatchResult CoreExpr)
-> (CoreExpr -> CoreExpr)
-> MatchResult CoreExpr
-> MatchResult CoreExpr
forall a b. (a -> b) -> a -> b
$ Bind Var -> CoreExpr -> CoreExpr
mkCoreLet (Bind Var -> CoreExpr -> CoreExpr)
-> Bind Var -> CoreExpr -> CoreExpr
forall a b. (a -> b) -> a -> b
$ Var -> CoreExpr -> Bind Var
forall b. b -> Expr b -> Bind b
NonRec Var
var' CoreExpr
viewExpr

mkEvalMatchResult :: Id -> Type -> MatchResult CoreExpr -> MatchResult CoreExpr
mkEvalMatchResult :: Var -> Mult -> MatchResult CoreExpr -> MatchResult CoreExpr
mkEvalMatchResult Var
var Mult
ty = (CoreExpr -> CoreExpr)
-> MatchResult CoreExpr -> MatchResult CoreExpr
forall a b. (a -> b) -> MatchResult a -> MatchResult b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((CoreExpr -> CoreExpr)
 -> MatchResult CoreExpr -> MatchResult CoreExpr)
-> (CoreExpr -> CoreExpr)
-> MatchResult CoreExpr
-> MatchResult CoreExpr
forall a b. (a -> b) -> a -> b
$ \CoreExpr
e ->
  CoreExpr -> Var -> Mult -> [Alt Var] -> CoreExpr
forall b. Expr b -> b -> Mult -> [Alt b] -> Expr b
Case (Var -> CoreExpr
forall b. Var -> Expr b
Var Var
var) Var
var Mult
ty [AltCon -> [Var] -> CoreExpr -> Alt Var
forall b. AltCon -> [b] -> Expr b -> Alt b
Alt AltCon
DEFAULT [] CoreExpr
e]

mkGuardedMatchResult :: CoreExpr -> MatchResult CoreExpr -> MatchResult CoreExpr
mkGuardedMatchResult :: CoreExpr -> MatchResult CoreExpr -> MatchResult CoreExpr
mkGuardedMatchResult CoreExpr
pred_expr MatchResult CoreExpr
mr = (CoreExpr -> DsM CoreExpr) -> MatchResult CoreExpr
forall a. (CoreExpr -> DsM a) -> MatchResult a
MR_Fallible ((CoreExpr -> DsM CoreExpr) -> MatchResult CoreExpr)
-> (CoreExpr -> DsM CoreExpr) -> MatchResult CoreExpr
forall a b. (a -> b) -> a -> b
$ \CoreExpr
fail -> do
  CoreExpr
body <- CoreExpr -> MatchResult CoreExpr -> DsM CoreExpr
forall a. CoreExpr -> MatchResult a -> DsM a
runMatchResult CoreExpr
fail MatchResult CoreExpr
mr
  CoreExpr -> DsM CoreExpr
forall a. a -> IOEnv (Env DsGblEnv DsLclEnv) a
forall (m :: * -> *) a. Monad m => a -> m a
return (CoreExpr -> CoreExpr -> CoreExpr -> CoreExpr
mkIfThenElse CoreExpr
pred_expr CoreExpr
body CoreExpr
fail)

mkCoPrimCaseMatchResult :: Id                  -- Scrutinee
                        -> Type                      -- Type of the case
                        -> [(Literal, MatchResult CoreExpr)]  -- Alternatives
                        -> MatchResult CoreExpr               -- Literals are all unlifted
mkCoPrimCaseMatchResult :: Var
-> Mult
-> [(Literal, MatchResult CoreExpr)]
-> MatchResult CoreExpr
mkCoPrimCaseMatchResult Var
var Mult
ty [(Literal, MatchResult CoreExpr)]
match_alts
  = (CoreExpr -> DsM CoreExpr) -> MatchResult CoreExpr
forall a. (CoreExpr -> DsM a) -> MatchResult a
MR_Fallible CoreExpr -> DsM CoreExpr
mk_case
  where
    mk_case :: CoreExpr -> DsM CoreExpr
mk_case CoreExpr
fail = do
        [Alt Var]
alts <- ((Literal, MatchResult CoreExpr)
 -> IOEnv (Env DsGblEnv DsLclEnv) (Alt Var))
-> [(Literal, MatchResult CoreExpr)]
-> IOEnv (Env DsGblEnv DsLclEnv) [Alt Var]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [b]
mapM (CoreExpr
-> (Literal, MatchResult CoreExpr)
-> IOEnv (Env DsGblEnv DsLclEnv) (Alt Var)
forall {b}.
CoreExpr
-> (Literal, MatchResult (Expr b))
-> IOEnv (Env DsGblEnv DsLclEnv) (Alt b)
mk_alt CoreExpr
fail) [(Literal, MatchResult CoreExpr)]
sorted_alts
        CoreExpr -> DsM CoreExpr
forall a. a -> IOEnv (Env DsGblEnv DsLclEnv) a
forall (m :: * -> *) a. Monad m => a -> m a
return (CoreExpr -> Var -> Mult -> [Alt Var] -> CoreExpr
forall b. Expr b -> b -> Mult -> [Alt b] -> Expr b
Case (Var -> CoreExpr
forall b. Var -> Expr b
Var Var
var) Var
var Mult
ty (AltCon -> [Var] -> CoreExpr -> Alt Var
forall b. AltCon -> [b] -> Expr b -> Alt b
Alt AltCon
DEFAULT [] CoreExpr
fail Alt Var -> [Alt Var] -> [Alt Var]
forall a. a -> [a] -> [a]
: [Alt Var]
alts))

    sorted_alts :: [(Literal, MatchResult CoreExpr)]
sorted_alts = ((Literal, MatchResult CoreExpr) -> Literal)
-> [(Literal, MatchResult CoreExpr)]
-> [(Literal, MatchResult CoreExpr)]
forall b a. Ord b => (a -> b) -> [a] -> [a]
sortWith (Literal, MatchResult CoreExpr) -> Literal
forall a b. (a, b) -> a
fst [(Literal, MatchResult CoreExpr)]
match_alts       -- Right order for a Case
    mk_alt :: CoreExpr
-> (Literal, MatchResult (Expr b))
-> IOEnv (Env DsGblEnv DsLclEnv) (Alt b)
mk_alt CoreExpr
fail (Literal
lit, MatchResult (Expr b)
mr)
       = Bool
-> IOEnv (Env DsGblEnv DsLclEnv) (Alt b)
-> IOEnv (Env DsGblEnv DsLclEnv) (Alt b)
forall a. HasCallStack => Bool -> a -> a
assert (Bool -> Bool
not (Literal -> Bool
litIsLifted Literal
lit)) (IOEnv (Env DsGblEnv DsLclEnv) (Alt b)
 -> IOEnv (Env DsGblEnv DsLclEnv) (Alt b))
-> IOEnv (Env DsGblEnv DsLclEnv) (Alt b)
-> IOEnv (Env DsGblEnv DsLclEnv) (Alt b)
forall a b. (a -> b) -> a -> b
$
         do Expr b
body <- CoreExpr -> MatchResult (Expr b) -> DsM (Expr b)
forall a. CoreExpr -> MatchResult a -> DsM a
runMatchResult CoreExpr
fail MatchResult (Expr b)
mr
            Alt b -> IOEnv (Env DsGblEnv DsLclEnv) (Alt b)
forall a. a -> IOEnv (Env DsGblEnv DsLclEnv) a
forall (m :: * -> *) a. Monad m => a -> m a
return (AltCon -> [b] -> Expr b -> Alt b
forall b. AltCon -> [b] -> Expr b -> Alt b
Alt (Literal -> AltCon
LitAlt Literal
lit) [] Expr b
body)

data CaseAlt a = MkCaseAlt{ forall a. CaseAlt a -> a
alt_pat :: a,
                            forall a. CaseAlt a -> [Var]
alt_bndrs :: [Var],
                            forall a. CaseAlt a -> HsWrapper
alt_wrapper :: HsWrapper,
                            forall a. CaseAlt a -> MatchResult CoreExpr
alt_result :: MatchResult CoreExpr }

mkCoAlgCaseMatchResult
  :: Id -- ^ Scrutinee
  -> Type -- ^ Type of exp
  -> NonEmpty (CaseAlt DataCon) -- ^ Alternatives (bndrs *include* tyvars, dicts)
  -> MatchResult CoreExpr
mkCoAlgCaseMatchResult :: Var -> Mult -> NonEmpty (CaseAlt DataCon) -> MatchResult CoreExpr
mkCoAlgCaseMatchResult Var
var Mult
ty NonEmpty (CaseAlt DataCon)
match_alts
  | Bool
isNewtype  -- Newtype case; use a let
  = Bool -> MatchResult CoreExpr -> MatchResult CoreExpr
forall a. HasCallStack => Bool -> a -> a
assert ([CaseAlt DataCon] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [CaseAlt DataCon]
match_alts_tail Bool -> Bool -> Bool
&& [Var] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null ([Var] -> [Var]
forall a. HasCallStack => [a] -> [a]
tail [Var]
arg_ids1)) (MatchResult CoreExpr -> MatchResult CoreExpr)
-> MatchResult CoreExpr -> MatchResult CoreExpr
forall a b. (a -> b) -> a -> b
$
    Bind Var -> MatchResult CoreExpr -> MatchResult CoreExpr
mkCoLetMatchResult (Var -> CoreExpr -> Bind Var
forall b. b -> Expr b -> Bind b
NonRec Var
arg_id1 CoreExpr
newtype_rhs) MatchResult CoreExpr
match_result1

  | Bool
otherwise
  = Var -> Mult -> NonEmpty (CaseAlt DataCon) -> MatchResult CoreExpr
mkDataConCase Var
var Mult
ty NonEmpty (CaseAlt DataCon)
match_alts
  where
    isNewtype :: Bool
isNewtype = TyCon -> Bool
isNewTyCon (DataCon -> TyCon
dataConTyCon (CaseAlt DataCon -> DataCon
forall a. CaseAlt a -> a
alt_pat CaseAlt DataCon
alt1))

        -- [Interesting: because of GADTs, we can't rely on the type of
        --  the scrutinised Id to be sufficiently refined to have a TyCon in it]

    alt1 :: CaseAlt DataCon
alt1@MkCaseAlt{ alt_bndrs :: forall a. CaseAlt a -> [Var]
alt_bndrs = [Var]
arg_ids1, alt_result :: forall a. CaseAlt a -> MatchResult CoreExpr
alt_result = MatchResult CoreExpr
match_result1 } :| [CaseAlt DataCon]
match_alts_tail
      = NonEmpty (CaseAlt DataCon)
match_alts
    -- Stuff for newtype
    arg_id1 :: Var
arg_id1       = Bool -> Var -> Var
forall a. HasCallStack => Bool -> a -> a
assert ([Var] -> Bool
forall (f :: * -> *) a. Foldable f => f a -> Bool
notNull [Var]
arg_ids1) (Var -> Var) -> Var -> Var
forall a b. (a -> b) -> a -> b
$ [Var] -> Var
forall a. HasCallStack => [a] -> a
head [Var]
arg_ids1
    var_ty :: Mult
var_ty        = Var -> Mult
idType Var
var
    (TyCon
tc, [Mult]
ty_args) = Mult -> (TyCon, [Mult])
tcSplitTyConApp Mult
var_ty      -- Don't look through newtypes
                                                -- (not that splitTyConApp does, these days)
    newtype_rhs :: CoreExpr
newtype_rhs = TyCon -> [Mult] -> CoreExpr -> CoreExpr
unwrapNewTypeBody TyCon
tc [Mult]
ty_args (Var -> CoreExpr
forall b. Var -> Expr b
Var Var
var)

mkCoSynCaseMatchResult :: Id -> Type -> CaseAlt PatSyn -> MatchResult CoreExpr
mkCoSynCaseMatchResult :: Var -> Mult -> CaseAlt PatSyn -> MatchResult CoreExpr
mkCoSynCaseMatchResult Var
var Mult
ty CaseAlt PatSyn
alt = (CoreExpr -> DsM CoreExpr) -> MatchResult CoreExpr
forall a. (CoreExpr -> DsM a) -> MatchResult a
MR_Fallible ((CoreExpr -> DsM CoreExpr) -> MatchResult CoreExpr)
-> (CoreExpr -> DsM CoreExpr) -> MatchResult CoreExpr
forall a b. (a -> b) -> a -> b
$ Var -> Mult -> CaseAlt PatSyn -> CoreExpr -> DsM CoreExpr
mkPatSynCase Var
var Mult
ty CaseAlt PatSyn
alt

mkPatSynCase :: Id -> Type -> CaseAlt PatSyn -> CoreExpr -> DsM CoreExpr
mkPatSynCase :: Var -> Mult -> CaseAlt PatSyn -> CoreExpr -> DsM CoreExpr
mkPatSynCase Var
var Mult
ty CaseAlt PatSyn
alt CoreExpr
fail = do
    Var
matcher_id <- Name -> DsM Var
dsLookupGlobalId Name
matcher_name
    CoreExpr
matcher <- LHsExpr GhcTc -> DsM CoreExpr
dsLExpr (LHsExpr GhcTc -> DsM CoreExpr) -> LHsExpr GhcTc -> DsM CoreExpr
forall a b. (a -> b) -> a -> b
$ HsWrapper -> LHsExpr GhcTc -> LHsExpr GhcTc
mkLHsWrap HsWrapper
wrapper (LHsExpr GhcTc -> LHsExpr GhcTc) -> LHsExpr GhcTc -> LHsExpr GhcTc
forall a b. (a -> b) -> a -> b
$
                         Var -> [Mult] -> LHsExpr GhcTc
nlHsTyApp Var
matcher_id [(() :: Constraint) => Mult -> Mult
Mult -> Mult
getRuntimeRep Mult
ty, Mult
ty]
    CoreExpr
cont <- [Var] -> CoreExpr -> CoreExpr
mkCoreLams [Var]
bndrs (CoreExpr -> CoreExpr) -> DsM CoreExpr -> DsM CoreExpr
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> CoreExpr -> MatchResult CoreExpr -> DsM CoreExpr
forall a. CoreExpr -> MatchResult a -> DsM a
runMatchResult CoreExpr
fail MatchResult CoreExpr
match_result
    CoreExpr -> DsM CoreExpr
forall a. a -> IOEnv (Env DsGblEnv DsLclEnv) a
forall (m :: * -> *) a. Monad m => a -> m a
return (CoreExpr -> DsM CoreExpr) -> CoreExpr -> DsM CoreExpr
forall a b. (a -> b) -> a -> b
$ SDoc -> CoreExpr -> [CoreExpr] -> CoreExpr
mkCoreAppsDs (String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"patsyn" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> Var -> SDoc
forall a. Outputable a => a -> SDoc
ppr Var
var) CoreExpr
matcher [Var -> CoreExpr
forall b. Var -> Expr b
Var Var
var, CoreExpr -> CoreExpr
ensure_unstrict CoreExpr
cont, Var -> CoreExpr -> CoreExpr
forall b. b -> Expr b -> Expr b
Lam Var
voidArgId CoreExpr
fail]
  where
    MkCaseAlt{ alt_pat :: forall a. CaseAlt a -> a
alt_pat = PatSyn
psyn,
               alt_bndrs :: forall a. CaseAlt a -> [Var]
alt_bndrs = [Var]
bndrs,
               alt_wrapper :: forall a. CaseAlt a -> HsWrapper
alt_wrapper = HsWrapper
wrapper,
               alt_result :: forall a. CaseAlt a -> MatchResult CoreExpr
alt_result = MatchResult CoreExpr
match_result} = CaseAlt PatSyn
alt
    (Name
matcher_name, Mult
_, Bool
needs_void_lam) = PatSyn -> (Name, Mult, Bool)
patSynMatcher PatSyn
psyn

    -- See Note [Matchers and builders for pattern synonyms] in GHC.Core.PatSyn
    -- on these extra Void# arguments
    ensure_unstrict :: CoreExpr -> CoreExpr
ensure_unstrict CoreExpr
cont | Bool
needs_void_lam = Var -> CoreExpr -> CoreExpr
forall b. b -> Expr b -> Expr b
Lam Var
voidArgId CoreExpr
cont
                         | Bool
otherwise      = CoreExpr
cont

mkDataConCase :: Id -> Type -> NonEmpty (CaseAlt DataCon) -> MatchResult CoreExpr
mkDataConCase :: Var -> Mult -> NonEmpty (CaseAlt DataCon) -> MatchResult CoreExpr
mkDataConCase Var
var Mult
ty alts :: NonEmpty (CaseAlt DataCon)
alts@(CaseAlt DataCon
alt1 :| [CaseAlt DataCon]
_)
    = (Maybe (Alt Var) -> [Alt Var] -> CoreExpr)
-> MatchResult (Maybe (Alt Var))
-> MatchResult [Alt Var]
-> MatchResult CoreExpr
forall a b c.
(a -> b -> c) -> MatchResult a -> MatchResult b -> MatchResult c
forall (f :: * -> *) a b c.
Applicative f =>
(a -> b -> c) -> f a -> f b -> f c
liftA2 Maybe (Alt Var) -> [Alt Var] -> CoreExpr
mk_case MatchResult (Maybe (Alt Var))
mk_default MatchResult [Alt Var]
mk_alts
    -- The liftA2 combines the failability of all the alternatives and the default
  where
    con1 :: DataCon
con1          = CaseAlt DataCon -> DataCon
forall a. CaseAlt a -> a
alt_pat CaseAlt DataCon
alt1
    tycon :: TyCon
tycon         = DataCon -> TyCon
dataConTyCon DataCon
con1
    data_cons :: [DataCon]
data_cons     = TyCon -> [DataCon]
tyConDataCons TyCon
tycon

    sorted_alts :: [ CaseAlt DataCon ]
    sorted_alts :: [CaseAlt DataCon]
sorted_alts  = (CaseAlt DataCon -> ConTag)
-> [CaseAlt DataCon] -> [CaseAlt DataCon]
forall b a. Ord b => (a -> b) -> [a] -> [a]
sortWith (DataCon -> ConTag
dataConTag (DataCon -> ConTag)
-> (CaseAlt DataCon -> DataCon) -> CaseAlt DataCon -> ConTag
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CaseAlt DataCon -> DataCon
forall a. CaseAlt a -> a
alt_pat) ([CaseAlt DataCon] -> [CaseAlt DataCon])
-> [CaseAlt DataCon] -> [CaseAlt DataCon]
forall a b. (a -> b) -> a -> b
$ NonEmpty (CaseAlt DataCon) -> [CaseAlt DataCon]
forall a. NonEmpty a -> [a]
NEL.toList NonEmpty (CaseAlt DataCon)
alts

    var_ty :: Mult
var_ty       = Var -> Mult
idType Var
var
    (TyCon
_, [Mult]
ty_args) = Mult -> (TyCon, [Mult])
tcSplitTyConApp Mult
var_ty -- Don't look through newtypes
                                          -- (not that splitTyConApp does, these days)

    mk_case :: Maybe CoreAlt -> [CoreAlt] -> CoreExpr
    mk_case :: Maybe (Alt Var) -> [Alt Var] -> CoreExpr
mk_case Maybe (Alt Var)
def [Alt Var]
alts = CoreExpr -> Scaled Mult -> Mult -> [Alt Var] -> CoreExpr
mkWildCase (Var -> CoreExpr
forall b. Var -> Expr b
Var Var
var) (Var -> Scaled Mult
idScaledType Var
var) Mult
ty ([Alt Var] -> CoreExpr) -> [Alt Var] -> CoreExpr
forall a b. (a -> b) -> a -> b
$
      Maybe (Alt Var) -> [Alt Var]
forall a. Maybe a -> [a]
maybeToList Maybe (Alt Var)
def [Alt Var] -> [Alt Var] -> [Alt Var]
forall a. [a] -> [a] -> [a]
++ [Alt Var]
alts

    mk_alts :: MatchResult [CoreAlt]
    mk_alts :: MatchResult [Alt Var]
mk_alts = (CaseAlt DataCon -> MatchResult (Alt Var))
-> [CaseAlt DataCon] -> MatchResult [Alt Var]
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
forall (f :: * -> *) a b.
Applicative f =>
(a -> f b) -> [a] -> f [b]
traverse CaseAlt DataCon -> MatchResult (Alt Var)
mk_alt [CaseAlt DataCon]
sorted_alts

    mk_alt :: CaseAlt DataCon -> MatchResult CoreAlt
    mk_alt :: CaseAlt DataCon -> MatchResult (Alt Var)
mk_alt MkCaseAlt { alt_pat :: forall a. CaseAlt a -> a
alt_pat = DataCon
con
                     , alt_bndrs :: forall a. CaseAlt a -> [Var]
alt_bndrs = [Var]
args
                     , alt_result :: forall a. CaseAlt a -> MatchResult CoreExpr
alt_result = MatchResult CoreExpr
match_result } =
      ((CoreExpr -> IOEnv (Env DsGblEnv DsLclEnv) (Alt Var))
 -> MatchResult CoreExpr -> MatchResult (Alt Var))
-> MatchResult CoreExpr
-> (CoreExpr -> IOEnv (Env DsGblEnv DsLclEnv) (Alt Var))
-> MatchResult (Alt Var)
forall a b c. (a -> b -> c) -> b -> a -> c
flip (CoreExpr -> IOEnv (Env DsGblEnv DsLclEnv) (Alt Var))
-> MatchResult CoreExpr -> MatchResult (Alt Var)
forall a b. (a -> DsM b) -> MatchResult a -> MatchResult b
adjustMatchResultDs MatchResult CoreExpr
match_result ((CoreExpr -> IOEnv (Env DsGblEnv DsLclEnv) (Alt Var))
 -> MatchResult (Alt Var))
-> (CoreExpr -> IOEnv (Env DsGblEnv DsLclEnv) (Alt Var))
-> MatchResult (Alt Var)
forall a b. (a -> b) -> a -> b
$ \CoreExpr
body -> do
        case DataCon -> Maybe DataConBoxer
dataConBoxer DataCon
con of
          Maybe DataConBoxer
Nothing -> Alt Var -> IOEnv (Env DsGblEnv DsLclEnv) (Alt Var)
forall a. a -> IOEnv (Env DsGblEnv DsLclEnv) a
forall (m :: * -> *) a. Monad m => a -> m a
return (AltCon -> [Var] -> CoreExpr -> Alt Var
forall b. AltCon -> [b] -> Expr b -> Alt b
Alt (DataCon -> AltCon
DataAlt DataCon
con) [Var]
args CoreExpr
body)
          Just (DCB [Mult] -> [Var] -> UniqSM ([Var], [Bind Var])
boxer) -> do
            UniqSupply
us <- TcRnIf DsGblEnv DsLclEnv UniqSupply
forall gbl lcl. TcRnIf gbl lcl UniqSupply
newUniqueSupply
            let ([Var]
rep_ids, [Bind Var]
binds) = UniqSupply -> UniqSM ([Var], [Bind Var]) -> ([Var], [Bind Var])
forall a. UniqSupply -> UniqSM a -> a
initUs_ UniqSupply
us ([Mult] -> [Var] -> UniqSM ([Var], [Bind Var])
boxer [Mult]
ty_args [Var]
args)
            let rep_ids' :: [Var]
rep_ids' = (Var -> Var) -> [Var] -> [Var]
forall a b. (a -> b) -> [a] -> [b]
map (Mult -> Var -> Var
scaleVarBy (Var -> Mult
idMult Var
var)) [Var]
rep_ids
              -- Upholds the invariant that the binders of a case expression
              -- must be scaled by the case multiplicity. See Note [Case
              -- expression invariants] in CoreSyn.
            Alt Var -> IOEnv (Env DsGblEnv DsLclEnv) (Alt Var)
forall a. a -> IOEnv (Env DsGblEnv DsLclEnv) a
forall (m :: * -> *) a. Monad m => a -> m a
return (AltCon -> [Var] -> CoreExpr -> Alt Var
forall b. AltCon -> [b] -> Expr b -> Alt b
Alt (DataCon -> AltCon
DataAlt DataCon
con) [Var]
rep_ids' ([Bind Var] -> CoreExpr -> CoreExpr
forall b. [Bind b] -> Expr b -> Expr b
mkLets [Bind Var]
binds CoreExpr
body))

    mk_default :: MatchResult (Maybe CoreAlt)
    mk_default :: MatchResult (Maybe (Alt Var))
mk_default
      | Bool
exhaustive_case = DsM (Maybe (Alt Var)) -> MatchResult (Maybe (Alt Var))
forall a. DsM a -> MatchResult a
MR_Infallible (DsM (Maybe (Alt Var)) -> MatchResult (Maybe (Alt Var)))
-> DsM (Maybe (Alt Var)) -> MatchResult (Maybe (Alt Var))
forall a b. (a -> b) -> a -> b
$ Maybe (Alt Var) -> DsM (Maybe (Alt Var))
forall a. a -> IOEnv (Env DsGblEnv DsLclEnv) a
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe (Alt Var)
forall a. Maybe a
Nothing
      | Bool
otherwise       = (CoreExpr -> DsM (Maybe (Alt Var)))
-> MatchResult (Maybe (Alt Var))
forall a. (CoreExpr -> DsM a) -> MatchResult a
MR_Fallible ((CoreExpr -> DsM (Maybe (Alt Var)))
 -> MatchResult (Maybe (Alt Var)))
-> (CoreExpr -> DsM (Maybe (Alt Var)))
-> MatchResult (Maybe (Alt Var))
forall a b. (a -> b) -> a -> b
$ \CoreExpr
fail -> Maybe (Alt Var) -> DsM (Maybe (Alt Var))
forall a. a -> IOEnv (Env DsGblEnv DsLclEnv) a
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe (Alt Var) -> DsM (Maybe (Alt Var)))
-> Maybe (Alt Var) -> DsM (Maybe (Alt Var))
forall a b. (a -> b) -> a -> b
$ Alt Var -> Maybe (Alt Var)
forall a. a -> Maybe a
Just (AltCon -> [Var] -> CoreExpr -> Alt Var
forall b. AltCon -> [b] -> Expr b -> Alt b
Alt AltCon
DEFAULT [] CoreExpr
fail)

    mentioned_constructors :: UniqSet DataCon
mentioned_constructors = [DataCon] -> UniqSet DataCon
forall a. Uniquable a => [a] -> UniqSet a
mkUniqSet ([DataCon] -> UniqSet DataCon) -> [DataCon] -> UniqSet DataCon
forall a b. (a -> b) -> a -> b
$ (CaseAlt DataCon -> DataCon) -> [CaseAlt DataCon] -> [DataCon]
forall a b. (a -> b) -> [a] -> [b]
map CaseAlt DataCon -> DataCon
forall a. CaseAlt a -> a
alt_pat [CaseAlt DataCon]
sorted_alts
    un_mentioned_constructors :: UniqSet DataCon
un_mentioned_constructors
        = [DataCon] -> UniqSet DataCon
forall a. Uniquable a => [a] -> UniqSet a
mkUniqSet [DataCon]
data_cons UniqSet DataCon -> UniqSet DataCon -> UniqSet DataCon
forall a. UniqSet a -> UniqSet a -> UniqSet a
`minusUniqSet` UniqSet DataCon
mentioned_constructors
    exhaustive_case :: Bool
exhaustive_case = UniqSet DataCon -> Bool
forall a. UniqSet a -> Bool
isEmptyUniqSet UniqSet DataCon
un_mentioned_constructors

{-
************************************************************************
*                                                                      *
\subsection{Desugarer's versions of some Core functions}
*                                                                      *
************************************************************************
-}

mkErrorAppDs :: Id              -- The error function
             -> Type            -- Type to which it should be applied
             -> SDoc            -- The error message string to pass
             -> DsM CoreExpr

mkErrorAppDs :: Var -> Mult -> SDoc -> DsM CoreExpr
mkErrorAppDs Var
err_id Mult
ty SDoc
msg = do
    SrcSpan
src_loc <- DsM SrcSpan
getSrcSpanDs
    DynFlags
dflags <- IOEnv (Env DsGblEnv DsLclEnv) DynFlags
forall (m :: * -> *). HasDynFlags m => m DynFlags
getDynFlags
    let full_msg :: String
full_msg = DynFlags -> SDoc -> String
showSDoc DynFlags
dflags ([SDoc] -> SDoc
forall doc. IsLine doc => [doc] -> doc
hcat [SrcSpan -> SDoc
forall a. Outputable a => a -> SDoc
ppr SrcSpan
src_loc, SDoc
forall doc. IsLine doc => doc
vbar, SDoc
msg])
        fail_expr :: CoreExpr
fail_expr = Var -> Mult -> String -> CoreExpr
mkRuntimeErrorApp Var
err_id Mult
unitTy String
full_msg
    CoreExpr -> DsM CoreExpr
forall a. a -> IOEnv (Env DsGblEnv DsLclEnv) a
forall (m :: * -> *) a. Monad m => a -> m a
return (CoreExpr -> DsM CoreExpr) -> CoreExpr -> DsM CoreExpr
forall a b. (a -> b) -> a -> b
$ CoreExpr -> Scaled Mult -> Mult -> [Alt Var] -> CoreExpr
mkWildCase CoreExpr
fail_expr (Mult -> Scaled Mult
forall a. a -> Scaled a
unrestricted Mult
unitTy) Mult
ty []
    -- See Note [Incompleteness and linearity]

{-
Note [Incompleteness and linearity]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The default branch of an incomplete pattern match is compiled to a call
to 'error'.
Because of linearity, we wrap it with an empty case. Example:

f :: a %1 -> Bool -> a
f x True = False

Adding 'f x False = error "Non-exhaustive pattern..."' would violate
the linearity of x.
Instead, we use 'f x False = case error "Non-exhaustive pattern..." :: () of {}'.
This case expression accounts for linear variables by assigning bottom usage
(See Note [Bottom as a usage] in GHC.Core.Multiplicity).
This is done in mkErrorAppDs, called from mkFailExpr.
We use '()' instead of the original return type ('a' in this case)
because there might be representation polymorphism, e.g. in

g :: forall (a :: TYPE r). (() -> a) %1 -> Bool -> a
g x True = x ()

adding 'g x False = case error "Non-exhaustive pattern" :: a of {}'
would create an illegal representation-polymorphic case binder.
This is important for pattern synonym matchers, which often look like this 'g'.

Similarly, a hole
h :: a %1 -> a
h x = _
is desugared to 'case error "Hole" :: () of {}'. Test: LinearHole.

Instead of () we could use Data.Void.Void, but that would require
moving Void to GHC.Types: partial pattern matching is used in modules
that are compiled before Data.Void.
We can use () even though it has a constructor, because
Note [Case expression invariants] point 4 in GHC.Core is satisfied
when the scrutinee is bottoming.

You might wonder if this change slows down compilation, but the
performance testsuite did not show up any regressions.

For uniformity, calls to 'error' in both cases are wrapped even if -XLinearTypes
is disabled.
-}

mkFailExpr :: HsMatchContext GhcRn -> Type -> DsM CoreExpr
mkFailExpr :: HsMatchContext GhcRn -> Mult -> DsM CoreExpr
mkFailExpr HsMatchContext GhcRn
ctxt Mult
ty
  = Var -> Mult -> SDoc -> DsM CoreExpr
mkErrorAppDs Var
pAT_ERROR_ID Mult
ty (HsMatchContext GhcRn -> SDoc
forall (p :: Pass).
OutputableBndrId p =>
HsMatchContext (GhcPass p) -> SDoc
matchContextErrString HsMatchContext GhcRn
ctxt)

{-
'mkCoreAppDs' and 'mkCoreAppsDs' handle the special-case desugaring of 'seq'.

Note [Desugaring seq]
~~~~~~~~~~~~~~~~~~~~~

There are a few subtleties in the desugaring of `seq`:

 1. (as described in #1031)

    Consider,
       f x y = x `seq` (y `seq` (# x,y #))

    Because the argument to the outer 'seq' has an unlifted type, we'll use
    call-by-value, and compile it as if we had

       f x y = case (y `seq` (# x,y #)) of v -> x `seq` v

    But that is bad, because we now evaluate y before x!

    Seq is very, very special!  So we recognise it right here, and desugar to
            case x of _ -> case y of _ -> (# x,y #)

 2. (as described in #2273)

    Consider
       let chp = case b of { True -> fst x; False -> 0 }
       in chp `seq` ...chp...
    Here the seq is designed to plug the space leak of retaining (snd x)
    for too long.

    If we rely on the ordinary inlining of seq, we'll get
       let chp = case b of { True -> fst x; False -> 0 }
       case chp of _ { I# -> ...chp... }

    But since chp is cheap, and the case is an alluring context, we'll
    inline chp into the case scrutinee.  Now there is only one use of chp,
    so we'll inline a second copy.  Alas, we've now ruined the purpose of
    the seq, by re-introducing the space leak:
        case (case b of {True -> fst x; False -> 0}) of
          I# _ -> ...case b of {True -> fst x; False -> 0}...

    We can try to avoid doing this by ensuring that the binder-swap in the
    case happens, so we get this at an early stage:
       case chp of chp2 { I# -> ...chp2... }
    But this is fragile.  The real culprit is the source program.  Perhaps we
    should have said explicitly
       let !chp2 = chp in ...chp2...

    But that's painful.  So the code here does a little hack to make seq
    more robust: a saturated application of 'seq' is turned *directly* into
    the case expression, thus:
       x  `seq` e2 ==> case x of x -> e2    -- Note shadowing!
       e1 `seq` e2 ==> case x of _ -> e2

    So we desugar our example to:
       let chp = case b of { True -> fst x; False -> 0 }
       case chp of chp { I# -> ...chp... }
    And now all is well.

    The reason it's a hack is because if you define mySeq=seq, the hack
    won't work on mySeq.

 3. (as described in #2409)

    The isInternalName ensures that we don't turn
            True `seq` e
    into
            case True of True { ... }
    which stupidly tries to bind the datacon 'True'.
-}

-- NB: Make sure the argument is not representation-polymorphic
mkCoreAppDs  :: SDoc -> CoreExpr -> CoreExpr -> CoreExpr
mkCoreAppDs :: SDoc -> CoreExpr -> CoreExpr -> CoreExpr
mkCoreAppDs SDoc
_ (Var Var
f `App` Type Mult
_r `App` Type Mult
ty1 `App` Type Mult
ty2 `App` CoreExpr
arg1) CoreExpr
arg2
  | Var
f Var -> Unique -> Bool
forall a. Uniquable a => a -> Unique -> Bool
`hasKey` Unique
seqIdKey            -- Note [Desugaring seq], points (1) and (2)
  = CoreExpr -> Var -> Mult -> [Alt Var] -> CoreExpr
forall b. Expr b -> b -> Mult -> [Alt b] -> Expr b
Case CoreExpr
arg1 Var
case_bndr Mult
ty2 [AltCon -> [Var] -> CoreExpr -> Alt Var
forall b. AltCon -> [b] -> Expr b -> Alt b
Alt AltCon
DEFAULT [] CoreExpr
arg2]
  where
    case_bndr :: Var
case_bndr = case CoreExpr
arg1 of
                   Var Var
v1 | Name -> Bool
isInternalName (Var -> Name
idName Var
v1)
                          -> Var
v1        -- Note [Desugaring seq], points (2) and (3)
                   CoreExpr
_      -> Mult -> Mult -> Var
mkWildValBinder Mult
ManyTy Mult
ty1

mkCoreAppDs SDoc
_ (Var Var
f `App` Type Mult
_r) CoreExpr
arg
  | Var
f Var -> Unique -> Bool
forall a. Uniquable a => a -> Unique -> Bool
`hasKey` Unique
noinlineIdKey   -- See Note [noinlineId magic] in GHC.Types.Id.Make
  , (CoreExpr
fun, [CoreExpr]
args) <- CoreExpr -> (CoreExpr, [CoreExpr])
forall b. Expr b -> (Expr b, [Expr b])
collectArgs CoreExpr
arg
  , Bool -> Bool
not ([CoreExpr] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [CoreExpr]
args)
  = (Var -> CoreExpr
forall b. Var -> Expr b
Var Var
f CoreExpr -> CoreExpr -> CoreExpr
forall b. Expr b -> Expr b -> Expr b
`App` Mult -> CoreExpr
forall b. Mult -> Expr b
Type ((() :: Constraint) => CoreExpr -> Mult
CoreExpr -> Mult
exprType CoreExpr
fun) CoreExpr -> CoreExpr -> CoreExpr
forall b. Expr b -> Expr b -> Expr b
`App` CoreExpr
fun)
    CoreExpr -> [CoreExpr] -> CoreExpr
`mkCoreApps` [CoreExpr]
args

mkCoreAppDs SDoc
s CoreExpr
fun CoreExpr
arg = SDoc -> CoreExpr -> CoreExpr -> CoreExpr
mkCoreApp SDoc
s CoreExpr
fun CoreExpr
arg  -- The rest is done in GHC.Core.Make

-- NB: No argument can be representation-polymorphic
mkCoreAppsDs :: SDoc -> CoreExpr -> [CoreExpr] -> CoreExpr
mkCoreAppsDs :: SDoc -> CoreExpr -> [CoreExpr] -> CoreExpr
mkCoreAppsDs SDoc
s CoreExpr
fun [CoreExpr]
args = (CoreExpr -> CoreExpr -> CoreExpr)
-> CoreExpr -> [CoreExpr] -> CoreExpr
forall b a. (b -> a -> b) -> b -> [a] -> b
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' (SDoc -> CoreExpr -> CoreExpr -> CoreExpr
mkCoreAppDs SDoc
s) CoreExpr
fun [CoreExpr]
args

mkCastDs :: CoreExpr -> Coercion -> CoreExpr
-- We define a desugarer-specific version of GHC.Core.Utils.mkCast,
-- because in the immediate output of the desugarer, we can have
-- apparently-mis-matched coercions:  E.g.
--     let a = b
--     in (x :: a) |> (co :: b ~ Int)
-- Lint know about type-bindings for let and does not complain
-- So here we do not make the assertion checks that we make in
-- GHC.Core.Utils.mkCast; and we do less peephole optimisation too
mkCastDs :: CoreExpr -> Coercion -> CoreExpr
mkCastDs CoreExpr
e Coercion
co | Coercion -> Bool
isReflCo Coercion
co = CoreExpr
e
              | Bool
otherwise   = CoreExpr -> Coercion -> CoreExpr
forall b. Expr b -> Coercion -> Expr b
Cast CoreExpr
e Coercion
co

{-
************************************************************************
*                                                                      *
               Tuples and selector bindings
*                                                                      *
************************************************************************

This is used in various places to do with lazy patterns.
For each binder $b$ in the pattern, we create a binding:
\begin{verbatim}
    b = case v of pat' -> b'
\end{verbatim}
where @pat'@ is @pat@ with each binder @b@ cloned into @b'@.

ToDo: making these bindings should really depend on whether there's
much work to be done per binding.  If the pattern is complex, it
should be de-mangled once, into a tuple (and then selected from).
Otherwise the demangling can be in-line in the bindings (as here).

Boring!  Boring!  One error message per binder.  The above ToDo is
even more helpful.  Something very similar happens for pattern-bound
expressions.

Note [mkSelectorBinds]
~~~~~~~~~~~~~~~~~~~~~~
mkSelectorBinds is used to desugar a pattern binding {p = e},
in a binding group:
  let { ...; p = e; ... } in body
where p binds x,y (this list of binders can be empty).
There are two cases.

------ Special case (A) -------
  For a pattern that is just a variable,
     let !x = e in body
  ==>
     let x = e in x `seq` body
  So we return the binding, with 'x' as the variable to seq.

------ Special case (B) -------
  For a pattern that is essentially just a tuple:
      * A product type, so cannot fail
      * Boxed, so that it can be matched lazily
      * Only one level, so that
          - generating multiple matches is fine
          - seq'ing it evaluates the same as matching it
  Then instead we generate
       { v = e
       ; x = case v of p -> x
       ; y = case v of p -> y }
  with 'v' as the variable to force

------ General case (C) -------
  In the general case we generate these bindings:
       let { ...; p = e; ... } in body
  ==>
       let { t = case e of p -> (x,y)
           ; x = case t of (x,y) -> x
           ; y = case t of (x,y) -> y }
       in t `seq` body

  Note that we return 't' as the variable to force if the pattern
  is strict (i.e. with -XStrict or an outermost-bang-pattern)

  Note that (C) /includes/ the situation where

   * The pattern binds exactly one variable
        let !(Just (Just x) = e in body
     ==>
       let { t = case e of Just (Just v) -> Solo v
           ; v = case t of Solo v -> v }
       in t `seq` body
    The 'Solo' is a one-tuple; see Note [One-tuples] in GHC.Builtin.Types
    Note that forcing 't' makes the pattern match happen,
    but does not force 'v'.  That's why we call `mkBigCoreVarTupSolo`
    in `mkSeletcorBinds`

  * The pattern binds no variables
        let !(True,False) = e in body
    ==>
        let t = case e of (True,False) -> ()
        in t `seq` body


------ Examples ----------
  *   !(_, (_, a)) = e
    ==>
      t = case e of (_, (_, a)) -> Solo a
      a = case t of Solo a -> a

    Note that
     - Forcing 't' will force the pattern to match fully;
       e.g. will diverge if (snd e) is bottom
     - But 'a' itself is not forced; it is wrapped in a one-tuple
       (see Note [One-tuples] in GHC.Builtin.Types)

  *   !(Just x) = e
    ==>
      t = case e of Just x -> Solo x
      x = case t of Solo x -> x

    Again, forcing 't' will fail if 'e' yields Nothing.

Note that even though this is rather general, the special cases
work out well:

* One binder, not -XStrict:

    let Just (Just v) = e in body
  ==>
    let t = case e of Just (Just v) -> Solo v
        v = case t of Solo v -> v
    in body
  ==>
    let v = case (case e of Just (Just v) -> Solo v) of
              Solo v -> v
    in body
  ==>
    let v = case e of Just (Just v) -> v
    in body

* Non-recursive, -XStrict
     let p = e in body
  ==>
     let { t = case e of p -> (x,y)
         ; x = case t of (x,y) -> x
         ; y = case t of (x,y) -> x }
     in t `seq` body
  ==> {inline seq, float x,y bindings inwards}
     let t = case e of p -> (x,y) in
     case t of t' ->
     let { x = case t' of (x,y) -> x
         ; y = case t' of (x,y) -> x } in
     body
  ==> {inline t, do case of case}
     case e of p ->
     let t = (x,y) in
     let { x = case t' of (x,y) -> x
         ; y = case t' of (x,y) -> x } in
     body
  ==> {case-cancellation, drop dead code}
     case e of p -> body

* Special case (B) is there to avoid fruitlessly taking the tuple
  apart and rebuilding it. For example, consider
     { K x y = e }
  where K is a product constructor.  Then general case (A) does:
     { t = case e of K x y -> (x,y)
     ; x = case t of (x,y) -> x
     ; y = case t of (x,y) -> y }
  In the lazy case we can't optimise out this fruitless taking apart
  and rebuilding.  Instead (B) builds
     { v = e
     ; x = case v of K x y -> x
     ; y = case v of K x y -> y }
  which is better.
-}
-- Remark: pattern selectors only occur in unrestricted patterns so we are free
-- to select Many as the multiplicity of every let-expression introduced.
mkSelectorBinds :: [[CoreTickish]] -- ^ ticks to add, possibly
                -> LPat GhcTc      -- ^ The pattern
                -> CoreExpr        -- ^ Expression to which the pattern is bound
                -> DsM (Id,[(Id,CoreExpr)])
                -- ^ Id the rhs is bound to, for desugaring strict
                -- binds (see Note [Desugar Strict binds] in "GHC.HsToCore.Binds")
                -- and all the desugared binds

mkSelectorBinds :: [[CoreTickish]]
-> XRec GhcTc (Pat GhcTc)
-> CoreExpr
-> DsM (Var, [(Var, CoreExpr)])
mkSelectorBinds [[CoreTickish]]
ticks XRec GhcTc (Pat GhcTc)
pat CoreExpr
val_expr
  | L SrcSpanAnnA
_ (VarPat XVarPat GhcTc
_ (L SrcSpanAnnN
_ Var
v)) <- XRec GhcTc (Pat GhcTc)
pat'     -- Special case (A)
  = (Var, [(Var, CoreExpr)]) -> DsM (Var, [(Var, CoreExpr)])
forall a. a -> IOEnv (Env DsGblEnv DsLclEnv) a
forall (m :: * -> *) a. Monad m => a -> m a
return (Var
v, [(Var
v, CoreExpr
val_expr)])

  | XRec GhcTc (Pat GhcTc) -> Bool
is_flat_prod_lpat XRec GhcTc (Pat GhcTc)
pat'           -- Special case (B)
  = do { let pat_ty :: Mult
pat_ty = XRec GhcTc (Pat GhcTc) -> Mult
hsLPatType XRec GhcTc (Pat GhcTc)
pat'
       ; Var
val_var <- Mult -> Mult -> DsM Var
newSysLocalDs Mult
ManyTy Mult
pat_ty

       ; let mk_bind :: [CoreTickish]
-> Var -> IOEnv (Env DsGblEnv DsLclEnv) (Var, CoreExpr)
mk_bind [CoreTickish]
tick Var
bndr_var
               -- (mk_bind sv bv)  generates  bv = case sv of { pat -> bv }
               -- Remember, 'pat' binds 'bv'
               = do { CoreExpr
rhs_expr <- CoreExpr
-> HsMatchContext GhcRn
-> XRec GhcTc (Pat GhcTc)
-> CoreExpr
-> CoreExpr
-> DsM CoreExpr
matchSimply (Var -> CoreExpr
forall b. Var -> Expr b
Var Var
val_var) HsMatchContext GhcRn
forall p. HsMatchContext p
PatBindRhs XRec GhcTc (Pat GhcTc)
pat'
                                       (Var -> CoreExpr
forall b. Var -> Expr b
Var Var
bndr_var)
                                       (Var -> CoreExpr
forall b. Var -> Expr b
Var Var
bndr_var)  -- Neat hack
                      -- Neat hack: since 'pat' can't fail, the
                      -- "fail-expr" passed to matchSimply is not
                      -- used. But it /is/ used for its type, and for
                      -- that bndr_var is just the ticket.
                    ; (Var, CoreExpr) -> IOEnv (Env DsGblEnv DsLclEnv) (Var, CoreExpr)
forall a. a -> IOEnv (Env DsGblEnv DsLclEnv) a
forall (m :: * -> *) a. Monad m => a -> m a
return (Var
bndr_var, [CoreTickish] -> CoreExpr -> CoreExpr
mkOptTickBox [CoreTickish]
tick CoreExpr
rhs_expr) }

       ; [(Var, CoreExpr)]
binds <- ([CoreTickish]
 -> Var -> IOEnv (Env DsGblEnv DsLclEnv) (Var, CoreExpr))
-> [[CoreTickish]]
-> [Var]
-> IOEnv (Env DsGblEnv DsLclEnv) [(Var, CoreExpr)]
forall (m :: * -> *) a b c.
Applicative m =>
(a -> b -> m c) -> [a] -> [b] -> m [c]
zipWithM [CoreTickish]
-> Var -> IOEnv (Env DsGblEnv DsLclEnv) (Var, CoreExpr)
mk_bind [[CoreTickish]]
ticks' [IdP GhcTc]
[Var]
binders
       ; (Var, [(Var, CoreExpr)]) -> DsM (Var, [(Var, CoreExpr)])
forall a. a -> IOEnv (Env DsGblEnv DsLclEnv) a
forall (m :: * -> *) a. Monad m => a -> m a
return ( Var
val_var, (Var
val_var, CoreExpr
val_expr) (Var, CoreExpr) -> [(Var, CoreExpr)] -> [(Var, CoreExpr)]
forall a. a -> [a] -> [a]
: [(Var, CoreExpr)]
binds) }

  | Bool
otherwise                          -- General case (C)
  = do { Var
tuple_var  <- Mult -> Mult -> DsM Var
newSysLocalDs Mult
ManyTy Mult
tuple_ty
       ; CoreExpr
error_expr <- Var -> Mult -> SDoc -> DsM CoreExpr
mkErrorAppDs Var
pAT_ERROR_ID Mult
tuple_ty (GenLocated SrcSpanAnnA (Pat GhcTc) -> SDoc
forall a. Outputable a => a -> SDoc
ppr XRec GhcTc (Pat GhcTc)
GenLocated SrcSpanAnnA (Pat GhcTc)
pat')
       ; CoreExpr
tuple_expr <- CoreExpr
-> HsMatchContext GhcRn
-> XRec GhcTc (Pat GhcTc)
-> CoreExpr
-> CoreExpr
-> DsM CoreExpr
matchSimply CoreExpr
val_expr HsMatchContext GhcRn
forall p. HsMatchContext p
PatBindRhs XRec GhcTc (Pat GhcTc)
pat
                                   CoreExpr
local_tuple CoreExpr
error_expr
       ; let mk_tup_bind :: [CoreTickish] -> Var -> (Var, CoreExpr)
mk_tup_bind [CoreTickish]
tick Var
binder
               = (Var
binder, [CoreTickish] -> CoreExpr -> CoreExpr
mkOptTickBox [CoreTickish]
tick (CoreExpr -> CoreExpr) -> CoreExpr -> CoreExpr
forall a b. (a -> b) -> a -> b
$
                          [Var] -> Var -> Var -> CoreExpr -> CoreExpr
mkBigTupleSelectorSolo [Var]
local_binders Var
binder
                                           Var
tuple_var (Var -> CoreExpr
forall b. Var -> Expr b
Var Var
tuple_var))
             tup_binds :: [(Var, CoreExpr)]
tup_binds = ([CoreTickish] -> Var -> (Var, CoreExpr))
-> [[CoreTickish]] -> [Var] -> [(Var, CoreExpr)]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith [CoreTickish] -> Var -> (Var, CoreExpr)
mk_tup_bind [[CoreTickish]]
ticks' [IdP GhcTc]
[Var]
binders
       ; (Var, [(Var, CoreExpr)]) -> DsM (Var, [(Var, CoreExpr)])
forall a. a -> IOEnv (Env DsGblEnv DsLclEnv) a
forall (m :: * -> *) a. Monad m => a -> m a
return (Var
tuple_var, (Var
tuple_var, CoreExpr
tuple_expr) (Var, CoreExpr) -> [(Var, CoreExpr)] -> [(Var, CoreExpr)]
forall a. a -> [a] -> [a]
: [(Var, CoreExpr)]
tup_binds) }
  where
    pat' :: XRec GhcTc (Pat GhcTc)
pat' = XRec GhcTc (Pat GhcTc) -> XRec GhcTc (Pat GhcTc)
forall (p :: Pass). LPat (GhcPass p) -> LPat (GhcPass p)
strip_bangs XRec GhcTc (Pat GhcTc)
pat
           -- Strip the bangs before looking for case (A) or (B)
           -- The incoming pattern may well have a bang on it

    binders :: [IdP GhcTc]
binders = CollectFlag GhcTc -> XRec GhcTc (Pat GhcTc) -> [IdP GhcTc]
forall p. CollectPass p => CollectFlag p -> LPat p -> [IdP p]
collectPatBinders CollectFlag GhcTc
forall p. CollectFlag p
CollNoDictBinders XRec GhcTc (Pat GhcTc)
pat'
    ticks' :: [[CoreTickish]]
ticks'  = [[CoreTickish]]
ticks [[CoreTickish]] -> [[CoreTickish]] -> [[CoreTickish]]
forall a. [a] -> [a] -> [a]
++ [CoreTickish] -> [[CoreTickish]]
forall a. a -> [a]
repeat []

    local_binders :: [Var]
local_binders = (Var -> Var) -> [Var] -> [Var]
forall a b. (a -> b) -> [a] -> [b]
map Var -> Var
localiseId [IdP GhcTc]
[Var]
binders      -- See Note [Localise pattern binders]
    local_tuple :: CoreExpr
local_tuple   = [Var] -> CoreExpr
mkBigCoreVarTupSolo [IdP GhcTc]
[Var]
binders
    tuple_ty :: Mult
tuple_ty      = (() :: Constraint) => CoreExpr -> Mult
CoreExpr -> Mult
exprType CoreExpr
local_tuple

strip_bangs :: LPat (GhcPass p) -> LPat (GhcPass p)
-- Remove outermost bangs and parens
strip_bangs :: forall (p :: Pass). LPat (GhcPass p) -> LPat (GhcPass p)
strip_bangs (L SrcSpanAnnA
_ (ParPat XParPat (GhcPass p)
_ LHsToken "(" (GhcPass p)
_ LPat (GhcPass p)
p LHsToken ")" (GhcPass p)
_))  = LPat (GhcPass p) -> LPat (GhcPass p)
forall (p :: Pass). LPat (GhcPass p) -> LPat (GhcPass p)
strip_bangs LPat (GhcPass p)
p
strip_bangs (L SrcSpanAnnA
_ (BangPat XBangPat (GhcPass p)
_ LPat (GhcPass p)
p)) = LPat (GhcPass p) -> LPat (GhcPass p)
forall (p :: Pass). LPat (GhcPass p) -> LPat (GhcPass p)
strip_bangs LPat (GhcPass p)
p
strip_bangs LPat (GhcPass p)
lp                  = LPat (GhcPass p)
lp

is_flat_prod_lpat :: LPat GhcTc -> Bool
-- Pattern is equivalent to a flat, boxed, lifted tuple
is_flat_prod_lpat :: XRec GhcTc (Pat GhcTc) -> Bool
is_flat_prod_lpat = Pat GhcTc -> Bool
is_flat_prod_pat (Pat GhcTc -> Bool)
-> (GenLocated SrcSpanAnnA (Pat GhcTc) -> Pat GhcTc)
-> GenLocated SrcSpanAnnA (Pat GhcTc)
-> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. GenLocated SrcSpanAnnA (Pat GhcTc) -> Pat GhcTc
forall l e. GenLocated l e -> e
unLoc

is_flat_prod_pat :: Pat GhcTc -> Bool
is_flat_prod_pat :: Pat GhcTc -> Bool
is_flat_prod_pat (ParPat XParPat GhcTc
_ LHsToken "(" GhcTc
_ XRec GhcTc (Pat GhcTc)
p LHsToken ")" GhcTc
_)      = XRec GhcTc (Pat GhcTc) -> Bool
is_flat_prod_lpat XRec GhcTc (Pat GhcTc)
p
is_flat_prod_pat (TuplePat XTuplePat GhcTc
_ [XRec GhcTc (Pat GhcTc)]
ps Boxity
Boxed) = (GenLocated SrcSpanAnnA (Pat GhcTc) -> Bool)
-> [GenLocated SrcSpanAnnA (Pat GhcTc)] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all XRec GhcTc (Pat GhcTc) -> Bool
GenLocated SrcSpanAnnA (Pat GhcTc) -> Bool
forall (p :: Pass). LPat (GhcPass p) -> Bool
is_triv_lpat [XRec GhcTc (Pat GhcTc)]
[GenLocated SrcSpanAnnA (Pat GhcTc)]
ps
is_flat_prod_pat (ConPat { pat_con :: forall p. Pat p -> XRec p (ConLikeP p)
pat_con  = L SrcSpanAnnN
_ ConLike
pcon
                         , pat_args :: forall p. Pat p -> HsConPatDetails p
pat_args = HsConPatDetails GhcTc
ps})
  | RealDataCon DataCon
con <- ConLike
pcon
  , let tc :: TyCon
tc = DataCon -> TyCon
dataConTyCon DataCon
con
  , Just DataCon
_ <- TyCon -> Maybe DataCon
tyConSingleDataCon_maybe TyCon
tc
  , TyCon -> Bool
isLiftedAlgTyCon TyCon
tc
  = (GenLocated SrcSpanAnnA (Pat GhcTc) -> Bool)
-> [GenLocated SrcSpanAnnA (Pat GhcTc)] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all XRec GhcTc (Pat GhcTc) -> Bool
GenLocated SrcSpanAnnA (Pat GhcTc) -> Bool
forall (p :: Pass). LPat (GhcPass p) -> Bool
is_triv_lpat (HsConPatDetails GhcTc -> [XRec GhcTc (Pat GhcTc)]
forall p. UnXRec p => HsConPatDetails p -> [LPat p]
hsConPatArgs HsConPatDetails GhcTc
ps)
is_flat_prod_pat Pat GhcTc
_ = Bool
False

is_triv_lpat :: LPat (GhcPass p) -> Bool
is_triv_lpat :: forall (p :: Pass). LPat (GhcPass p) -> Bool
is_triv_lpat = Pat (GhcPass p) -> Bool
forall (p :: Pass). Pat (GhcPass p) -> Bool
is_triv_pat (Pat (GhcPass p) -> Bool)
-> (GenLocated SrcSpanAnnA (Pat (GhcPass p)) -> Pat (GhcPass p))
-> GenLocated SrcSpanAnnA (Pat (GhcPass p))
-> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. GenLocated SrcSpanAnnA (Pat (GhcPass p)) -> Pat (GhcPass p)
forall l e. GenLocated l e -> e
unLoc

is_triv_pat :: Pat (GhcPass p) -> Bool
is_triv_pat :: forall (p :: Pass). Pat (GhcPass p) -> Bool
is_triv_pat (VarPat {})  = Bool
True
is_triv_pat (WildPat{})  = Bool
True
is_triv_pat (ParPat XParPat (GhcPass p)
_ LHsToken "(" (GhcPass p)
_ LPat (GhcPass p)
p LHsToken ")" (GhcPass p)
_) = LPat (GhcPass p) -> Bool
forall (p :: Pass). LPat (GhcPass p) -> Bool
is_triv_lpat LPat (GhcPass p)
p
is_triv_pat Pat (GhcPass p)
_            = Bool
False


{- *********************************************************************
*                                                                      *
  Creating big tuples and their types for full Haskell expressions.
  They work over *Ids*, and create tuples replete with their types,
  which is whey they are not in GHC.Hs.Utils.
*                                                                      *
********************************************************************* -}

mkLHsPatTup :: [LPat GhcTc] -> LPat GhcTc
mkLHsPatTup :: [XRec GhcTc (Pat GhcTc)] -> XRec GhcTc (Pat GhcTc)
mkLHsPatTup []     = Pat GhcTc -> GenLocated SrcSpanAnnA (Pat GhcTc)
forall a an. a -> LocatedAn an a
noLocA (Pat GhcTc -> GenLocated SrcSpanAnnA (Pat GhcTc))
-> Pat GhcTc -> GenLocated SrcSpanAnnA (Pat GhcTc)
forall a b. (a -> b) -> a -> b
$ [XRec GhcTc (Pat GhcTc)] -> Boxity -> Pat GhcTc
mkVanillaTuplePat [] Boxity
Boxed
mkLHsPatTup [XRec GhcTc (Pat GhcTc)
lpat] = XRec GhcTc (Pat GhcTc)
lpat
mkLHsPatTup lpats :: [XRec GhcTc (Pat GhcTc)]
lpats@(L SrcSpanAnnA
l Pat GhcTc
_:[XRec GhcTc (Pat GhcTc)]
_)  = SrcSpanAnnA -> Pat GhcTc -> GenLocated SrcSpanAnnA (Pat GhcTc)
forall l e. l -> e -> GenLocated l e
L SrcSpanAnnA
l (Pat GhcTc -> GenLocated SrcSpanAnnA (Pat GhcTc))
-> Pat GhcTc -> GenLocated SrcSpanAnnA (Pat GhcTc)
forall a b. (a -> b) -> a -> b
$
                     [XRec GhcTc (Pat GhcTc)] -> Boxity -> Pat GhcTc
mkVanillaTuplePat [XRec GhcTc (Pat GhcTc)]
lpats Boxity
Boxed

mkVanillaTuplePat :: [LPat GhcTc] -> Boxity -> Pat GhcTc
-- A vanilla tuple pattern simply gets its type from its sub-patterns
mkVanillaTuplePat :: [XRec GhcTc (Pat GhcTc)] -> Boxity -> Pat GhcTc
mkVanillaTuplePat [XRec GhcTc (Pat GhcTc)]
pats Boxity
box = XTuplePat GhcTc -> [XRec GhcTc (Pat GhcTc)] -> Boxity -> Pat GhcTc
forall p. XTuplePat p -> [LPat p] -> Boxity -> Pat p
TuplePat ((GenLocated SrcSpanAnnA (Pat GhcTc) -> Mult)
-> [GenLocated SrcSpanAnnA (Pat GhcTc)] -> [Mult]
forall a b. (a -> b) -> [a] -> [b]
map XRec GhcTc (Pat GhcTc) -> Mult
GenLocated SrcSpanAnnA (Pat GhcTc) -> Mult
hsLPatType [XRec GhcTc (Pat GhcTc)]
[GenLocated SrcSpanAnnA (Pat GhcTc)]
pats) [XRec GhcTc (Pat GhcTc)]
pats Boxity
box

-- The Big equivalents for the source tuple expressions
mkBigLHsVarTupId :: [Id] -> LHsExpr GhcTc
mkBigLHsVarTupId :: [Var] -> LHsExpr GhcTc
mkBigLHsVarTupId [Var]
ids = [LHsExpr GhcTc] -> LHsExpr GhcTc
mkBigLHsTupId ((Var -> GenLocated SrcSpanAnnA (HsExpr GhcTc))
-> [Var] -> [GenLocated SrcSpanAnnA (HsExpr GhcTc)]
forall a b. (a -> b) -> [a] -> [b]
map IdP GhcTc -> LHsExpr GhcTc
Var -> GenLocated SrcSpanAnnA (HsExpr GhcTc)
forall (p :: Pass) a.
IsSrcSpanAnn p a =>
IdP (GhcPass p) -> LHsExpr (GhcPass p)
nlHsVar [Var]
ids)

mkBigLHsTupId :: [LHsExpr GhcTc] -> LHsExpr GhcTc
mkBigLHsTupId :: [LHsExpr GhcTc] -> LHsExpr GhcTc
mkBigLHsTupId = ([GenLocated SrcSpanAnnA (HsExpr GhcTc)]
 -> GenLocated SrcSpanAnnA (HsExpr GhcTc))
-> [GenLocated SrcSpanAnnA (HsExpr GhcTc)]
-> GenLocated SrcSpanAnnA (HsExpr GhcTc)
forall a. ([a] -> a) -> [a] -> a
mkChunkified (\[GenLocated SrcSpanAnnA (HsExpr GhcTc)]
e -> [LHsExpr GhcTc] -> XExplicitTuple GhcTc -> LHsExpr GhcTc
forall (p :: Pass).
[LHsExpr (GhcPass p)]
-> XExplicitTuple (GhcPass p) -> LHsExpr (GhcPass p)
mkLHsTupleExpr [LHsExpr GhcTc]
[GenLocated SrcSpanAnnA (HsExpr GhcTc)]
e XExplicitTuple GhcTc
NoExtField
noExtField)

-- The Big equivalents for the source tuple patterns
mkBigLHsVarPatTupId :: [Id] -> LPat GhcTc
mkBigLHsVarPatTupId :: [Var] -> XRec GhcTc (Pat GhcTc)
mkBigLHsVarPatTupId [Var]
bs = [XRec GhcTc (Pat GhcTc)] -> XRec GhcTc (Pat GhcTc)
mkBigLHsPatTupId ((Var -> GenLocated SrcSpanAnnA (Pat GhcTc))
-> [Var] -> [GenLocated SrcSpanAnnA (Pat GhcTc)]
forall a b. (a -> b) -> [a] -> [b]
map IdP GhcTc -> XRec GhcTc (Pat GhcTc)
Var -> GenLocated SrcSpanAnnA (Pat GhcTc)
forall (p :: Pass) a.
IsSrcSpanAnn p a =>
IdP (GhcPass p) -> LPat (GhcPass p)
nlVarPat [Var]
bs)

mkBigLHsPatTupId :: [LPat GhcTc] -> LPat GhcTc
mkBigLHsPatTupId :: [XRec GhcTc (Pat GhcTc)] -> XRec GhcTc (Pat GhcTc)
mkBigLHsPatTupId = ([GenLocated SrcSpanAnnA (Pat GhcTc)]
 -> GenLocated SrcSpanAnnA (Pat GhcTc))
-> [GenLocated SrcSpanAnnA (Pat GhcTc)]
-> GenLocated SrcSpanAnnA (Pat GhcTc)
forall a. ([a] -> a) -> [a] -> a
mkChunkified [XRec GhcTc (Pat GhcTc)] -> XRec GhcTc (Pat GhcTc)
[GenLocated SrcSpanAnnA (Pat GhcTc)]
-> GenLocated SrcSpanAnnA (Pat GhcTc)
mkLHsPatTup

{-
************************************************************************
*                                                                      *
        Code for pattern-matching and other failures
*                                                                      *
************************************************************************

Generally, we handle pattern matching failure like this: let-bind a
fail-variable, and use that variable if the thing fails:
\begin{verbatim}
        let fail.33 = error "Help"
        in
        case x of
                p1 -> ...
                p2 -> fail.33
                p3 -> fail.33
                p4 -> ...
\end{verbatim}
Then
\begin{itemize}
\item
If the case can't fail, then there'll be no mention of @fail.33@, and the
simplifier will later discard it.

\item
If it can fail in only one way, then the simplifier will inline it.

\item
Only if it is used more than once will the let-binding remain.
\end{itemize}

There's a problem when the result of the case expression is of
unboxed type.  Then the type of @fail.33@ is unboxed too, and
there is every chance that someone will change the let into a case:
\begin{verbatim}
        case error "Help" of
          fail.33 -> case ....
\end{verbatim}

which is of course utterly wrong.  Rather than drop the condition that
only boxed types can be let-bound, we just turn the fail into a function
for the primitive case:
\begin{verbatim}
        let fail.33 :: Void -> Int#
            fail.33 = \_ -> error "Help"
        in
        case x of
                p1 -> ...
                p2 -> fail.33 void
                p3 -> fail.33 void
                p4 -> ...
\end{verbatim}

Now @fail.33@ is a function, so it can be let-bound.

We would *like* to use join points here; in fact, these "fail variables" are
paradigmatic join points! Sadly, this breaks pattern synonyms, which desugar as
CPS functions - i.e. they take "join points" as parameters. It's not impossible
to imagine extending our type system to allow passing join points around (very
carefully), but we certainly don't support it now.

99.99% of the time, the fail variables wind up as join points in short order
anyway, and the Void# doesn't do much harm.
-}

mkFailurePair :: CoreExpr       -- Result type of the whole case expression
              -> DsM (CoreBind, -- Binds the newly-created fail variable
                                -- to \ _ -> expression
                      CoreExpr) -- Fail variable applied to realWorld#
-- See Note [Failure thunks and CPR]
mkFailurePair :: CoreExpr -> DsM (Bind Var, CoreExpr)
mkFailurePair CoreExpr
expr
  = do { Var
fail_fun_var <- Mult -> Mult -> DsM Var
newFailLocalDs Mult
ManyTy (Mult
unboxedUnitTy (() :: Constraint) => Mult -> Mult -> Mult
Mult -> Mult -> Mult
`mkVisFunTyMany` Mult
ty)
       ; Var
fail_fun_arg <- Mult -> Mult -> DsM Var
newSysLocalDs Mult
ManyTy Mult
unboxedUnitTy
       ; let real_arg :: Var
real_arg = Var -> Var
setOneShotLambda Var
fail_fun_arg
       ; (Bind Var, CoreExpr) -> DsM (Bind Var, CoreExpr)
forall a. a -> IOEnv (Env DsGblEnv DsLclEnv) a
forall (m :: * -> *) a. Monad m => a -> m a
return (Var -> CoreExpr -> Bind Var
forall b. b -> Expr b -> Bind b
NonRec Var
fail_fun_var (Var -> CoreExpr -> CoreExpr
forall b. b -> Expr b -> Expr b
Lam Var
real_arg CoreExpr
expr),
                 CoreExpr -> CoreExpr -> CoreExpr
forall b. Expr b -> Expr b -> Expr b
App (Var -> CoreExpr
forall b. Var -> Expr b
Var Var
fail_fun_var) CoreExpr
unboxedUnitExpr) }
  where
    ty :: Mult
ty = (() :: Constraint) => CoreExpr -> Mult
CoreExpr -> Mult
exprType CoreExpr
expr

-- Uses '@mkFailurePair@' to bind the failure case. Infallible matches have
-- neither a failure arg or failure "hole", so nothing is let-bound, and no
-- extraneous Core is produced.
shareFailureHandler :: MatchResult CoreExpr -> MatchResult CoreExpr
shareFailureHandler :: MatchResult CoreExpr -> MatchResult CoreExpr
shareFailureHandler = \case
  mr :: MatchResult CoreExpr
mr@(MR_Infallible DsM CoreExpr
_) -> MatchResult CoreExpr
mr
  MR_Fallible CoreExpr -> DsM CoreExpr
match_fn -> (CoreExpr -> DsM CoreExpr) -> MatchResult CoreExpr
forall a. (CoreExpr -> DsM a) -> MatchResult a
MR_Fallible ((CoreExpr -> DsM CoreExpr) -> MatchResult CoreExpr)
-> (CoreExpr -> DsM CoreExpr) -> MatchResult CoreExpr
forall a b. (a -> b) -> a -> b
$ \CoreExpr
fail_expr -> do
    (Bind Var
fail_bind, CoreExpr
shared_failure_handler) <- CoreExpr -> DsM (Bind Var, CoreExpr)
mkFailurePair CoreExpr
fail_expr
    CoreExpr
body <- CoreExpr -> DsM CoreExpr
match_fn CoreExpr
shared_failure_handler
    -- Never unboxed, per the above, so always OK for `let` not `case`.
    CoreExpr -> DsM CoreExpr
forall a. a -> IOEnv (Env DsGblEnv DsLclEnv) a
forall (m :: * -> *) a. Monad m => a -> m a
return (CoreExpr -> DsM CoreExpr) -> CoreExpr -> DsM CoreExpr
forall a b. (a -> b) -> a -> b
$ Bind Var -> CoreExpr -> CoreExpr
forall b. Bind b -> Expr b -> Expr b
Let Bind Var
fail_bind CoreExpr
body

{-
Note [Failure thunks and CPR]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
(This note predates join points as formal entities (hence the quotation marks).
We can't use actual join points here (see above); if we did, this would also
solve the CPR problem, since join points don't get CPR'd. See Note [Don't w/w
join points for CPR] in GHC.Core.Opt.WorkWrap.)

When we make a failure point we ensure that it
does not look like a thunk. Example:

   let fail = \rw -> error "urk"
   in case x of
        [] -> fail realWorld#
        (y:ys) -> case ys of
                    [] -> fail realWorld#
                    (z:zs) -> (y,z)

Reason: we know that a failure point is always a "join point" and is
entered at most once.  Adding a dummy 'realWorld' token argument makes
it clear that sharing is not an issue.  And that in turn makes it more
CPR-friendly.  This matters a lot: if you don't get it right, you lose
the tail call property.  For example, see #3403.
-}

dsHandleMonadicFailure :: HsDoFlavour -> LPat GhcTc -> MatchResult CoreExpr -> FailOperator GhcTc -> DsM CoreExpr
    -- In a do expression, pattern-match failure just calls
    -- the monadic 'fail' rather than throwing an exception
dsHandleMonadicFailure :: HsDoFlavour
-> XRec GhcTc (Pat GhcTc)
-> MatchResult CoreExpr
-> FailOperator GhcTc
-> DsM CoreExpr
dsHandleMonadicFailure HsDoFlavour
ctx XRec GhcTc (Pat GhcTc)
pat MatchResult CoreExpr
match FailOperator GhcTc
m_fail_op =
  case MatchResult CoreExpr -> MatchResult CoreExpr
shareFailureHandler MatchResult CoreExpr
match of
    MR_Infallible DsM CoreExpr
body -> DsM CoreExpr
body
    MR_Fallible CoreExpr -> DsM CoreExpr
body -> do
      SyntaxExprTc
fail_op <- case FailOperator GhcTc
m_fail_op of
        -- Note that (non-monadic) list comprehension, pattern guards, etc could
        -- have fallible bindings without an explicit failure op, but this is
        -- handled elsewhere. See Note [Failing pattern matches in Stmts] the
        -- breakdown of regular and special binds.
        FailOperator GhcTc
Nothing -> String -> SDoc -> IOEnv (Env DsGblEnv DsLclEnv) SyntaxExprTc
forall a. HasCallStack => String -> SDoc -> a
pprPanic String
"missing fail op" (SDoc -> IOEnv (Env DsGblEnv DsLclEnv) SyntaxExprTc)
-> SDoc -> IOEnv (Env DsGblEnv DsLclEnv) SyntaxExprTc
forall a b. (a -> b) -> a -> b
$
          String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"Pattern match:" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> GenLocated SrcSpanAnnA (Pat GhcTc) -> SDoc
forall a. Outputable a => a -> SDoc
ppr XRec GhcTc (Pat GhcTc)
GenLocated SrcSpanAnnA (Pat GhcTc)
pat SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+>
          String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"is failable, and fail_expr was left unset"
        Just SyntaxExpr GhcTc
fail_op -> SyntaxExprTc -> IOEnv (Env DsGblEnv DsLclEnv) SyntaxExprTc
forall a. a -> IOEnv (Env DsGblEnv DsLclEnv) a
forall (f :: * -> *) a. Applicative f => a -> f a
pure SyntaxExpr GhcTc
SyntaxExprTc
fail_op
      DynFlags
dflags <- IOEnv (Env DsGblEnv DsLclEnv) DynFlags
forall (m :: * -> *). HasDynFlags m => m DynFlags
getDynFlags
      CoreExpr
fail_msg <- String -> DsM CoreExpr
forall (m :: * -> *). MonadThings m => String -> m CoreExpr
mkStringExpr (DynFlags
-> HsDoFlavour -> GenLocated SrcSpanAnnA (Pat GhcTc) -> String
forall e. DynFlags -> HsDoFlavour -> LocatedA e -> String
mk_fail_msg DynFlags
dflags HsDoFlavour
ctx XRec GhcTc (Pat GhcTc)
GenLocated SrcSpanAnnA (Pat GhcTc)
pat)
      CoreExpr
fail_expr <- SyntaxExpr GhcTc -> [CoreExpr] -> DsM CoreExpr
dsSyntaxExpr SyntaxExpr GhcTc
SyntaxExprTc
fail_op [CoreExpr
fail_msg]
      CoreExpr -> DsM CoreExpr
body CoreExpr
fail_expr

mk_fail_msg :: DynFlags -> HsDoFlavour -> LocatedA e -> String
mk_fail_msg :: forall e. DynFlags -> HsDoFlavour -> LocatedA e -> String
mk_fail_msg DynFlags
dflags HsDoFlavour
ctx LocatedA e
pat
  = DynFlags -> SDoc -> String
forall a. Outputable a => DynFlags -> a -> String
showPpr DynFlags
dflags (SDoc -> String) -> SDoc -> String
forall a b. (a -> b) -> a -> b
$ String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"Pattern match failure in" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> HsDoFlavour -> SDoc
pprHsDoFlavour HsDoFlavour
ctx
                   SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"at" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> SrcSpan -> SDoc
forall a. Outputable a => a -> SDoc
ppr (LocatedA e -> SrcSpan
forall a e. GenLocated (SrcSpanAnn' a) e -> SrcSpan
getLocA LocatedA e
pat)

{- *********************************************************************
*                                                                      *
              Ticks
*                                                                      *
********************************************************************* -}

mkOptTickBox :: [CoreTickish] -> CoreExpr -> CoreExpr
mkOptTickBox :: [CoreTickish] -> CoreExpr -> CoreExpr
mkOptTickBox = (CoreExpr -> [CoreTickish] -> CoreExpr)
-> [CoreTickish] -> CoreExpr -> CoreExpr
forall a b c. (a -> b -> c) -> b -> a -> c
flip ((CoreTickish -> CoreExpr -> CoreExpr)
-> CoreExpr -> [CoreTickish] -> CoreExpr
forall a b. (a -> b -> b) -> b -> [a] -> b
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr CoreTickish -> CoreExpr -> CoreExpr
forall b. CoreTickish -> Expr b -> Expr b
Tick)

mkBinaryTickBox :: Int -> Int -> CoreExpr -> DsM CoreExpr
mkBinaryTickBox :: ConTag -> ConTag -> CoreExpr -> DsM CoreExpr
mkBinaryTickBox ConTag
ixT ConTag
ixF CoreExpr
e = do
       Unique
uq <- TcRnIf DsGblEnv DsLclEnv Unique
forall gbl lcl. TcRnIf gbl lcl Unique
newUnique
       Module
this_mod <- IOEnv (Env DsGblEnv DsLclEnv) Module
forall (m :: * -> *). HasModule m => m Module
getModule
       let bndr1 :: Var
bndr1 = FastString -> Unique -> Mult -> Mult -> Var
mkSysLocal (String -> FastString
fsLit String
"t1") Unique
uq Mult
OneTy Mult
boolTy
         -- It's always sufficient to pattern-match on a boolean with
         -- multiplicity 'One'.
       let
           falseBox :: CoreExpr
falseBox = CoreTickish -> CoreExpr -> CoreExpr
forall b. CoreTickish -> Expr b -> Expr b
Tick (Module -> ConTag -> CoreTickish
forall (pass :: TickishPass). Module -> ConTag -> GenTickish pass
HpcTick Module
this_mod ConTag
ixF) (Var -> CoreExpr
forall b. Var -> Expr b
Var Var
falseDataConId)
           trueBox :: CoreExpr
trueBox  = CoreTickish -> CoreExpr -> CoreExpr
forall b. CoreTickish -> Expr b -> Expr b
Tick (Module -> ConTag -> CoreTickish
forall (pass :: TickishPass). Module -> ConTag -> GenTickish pass
HpcTick Module
this_mod ConTag
ixT) (Var -> CoreExpr
forall b. Var -> Expr b
Var Var
trueDataConId)
       --
       CoreExpr -> DsM CoreExpr
forall a. a -> IOEnv (Env DsGblEnv DsLclEnv) a
forall (m :: * -> *) a. Monad m => a -> m a
return (CoreExpr -> DsM CoreExpr) -> CoreExpr -> DsM CoreExpr
forall a b. (a -> b) -> a -> b
$ CoreExpr -> Var -> Mult -> [Alt Var] -> CoreExpr
forall b. Expr b -> b -> Mult -> [Alt b] -> Expr b
Case CoreExpr
e Var
bndr1 Mult
boolTy
                       [ AltCon -> [Var] -> CoreExpr -> Alt Var
forall b. AltCon -> [b] -> Expr b -> Alt b
Alt (DataCon -> AltCon
DataAlt DataCon
falseDataCon) [] CoreExpr
falseBox
                       , AltCon -> [Var] -> CoreExpr -> Alt Var
forall b. AltCon -> [b] -> Expr b -> Alt b
Alt (DataCon -> AltCon
DataAlt DataCon
trueDataCon)  [] CoreExpr
trueBox
                       ]



-- *******************************************************************

{- Note [decideBangHood]
~~~~~~~~~~~~~~~~~~~~~~~~
With -XStrict we may make /outermost/ patterns more strict.
E.g.
       let (Just x) = e in ...
          ==>
       let !(Just x) = e in ...
and
       f x = e
          ==>
       f !x = e

This adjustment is done by decideBangHood,

  * Just before constructing an EqnInfo, in GHC.HsToCore.Match
      (matchWrapper and matchSinglePat)

  * When desugaring a pattern-binding in GHC.HsToCore.Binds.dsHsBind

Note that it is /not/ done recursively.  See the -XStrict
spec in the user manual.

Specifically:
   ~pat    => pat    -- when -XStrict (even if pat = ~pat')
   !pat    => !pat   -- always
   pat     => !pat   -- when -XStrict
   pat     => pat    -- otherwise
-}


-- | Use -XStrict to add a ! or remove a ~
-- See Note [decideBangHood]
decideBangHood :: DynFlags
               -> LPat GhcTc  -- ^ Original pattern
               -> LPat GhcTc  -- Pattern with bang if necessary
decideBangHood :: DynFlags -> XRec GhcTc (Pat GhcTc) -> XRec GhcTc (Pat GhcTc)
decideBangHood DynFlags
dflags XRec GhcTc (Pat GhcTc)
lpat
  | Bool -> Bool
not (Extension -> DynFlags -> Bool
xopt Extension
LangExt.Strict DynFlags
dflags)
  = XRec GhcTc (Pat GhcTc)
lpat
  | Bool
otherwise   --  -XStrict
  = GenLocated SrcSpanAnnA (Pat GhcTc)
-> GenLocated SrcSpanAnnA (Pat GhcTc)
forall {p} {l}.
(XRec p (Pat p) ~ GenLocated l (Pat p), XBangPat p ~ NoExtField) =>
GenLocated l (Pat p) -> GenLocated l (Pat p)
go XRec GhcTc (Pat GhcTc)
GenLocated SrcSpanAnnA (Pat GhcTc)
lpat
  where
    go :: GenLocated l (Pat p) -> GenLocated l (Pat p)
go lp :: GenLocated l (Pat p)
lp@(L l
l Pat p
p)
      = case Pat p
p of
           ParPat XParPat p
x LHsToken "(" p
lpar XRec p (Pat p)
p LHsToken ")" p
rpar -> l -> Pat p -> GenLocated l (Pat p)
forall l e. l -> e -> GenLocated l e
L l
l (XParPat p
-> LHsToken "(" p -> XRec p (Pat p) -> LHsToken ")" p -> Pat p
forall p.
XParPat p -> LHsToken "(" p -> LPat p -> LHsToken ")" p -> Pat p
ParPat XParPat p
x LHsToken "(" p
lpar (GenLocated l (Pat p) -> GenLocated l (Pat p)
go XRec p (Pat p)
GenLocated l (Pat p)
p) LHsToken ")" p
rpar)
           LazyPat XLazyPat p
_ XRec p (Pat p)
lp' -> XRec p (Pat p)
GenLocated l (Pat p)
lp'
           BangPat XBangPat p
_ XRec p (Pat p)
_   -> GenLocated l (Pat p)
lp
           Pat p
_             -> l -> Pat p -> GenLocated l (Pat p)
forall l e. l -> e -> GenLocated l e
L l
l (XBangPat p -> XRec p (Pat p) -> Pat p
forall p. XBangPat p -> LPat p -> Pat p
BangPat XBangPat p
NoExtField
noExtField XRec p (Pat p)
GenLocated l (Pat p)
lp)

isTrueLHsExpr :: LHsExpr GhcTc -> Maybe (CoreExpr -> DsM CoreExpr)

-- Returns Just {..} if we're sure that the expression is True
-- I.e.   * 'True' datacon
--        * 'otherwise' Id
--        * Trivial wrappings of these
-- The arguments to Just are any HsTicks that we have found,
-- because we still want to tick then, even it they are always evaluated.
isTrueLHsExpr :: LHsExpr GhcTc -> Maybe (CoreExpr -> DsM CoreExpr)
isTrueLHsExpr (L SrcSpanAnnA
_ (HsVar XVar GhcTc
_ (L SrcSpanAnnN
_ Var
v)))
  |  Var
v Var -> Unique -> Bool
forall a. Uniquable a => a -> Unique -> Bool
`hasKey` Unique
otherwiseIdKey
     Bool -> Bool -> Bool
|| Var
v Var -> Unique -> Bool
forall a. Uniquable a => a -> Unique -> Bool
`hasKey` Var -> Unique
forall a. Uniquable a => a -> Unique
getUnique Var
trueDataConId
                                              = (CoreExpr -> DsM CoreExpr) -> Maybe (CoreExpr -> DsM CoreExpr)
forall a. a -> Maybe a
Just CoreExpr -> DsM CoreExpr
forall a. a -> IOEnv (Env DsGblEnv DsLclEnv) a
forall (m :: * -> *) a. Monad m => a -> m a
return
        -- trueDataConId doesn't have the same unique as trueDataCon
isTrueLHsExpr (L SrcSpanAnnA
_ (XExpr (ConLikeTc ConLike
con [Var]
_ [Scaled Mult]
_)))
  | ConLike
con ConLike -> Unique -> Bool
forall a. Uniquable a => a -> Unique -> Bool
`hasKey` DataCon -> Unique
forall a. Uniquable a => a -> Unique
getUnique DataCon
trueDataCon = (CoreExpr -> DsM CoreExpr) -> Maybe (CoreExpr -> DsM CoreExpr)
forall a. a -> Maybe a
Just CoreExpr -> DsM CoreExpr
forall a. a -> IOEnv (Env DsGblEnv DsLclEnv) a
forall (m :: * -> *) a. Monad m => a -> m a
return
isTrueLHsExpr (L SrcSpanAnnA
_ (XExpr (HsTick CoreTickish
tickish LHsExpr GhcTc
e)))
    | Just CoreExpr -> DsM CoreExpr
ticks <- LHsExpr GhcTc -> Maybe (CoreExpr -> DsM CoreExpr)
isTrueLHsExpr LHsExpr GhcTc
e
    = (CoreExpr -> DsM CoreExpr) -> Maybe (CoreExpr -> DsM CoreExpr)
forall a. a -> Maybe a
Just (\CoreExpr
x -> do CoreExpr
wrapped <- CoreExpr -> DsM CoreExpr
ticks CoreExpr
x
                     CoreExpr -> DsM CoreExpr
forall a. a -> IOEnv (Env DsGblEnv DsLclEnv) a
forall (m :: * -> *) a. Monad m => a -> m a
return (CoreTickish -> CoreExpr -> CoreExpr
forall b. CoreTickish -> Expr b -> Expr b
Tick CoreTickish
tickish CoreExpr
wrapped))
   -- This encodes that the result is constant True for Hpc tick purposes;
   -- which is specifically what isTrueLHsExpr is trying to find out.
isTrueLHsExpr (L SrcSpanAnnA
_ (XExpr (HsBinTick ConTag
ixT ConTag
_ LHsExpr GhcTc
e)))
    | Just CoreExpr -> DsM CoreExpr
ticks <- LHsExpr GhcTc -> Maybe (CoreExpr -> DsM CoreExpr)
isTrueLHsExpr LHsExpr GhcTc
e
    = (CoreExpr -> DsM CoreExpr) -> Maybe (CoreExpr -> DsM CoreExpr)
forall a. a -> Maybe a
Just (\CoreExpr
x -> do CoreExpr
e <- CoreExpr -> DsM CoreExpr
ticks CoreExpr
x
                     Module
this_mod <- IOEnv (Env DsGblEnv DsLclEnv) Module
forall (m :: * -> *). HasModule m => m Module
getModule
                     CoreExpr -> DsM CoreExpr
forall a. a -> IOEnv (Env DsGblEnv DsLclEnv) a
forall (m :: * -> *) a. Monad m => a -> m a
return (CoreTickish -> CoreExpr -> CoreExpr
forall b. CoreTickish -> Expr b -> Expr b
Tick (Module -> ConTag -> CoreTickish
forall (pass :: TickishPass). Module -> ConTag -> GenTickish pass
HpcTick Module
this_mod ConTag
ixT) CoreExpr
e))

isTrueLHsExpr (L SrcSpanAnnA
_ (HsPar XPar GhcTc
_ LHsToken "(" GhcTc
_ LHsExpr GhcTc
e LHsToken ")" GhcTc
_)) = LHsExpr GhcTc -> Maybe (CoreExpr -> DsM CoreExpr)
isTrueLHsExpr LHsExpr GhcTc
e
isTrueLHsExpr LHsExpr GhcTc
_                     = Maybe (CoreExpr -> DsM CoreExpr)
forall a. Maybe a
Nothing