GHC.Types.Demand

ghc-9.0.0.20200925: The GHC API

Safe Haskell | None
Language | Haskell2010

GHC.Types.Demand

Synopsis

- data StrDmd
- data UseDmd
  - = UCall Count UseDmd
  - | UProd [ArgUse]
  - | UHead
  - | Used
- data Count
- type Demand = JointDmd ArgStr ArgUse
- type DmdShell = JointDmd (Str ()) (Use ())
- type CleanDemand = JointDmd StrDmd UseDmd
- getStrDmd :: JointDmd s u -> s
- getUseDmd :: JointDmd s u -> u
- mkProdDmd :: [Demand] -> CleanDemand
- mkOnceUsedDmd :: CleanDemand -> Demand
- mkManyUsedDmd :: CleanDemand -> Demand
- mkHeadStrict :: CleanDemand -> CleanDemand
- oneifyDmd :: JointDmd s (Use u) -> JointDmd s (Use u)
- toCleanDmd :: Demand -> (DmdShell, CleanDemand)
- absDmd :: Demand
- topDmd :: Demand
- botDmd :: Demand
- seqDmd :: Demand
- lubDmd :: Demand -> Demand -> Demand
- bothDmd :: Demand -> Demand -> Demand
- lazyApply1Dmd :: Demand
- lazyApply2Dmd :: Demand
- strictApply1Dmd :: Demand
- isTopDmd :: Demand -> Bool
- isAbsDmd :: JointDmd (Str s) (Use u) -> Bool
- isSeqDmd :: Demand -> Bool
- peelUseCall :: UseDmd -> Maybe (Count, UseDmd)
- cleanUseDmd_maybe :: Demand -> Maybe UseDmd
- strictenDmd :: Demand -> Demand
- bothCleanDmd :: CleanDemand -> CleanDemand -> CleanDemand
- addCaseBndrDmd :: Demand -> [Demand] -> [Demand]
- data DmdType = DmdType DmdEnv [Demand] Divergence
- dmdTypeDepth :: DmdType -> Arity
- lubDmdType :: DmdType -> DmdType -> DmdType
- bothDmdType :: DmdType -> BothDmdArg -> DmdType
- type BothDmdArg = (DmdEnv, Divergence)
- mkBothDmdArg :: DmdEnv -> BothDmdArg
- toBothDmdArg :: DmdType -> BothDmdArg
- nopDmdType :: DmdType
- botDmdType :: DmdType
- addDemand :: Demand -> DmdType -> DmdType
- type DmdEnv = VarEnv Demand
- emptyDmdEnv :: VarEnv Demand
- peelFV :: DmdType -> Var -> (DmdType, Demand)
- findIdDemand :: DmdType -> Var -> Demand
- data Divergence
  - = Diverges
  - | ExnOrDiv
  - | Dunno
- lubDivergence :: Divergence -> Divergence -> Divergence
- isDeadEndDiv :: Divergence -> Bool
- topDiv :: Divergence
- botDiv :: Divergence
- exnDiv :: Divergence
- appIsDeadEnd :: StrictSig -> Int -> Bool
- isDeadEndSig :: StrictSig -> Bool
- pprIfaceStrictSig :: StrictSig -> SDoc
- newtype StrictSig = StrictSig DmdType
- mkStrictSigForArity :: Arity -> DmdType -> StrictSig
- mkClosedStrictSig :: [Demand] -> Divergence -> StrictSig
- nopSig :: StrictSig
- botSig :: StrictSig
- isTopSig :: StrictSig -> Bool
- hasDemandEnvSig :: StrictSig -> Bool
- splitStrictSig :: StrictSig -> ([Demand], Divergence)
- strictSigDmdEnv :: StrictSig -> DmdEnv
- prependArgsStrictSig :: Int -> StrictSig -> StrictSig
- etaConvertStrictSig :: Arity -> StrictSig -> StrictSig
- seqDemand :: Demand -> ()
- seqDemandList :: [Demand] -> ()
- seqDmdType :: DmdType -> ()
- seqStrictSig :: StrictSig -> ()
- evalDmd :: Demand
- cleanEvalDmd :: CleanDemand
- cleanEvalProdDmd :: Arity -> CleanDemand
- isStrictDmd :: JointDmd (Str s) (Use u) -> Bool
- splitDmdTy :: DmdType -> (Demand, DmdType)
- splitFVs :: Bool -> DmdEnv -> (DmdEnv, DmdEnv)
- deferAfterPreciseException :: DmdType -> DmdType
- postProcessUnsat :: DmdShell -> DmdType -> DmdType
- postProcessDmdType :: DmdShell -> DmdType -> BothDmdArg
- splitProdDmd_maybe :: Demand -> Maybe [Demand]
- peelCallDmd :: CleanDemand -> (CleanDemand, DmdShell)
- peelManyCalls :: Int -> CleanDemand -> DmdShell
- mkCallDmd :: CleanDemand -> CleanDemand
- mkCallDmds :: Arity -> CleanDemand -> CleanDemand
- mkWorkerDemand :: Int -> Demand
- dmdTransformSig :: StrictSig -> CleanDemand -> DmdType
- dmdTransformDataConSig :: Arity -> CleanDemand -> DmdType
- dmdTransformDictSelSig :: StrictSig -> CleanDemand -> DmdType
- argOneShots :: Demand -> [OneShotInfo]
- argsOneShots :: StrictSig -> Arity -> [[OneShotInfo]]
- saturatedByOneShots :: Int -> Demand -> Bool
- data TypeShape
  - = TsFun TypeShape
  - | TsProd [TypeShape]
  - | TsUnk
- trimToType :: Demand -> TypeShape -> Demand
- useCount :: Use u -> Count
- isUsedOnce :: JointDmd (Str s) (Use u) -> Bool
- reuseEnv :: DmdEnv -> DmdEnv
- zapUsageDemand :: Demand -> Demand
- zapUsageEnvSig :: StrictSig -> StrictSig
- zapUsedOnceDemand :: Demand -> Demand
- zapUsedOnceSig :: StrictSig -> StrictSig
- strictifyDictDmd :: Type -> Demand -> Demand
- strictifyDmd :: Demand -> Demand

# Documentation

data StrDmd Source #

Vanilla strictness domain

#### Instances

Instances details

Eq StrDmd # |
Instance details Defined in GHC.Types.Demand Methods (==) :: StrDmd -> StrDmd -> Bool # (/=) :: StrDmd -> StrDmd -> Bool #
Show StrDmd # |
Instance details Defined in GHC.Types.Demand Methods showsPrec :: Int -> StrDmd -> ShowS Source # show :: StrDmd -> String Source # showList :: [StrDmd] -> ShowS Source #
Outputable StrDmd # |
Instance details Defined in GHC.Types.Demand Methods ppr :: StrDmd -> SDoc Source # pprPrec :: Rational -> StrDmd -> SDoc Source #
Binary StrDmd # |
Instance details Defined in GHC.Types.Demand Methods put_ :: BinHandle -> StrDmd -> IO () Source # put :: BinHandle -> StrDmd -> IO (Bin StrDmd) Source # get :: BinHandle -> IO StrDmd Source #

data UseDmd Source #

Domain for genuine usage

Constructors

UCall Count UseDmd | Call demand for absence. Used only for values of function type
UProd [ArgUse] | Product. Used only for values of product type See Note [Don't optimise UProd(Used) to Used] Invariant: Not all components are Abs (in that case, use UHead)
UHead | May be used but its sub-components are definitely *not* used. For product types, UHead is equivalent to U(AAA); see mkUProd. UHead is needed only to express the demand of `seq` and 'case' which are polymorphic; i.e. the scrutinised value is of type `a` rather than a product type. That's why we can't use UProd [A,A,A] Since (UCall _ Abs) is ill-typed, UHead doesn't make sense for lambdas
Used | May be used and its sub-components may be used. (top of the lattice)

#### Instances

Instances details

Eq UseDmd # |
Instance details Defined in GHC.Types.Demand Methods (==) :: UseDmd -> UseDmd -> Bool # (/=) :: UseDmd -> UseDmd -> Bool #
Show UseDmd # |
Instance details Defined in GHC.Types.Demand Methods showsPrec :: Int -> UseDmd -> ShowS Source # show :: UseDmd -> String Source # showList :: [UseDmd] -> ShowS Source #
Outputable UseDmd # |
Instance details Defined in GHC.Types.Demand Methods ppr :: UseDmd -> SDoc Source # pprPrec :: Rational -> UseDmd -> SDoc Source #
Binary UseDmd # |
Instance details Defined in GHC.Types.Demand Methods put_ :: BinHandle -> UseDmd -> IO () Source # put :: BinHandle -> UseDmd -> IO (Bin UseDmd) Source # get :: BinHandle -> IO UseDmd Source #

data Count Source #

Abstract counting of usages

#### Instances

Instances details

Eq Count # |
Instance details Defined in GHC.Types.Demand Methods (==) :: Count -> Count -> Bool # (/=) :: Count -> Count -> Bool #
Show Count # |
Instance details Defined in GHC.Types.Demand Methods showsPrec :: Int -> Count -> ShowS Source # show :: Count -> String Source # showList :: [Count] -> ShowS Source #
Outputable Count # |
Instance details Defined in GHC.Types.Demand Methods ppr :: Count -> SDoc Source # pprPrec :: Rational -> Count -> SDoc Source #
Binary Count # |
Instance details Defined in GHC.Types.Demand Methods put_ :: BinHandle -> Count -> IO () Source # put :: BinHandle -> Count -> IO (Bin Count) Source # get :: BinHandle -> IO Count Source #

type Demand = JointDmd ArgStr ArgUse Source #

type DmdShell = JointDmd (Str ()) (Use ()) Source #

type CleanDemand = JointDmd StrDmd UseDmd Source #

getStrDmd :: JointDmd s u -> s Source #

getUseDmd :: JointDmd s u -> u Source #

mkProdDmd :: [Demand] -> CleanDemand Source #

mkOnceUsedDmd :: CleanDemand -> Demand Source #

mkManyUsedDmd :: CleanDemand -> Demand Source #

mkHeadStrict :: CleanDemand -> CleanDemand Source #

oneifyDmd :: JointDmd s (Use u) -> JointDmd s (Use u) Source #

toCleanDmd :: Demand -> (DmdShell, CleanDemand) Source #

absDmd :: Demand Source #

topDmd :: Demand Source #

botDmd :: Demand Source #

seqDmd :: Demand Source #

lubDmd :: Demand -> Demand -> Demand Source #

bothDmd :: Demand -> Demand -> Demand Source #

lazyApply1Dmd :: Demand Source #

lazyApply2Dmd :: Demand Source #

strictApply1Dmd :: Demand Source #

isTopDmd :: Demand -> Bool Source #

isAbsDmd :: JointDmd (Str s) (Use u) -> Bool Source #

isSeqDmd :: Demand -> Bool Source #

peelUseCall :: UseDmd -> Maybe (Count, UseDmd) Source #

cleanUseDmd_maybe :: Demand -> Maybe UseDmd Source #

strictenDmd :: Demand -> Demand Source #

bothCleanDmd :: CleanDemand -> CleanDemand -> CleanDemand Source #

addCaseBndrDmd :: Demand -> [Demand] -> [Demand] Source #

data DmdType Source #

Constructors

DmdType DmdEnv [Demand] Divergence |

#### Instances

Instances details

Eq DmdType # |
Instance details Defined in GHC.Types.Demand Methods (==) :: DmdType -> DmdType -> Bool # (/=) :: DmdType -> DmdType -> Bool #
Outputable DmdType # |
Instance details Defined in GHC.Types.Demand Methods ppr :: DmdType -> SDoc Source # pprPrec :: Rational -> DmdType -> SDoc Source #
Binary DmdType # |
Instance details Defined in GHC.Types.Demand Methods put_ :: BinHandle -> DmdType -> IO () Source # put :: BinHandle -> DmdType -> IO (Bin DmdType) Source # get :: BinHandle -> IO DmdType Source #

dmdTypeDepth :: DmdType -> Arity Source #

lubDmdType :: DmdType -> DmdType -> DmdType Source #

Compute the least upper bound of two `DmdType`s elicited /by the same incoming demand/!

bothDmdType :: DmdType -> BothDmdArg -> DmdType Source #

type BothDmdArg = (DmdEnv, Divergence) Source #

mkBothDmdArg :: DmdEnv -> BothDmdArg Source #

toBothDmdArg :: DmdType -> BothDmdArg Source #

nopDmdType :: DmdType Source #

The demand type of doing nothing (lazy, absent, no Divergence information). Note that it is '`not'` the top of the lattice (which would be "may use everything"), so it is (no longer) called topDmdType. (SG: I agree, but why is it still `topDmd` then?)

botDmdType :: DmdType Source #

addDemand :: Demand -> DmdType -> DmdType Source #

type DmdEnv = VarEnv Demand Source #

emptyDmdEnv :: VarEnv Demand Source #

peelFV :: DmdType -> Var -> (DmdType, Demand) Source #

findIdDemand :: DmdType -> Var -> Demand Source #

data Divergence Source #

Divergence lattice. Models a subset lattice of the following exhaustive set of divergence results:

n
  nontermination (e.g. loops)
i
  throws imprecise exception
p
  throws precise exception
c
  converges (reduces to WHNF)

The different lattice elements correspond to different subsets, indicated by juxtaposition of indicators (e.g. nc definitely doesn't throw an exception, and may or may not reduce to WHNF).

                Dunno (nipc)
                     |
               ExnOrDiv (nip)
                     |
               Diverges (ni)

As you can see, we don't distinguish n and i. See Note [Precise exceptions and strictness analysis] for why p is so special compared to i.

Constructors

Diverges | Definitely throws an imprecise exception or diverges.
ExnOrDiv | Definitely throws a *precise* exception, an imprecise exception or diverges. Never converges, hence `isDeadEndDiv`! See scenario 1 in Note [Precise exceptions and strictness analysis].
Dunno | Might diverge, throw any kind of exception or converge.

#### Instances

Instances details

Eq Divergence # |
Instance details Defined in GHC.Types.Demand Methods (==) :: Divergence -> Divergence -> Bool # (/=) :: Divergence -> Divergence -> Bool #
Show Divergence # |
Instance details Defined in GHC.Types.Demand Methods showsPrec :: Int -> Divergence -> ShowS Source # show :: Divergence -> String Source # showList :: [Divergence] -> ShowS Source #
Outputable Divergence # |
Instance details Defined in GHC.Types.Demand Methods ppr :: Divergence -> SDoc Source # pprPrec :: Rational -> Divergence -> SDoc Source #
Binary Divergence # |
Instance details Defined in GHC.Types.Demand Methods put_ :: BinHandle -> Divergence -> IO () Source # put :: BinHandle -> Divergence -> IO (Bin Divergence) Source # get :: BinHandle -> IO Divergence Source #

lubDivergence :: Divergence -> Divergence -> Divergence Source #

isDeadEndDiv :: Divergence -> Bool Source #

True if the result indicates that evaluation will not return. See Note [Dead ends].

topDiv :: Divergence Source #

botDiv :: Divergence Source #

exnDiv :: Divergence Source #

appIsDeadEnd :: StrictSig -> Int -> Bool Source #

Returns true if an application to n args would diverge or throw an exception. See Note [Unsaturated applications] and Note [Dead ends].

isDeadEndSig :: StrictSig -> Bool Source #

True if the signature diverges or throws an exception in a saturated call. See Note [Dead ends].

pprIfaceStrictSig :: StrictSig -> SDoc Source #

newtype StrictSig Source #

The depth of the wrapped `DmdType` encodes the arity at which it is safe to unleash. Better construct this through `mkStrictSigForArity`. See Note [Understanding DmdType and StrictSig]

Constructors

StrictSig DmdType |

#### Instances

Instances details

Eq StrictSig # |
Instance details Defined in GHC.Types.Demand Methods (==) :: StrictSig -> StrictSig -> Bool # (/=) :: StrictSig -> StrictSig -> Bool #
Outputable StrictSig # |
Instance details Defined in GHC.Types.Demand Methods ppr :: StrictSig -> SDoc Source # pprPrec :: Rational -> StrictSig -> SDoc Source #
Binary StrictSig # |
Instance details Defined in GHC.Types.Demand Methods put_ :: BinHandle -> StrictSig -> IO () Source # put :: BinHandle -> StrictSig -> IO (Bin StrictSig) Source # get :: BinHandle -> IO StrictSig Source #

mkStrictSigForArity :: Arity -> DmdType -> StrictSig Source #

Turns a `DmdType` computed for the particular `Arity` into a `StrictSig` unleashable at that arity. See Note [Understanding DmdType and StrictSig]

mkClosedStrictSig :: [Demand] -> Divergence -> StrictSig Source #

nopSig :: StrictSig Source #

botSig :: StrictSig Source #

isTopSig :: StrictSig -> Bool Source #

hasDemandEnvSig :: StrictSig -> Bool Source #

splitStrictSig :: StrictSig -> ([Demand], Divergence) Source #

strictSigDmdEnv :: StrictSig -> DmdEnv Source #

prependArgsStrictSig :: Int -> StrictSig -> StrictSig Source #

Add extra (`topDmd`) arguments to a strictness signature. In contrast to `etaConvertStrictSig`, this prepends additional argument demands. This is used by FloatOut.

etaConvertStrictSig :: Arity -> StrictSig -> StrictSig Source #

We are expanding (x y. e) to (x y z. e z) or reducing from the latter to the former (when the Simplifier identifies a new join points, for example). In contrast to `prependArgsStrictSig`, this appends extra arg demands if necessary. This works by looking at the `DmdType` (which was produced under a call demand for the old arity) and trying to transfer as many facts as we can to the call demand of new arity. An arity increase (resulting in a stronger incoming demand) can retain much of the info, while an arity decrease (a weakening of the incoming demand) must fall back to a conservative default.

seqDemand :: Demand -> () Source #

seqDemandList :: [Demand] -> () Source #

seqDmdType :: DmdType -> () Source #

seqStrictSig :: StrictSig -> () Source #

evalDmd :: Demand Source #

cleanEvalDmd :: CleanDemand Source #

cleanEvalProdDmd :: Arity -> CleanDemand Source #

isStrictDmd :: JointDmd (Str s) (Use u) -> Bool Source #

splitDmdTy :: DmdType -> (Demand, DmdType) Source #

splitFVs :: Bool -> DmdEnv -> (DmdEnv, DmdEnv) Source #

deferAfterPreciseException :: DmdType -> DmdType Source #

When e is evaluated after executing an IO action that may throw a precise exception, we act as if there is an additional control flow path that is taken if e throws a precise exception. The demand type of this control flow path * is lazy and absent (`topDmd`) in all free variables and arguments * has `exnDiv` `Divergence` result So we can simply take a variant of `nopDmdType`, `exnDmdType`. Why not `nopDmdType`? Because then the result of `e` can never be `exnDiv`! That means failure to drop dead-ends, see #18086. See Note [Precise exceptions and strictness analysis]

postProcessUnsat :: DmdShell -> DmdType -> DmdType Source #

postProcessDmdType :: DmdShell -> DmdType -> BothDmdArg Source #

splitProdDmd_maybe :: Demand -> Maybe [Demand] Source #

peelCallDmd :: CleanDemand -> (CleanDemand, DmdShell) Source #

peelManyCalls :: Int -> CleanDemand -> DmdShell Source #

mkCallDmd :: CleanDemand -> CleanDemand Source #

Wraps the `CleanDemand` with a one-shot call demand: `d` -> `C1(d)`.

mkCallDmds :: Arity -> CleanDemand -> CleanDemand Source #

`mkCallDmds n d` returns `C1(C1...(C1 d))` where there are `n` `C1`'s.

mkWorkerDemand :: Int -> Demand Source #

dmdTransformSig :: StrictSig -> CleanDemand -> DmdType Source #

dmdTransformDataConSig :: Arity -> CleanDemand -> DmdType Source #

dmdTransformDictSelSig :: StrictSig -> CleanDemand -> DmdType Source #

argOneShots :: Demand -> [OneShotInfo] Source #

argsOneShots :: StrictSig -> Arity -> [[OneShotInfo]] Source #

saturatedByOneShots :: Int -> Demand -> Bool Source #

data TypeShape Source #

Constructors

TsFun TypeShape |
TsProd [TypeShape] |
TsUnk |

#### Instances

Instances details

Outputable TypeShape # |
Instance details Defined in GHC.Types.Demand Methods ppr :: TypeShape -> SDoc Source # pprPrec :: Rational -> TypeShape -> SDoc Source #

trimToType :: Demand -> TypeShape -> Demand Source #

useCount :: Use u -> Count Source #

isUsedOnce :: JointDmd (Str s) (Use u) -> Bool Source #

reuseEnv :: DmdEnv -> DmdEnv Source #

zapUsageDemand :: Demand -> Demand Source #

zapUsageEnvSig :: StrictSig -> StrictSig Source #

zapUsedOnceDemand :: Demand -> Demand Source #

Remove all 1* information (but not C1 information) from the demand

zapUsedOnceSig :: StrictSig -> StrictSig Source #

Remove all 1* information (but not C1 information) from the strictness signature

strictifyDictDmd :: Type -> Demand -> Demand Source #

strictifyDmd :: Demand -> Demand Source #