Safe Haskell | None |
---|---|

Language | GHC2021 |

Commonly useful utilities for manipulating the Core language

## Synopsis

- mkCast :: HasDebugCallStack => CoreExpr -> CoercionR -> CoreExpr
- mkCastMCo :: CoreExpr -> MCoercionR -> CoreExpr
- mkPiMCo :: Var -> MCoercionR -> MCoercionR
- mkTick :: CoreTickish -> CoreExpr -> CoreExpr
- mkTicks :: [CoreTickish] -> CoreExpr -> CoreExpr
- mkTickNoHNF :: CoreTickish -> CoreExpr -> CoreExpr
- tickHNFArgs :: CoreTickish -> CoreExpr -> CoreExpr
- bindNonRec :: HasDebugCallStack => Id -> CoreExpr -> CoreExpr -> CoreExpr
- needsCaseBinding :: HasDebugCallStack => Type -> CoreExpr -> Bool
- needsCaseBindingL :: Levity -> CoreExpr -> Bool
- mkAltExpr :: AltCon -> [CoreBndr] -> [Type] -> CoreExpr
- mkDefaultCase :: CoreExpr -> Id -> CoreExpr -> CoreExpr
- mkSingleAltCase :: CoreExpr -> Id -> AltCon -> [Var] -> CoreExpr -> CoreExpr
- findDefault :: [Alt b] -> ([Alt b], Maybe (Expr b))
- addDefault :: [Alt b] -> Maybe (Expr b) -> [Alt b]
- findAlt :: AltCon -> [Alt b] -> Maybe (Alt b)
- isDefaultAlt :: Alt b -> Bool
- mergeAlts :: [Alt a] -> [Alt a] -> [Alt a]
- mergeCaseAlts :: Id -> [CoreAlt] -> Maybe ([CoreBind], [CoreAlt])
- trimConArgs :: AltCon -> [CoreArg] -> [CoreArg]
- filterAlts :: TyCon -> [Type] -> [AltCon] -> [Alt b] -> ([AltCon], [Alt b])
- combineIdenticalAlts :: [AltCon] -> [CoreAlt] -> (Bool, [AltCon], [CoreAlt])
- refineDefaultAlt :: [Unique] -> Mult -> TyCon -> [Type] -> [AltCon] -> [CoreAlt] -> (Bool, [CoreAlt])
- scaleAltsBy :: Mult -> [CoreAlt] -> [CoreAlt]
- exprType :: HasDebugCallStack => CoreExpr -> Type
- coreAltType :: CoreAlt -> Type
- coreAltsType :: [CoreAlt] -> Type
- mkLamType :: HasDebugCallStack => Var -> Type -> Type
- mkLamTypes :: [Var] -> Type -> Type
- mkFunctionType :: HasDebugCallStack => Mult -> Type -> Type -> Type
- exprIsTrivial :: CoreExpr -> Bool
- getIdFromTrivialExpr :: HasDebugCallStack => CoreExpr -> Id
- getIdFromTrivialExpr_maybe :: CoreExpr -> Maybe Id
- trivial_expr_fold :: (Id -> r) -> (Literal -> r) -> r -> r -> CoreExpr -> r
- exprIsDupable :: Platform -> CoreExpr -> Bool
- exprIsCheap :: CoreExpr -> Bool
- exprIsExpandable :: CoreExpr -> Bool
- exprIsCheapX :: CheapAppFun -> CoreExpr -> Bool
- type CheapAppFun = Id -> Arity -> Bool
- exprIsHNF :: CoreExpr -> Bool
- exprOkForSpeculation :: CoreExpr -> Bool
- exprOkToDiscard :: CoreExpr -> Bool
- exprOkForSpecEval :: (Id -> Bool) -> CoreExpr -> Bool
- exprIsWorkFree :: CoreExpr -> Bool
- exprIsConLike :: CoreExpr -> Bool
- isCheapApp :: CheapAppFun
- isExpandableApp :: CheapAppFun
- isSaturatedConApp :: CoreExpr -> Bool
- exprIsTickedString :: CoreExpr -> Bool
- exprIsTickedString_maybe :: CoreExpr -> Maybe ByteString
- exprIsTopLevelBindable :: CoreExpr -> Type -> Bool
- altsAreExhaustive :: [Alt b] -> Bool
- etaExpansionTick :: forall (pass :: TickishPass). Id -> GenTickish pass -> Bool
- cheapEqExpr :: Expr b -> Expr b -> Bool
- cheapEqExpr' :: (CoreTickish -> Bool) -> Expr b -> Expr b -> Bool
- diffBinds :: Bool -> RnEnv2 -> [(Var, CoreExpr)] -> [(Var, CoreExpr)] -> ([SDoc], RnEnv2)
- exprToType :: CoreExpr -> Type
- applyTypeToArgs :: HasDebugCallStack => SDoc -> Type -> [CoreExpr] -> Type
- dataConRepInstPat :: [Unique] -> Mult -> DataCon -> [Type] -> ([TyCoVar], [Id])
- dataConRepFSInstPat :: [FastString] -> [Unique] -> Mult -> DataCon -> [Type] -> ([TyCoVar], [Id])
- isEmptyTy :: Type -> Bool
- normSplitTyConApp_maybe :: FamInstEnvs -> Type -> Maybe (TyCon, [Type], Coercion)
- stripTicksTop :: (CoreTickish -> Bool) -> Expr b -> ([CoreTickish], Expr b)
- stripTicksTopE :: (CoreTickish -> Bool) -> Expr b -> Expr b
- stripTicksTopT :: (CoreTickish -> Bool) -> Expr b -> [CoreTickish]
- stripTicksE :: (CoreTickish -> Bool) -> Expr b -> Expr b
- stripTicksT :: (CoreTickish -> Bool) -> Expr b -> [CoreTickish]
- mkInScopeSetBndrs :: [CoreBind] -> InScopeSet
- extendInScopeSetBind :: InScopeSet -> CoreBind -> InScopeSet
- extendInScopeSetBndrs :: InScopeSet -> [CoreBind] -> InScopeSet
- collectMakeStaticArgs :: CoreExpr -> Maybe (CoreExpr, Type, CoreExpr, CoreExpr)
- isJoinBind :: CoreBind -> Bool
- mkStrictFieldSeqs :: [(Id, StrictnessMark)] -> CoreExpr -> CoreExpr
- shouldStrictifyIdForCbv :: Var -> Bool
- shouldUseCbvForId :: Var -> Bool
- isUnsafeEqualityCase :: CoreExpr -> Id -> [CoreAlt] -> Maybe CoreExpr
- dumpIdInfoOfProgram :: Bool -> (IdInfo -> SDoc) -> CoreProgram -> SDoc

# Constructing expressions

mkCast :: HasDebugCallStack => CoreExpr -> CoercionR -> CoreExpr Source #

Wrap the given expression in the coercion safely, dropping identity coercions and coalescing nested coercions

mkPiMCo :: Var -> MCoercionR -> MCoercionR Source #

mkTick :: CoreTickish -> CoreExpr -> CoreExpr Source #

Wraps the given expression in the source annotation, dropping the annotation if possible.

mkTickNoHNF :: CoreTickish -> CoreExpr -> CoreExpr Source #

tickHNFArgs :: CoreTickish -> CoreExpr -> CoreExpr Source #

bindNonRec :: HasDebugCallStack => Id -> CoreExpr -> CoreExpr -> CoreExpr Source #

`bindNonRec x r b`

produces either:

let x = r in b

or:

case r of x { _DEFAULT_ -> b }

depending on whether we have to use a `case`

or `let`

binding for the expression (see `needsCaseBinding`

).
It's used by the desugarer to avoid building bindings
that give Core Lint a heart attack, although actually
the simplifier deals with them perfectly well. See
also `mkCoreLet`

needsCaseBinding :: HasDebugCallStack => Type -> CoreExpr -> Bool Source #

`needsCaseBinding`

tests whether we have to use a `case`

rather than `let`

binding for this expression as per the invariants of `CoreExpr`

: see
GHC.Core
(needsCaseBinding ty rhs) requires that `ty`

has a well-defined levity, else
`typeLevity ty` will fail; but that should be the case because
`needsCaseBinding`

is only called once typechecking is complete

:: AltCon | Case alternative constructor |

-> [CoreBndr] | Things bound by the pattern match |

-> [Type] | The type arguments to the case alternative |

-> CoreExpr |

This guy constructs the value that the scrutinee must have given that you are in one particular branch of a case

# Taking expressions apart

findAlt :: AltCon -> [Alt b] -> Maybe (Alt b) Source #

Find the case alternative corresponding to a particular constructor: panics if no such constructor exists

isDefaultAlt :: Alt b -> Bool Source #

mergeAlts :: [Alt a] -> [Alt a] -> [Alt a] Source #

Merge alternatives preserving order; alternatives in the first argument shadow ones in the second

trimConArgs :: AltCon -> [CoreArg] -> [CoreArg] Source #

Given:

case (C a b x y) of C b x y -> ...

We want to drop the leading type argument of the scrutinee leaving the arguments to match against the pattern

:: [Unique] | Uniques for constructing new binders |

-> Mult | Multiplicity annotation of the case expression |

-> TyCon | Type constructor of scrutinee's type |

-> [Type] | Type arguments of scrutinee's type |

-> [AltCon] | Constructors that cannot match the DEFAULT (if any) |

-> [CoreAlt] | |

-> (Bool, [CoreAlt]) |

Refine the default alternative to a `DataAlt`

, if there is a unique way to do so.
See Note [Refine DEFAULT case alternatives]

# Properties of expressions

exprType :: HasDebugCallStack => CoreExpr -> Type Source #

Recover the type of a well-typed Core expression. Fails when
applied to the actual `Type`

expression as it cannot
really be said to have a type

coreAltType :: CoreAlt -> Type Source #

Returns the type of the alternatives right hand side

coreAltsType :: [CoreAlt] -> Type Source #

Returns the type of the first alternative, which should be the same as for all alternatives

mkLamType :: HasDebugCallStack => Var -> Type -> Type Source #

Makes a `(->)`

type or an implicit forall type, depending
on whether it is given a type variable or a term variable.
This is used, for example, when producing the type of a lambda.

mkFunctionType :: HasDebugCallStack => Mult -> Type -> Type -> Type Source #

This one works out the FunTyFlag from the argument type See GHC.Types.Var Note [FunTyFlag]

exprIsTrivial :: CoreExpr -> Bool Source #

getIdFromTrivialExpr :: HasDebugCallStack => CoreExpr -> Id Source #

trivial_expr_fold :: (Id -> r) -> (Literal -> r) -> r -> r -> CoreExpr -> r Source #

The worker function for Note [exprIsTrivial] and Note [getIdFromTrivialExpr] This is meant to have the code of both functions in one place and make it easy to derive custom predicates.

(trivial_expr_fold k_id k_triv k_not_triv e)
* returns (k_id x) if `e`

is a variable `x`

(with trivial wrapping)
* returns (k_lit x) if `e`

is a trivial literal `l`

(with trivial wrapping)
* returns k_triv if `e`

is a literal, type, or coercion (with trivial wrapping)
* returns k_not_triv otherwise

where "trivial wrapping" is
* Type application or abstraction
* Ticks other than `tickishIsCode`

* `case e of {}` an empty case

exprIsCheap :: CoreExpr -> Bool Source #

exprIsExpandable :: CoreExpr -> Bool Source #

exprIsCheapX :: CheapAppFun -> CoreExpr -> Bool Source #

exprIsHNF :: CoreExpr -> Bool Source #

exprIsHNF returns true for expressions that are certainly *already*
evaluated to *head* normal form. This is used to decide whether it's ok
to perform case-to-let for lifted expressions, which changes:

case x of x' { _ -> e }

into:

let x' = x in e

and in so doing makes the binding lazy.

So, it does *not* treat variables as evaluated, unless they say they are.
However, it *does* treat partial applications and constructor applications
as values, even if their arguments are non-trivial, provided the argument
type is lifted. For example, both of these are values:

(:) (f x) (map f xs) map (...redex...)

because `seq`

on such things completes immediately.

For unlifted argument types, we have to be careful:

C (f x :: Int#)

Suppose `f x`

diverges; then `C (f x)`

is not a value.
We check for this using needsCaseBinding below

exprOkForSpeculation :: CoreExpr -> Bool Source #

To a first approximation, `exprOkForSpeculation`

returns True of
an expression that is:

- Safe to evaluate even if normal order eval might not evaluate the expression at all, and
- Safe
*not*to evaluate even if normal order would do so

More specifically, this means that: * A: Evaluation of the expression reaches weak-head-normal-form, * B: soon, * C: without causing a write side effect (e.g. writing a mutable variable).

In particular, an expression that may
* throw a synchronous Haskell exception, or
* risk an unchecked runtime exception (e.g. array
out of bounds, divide by zero)
is *not* considered OK-for-speculation, as these violate condition A.

For `exprOkToDiscard`

, condition A is weakened to allow expressions
that might risk an unchecked runtime exception but must otherwise
reach weak-head-normal-form.
(Note that `exprOkForSpeculation`

implies `exprOkToDiscard`

)

But in fact both functions are a bit more conservative than the above, in at least the following ways:

- W1: We do not take advantage of already-evaluated lifted variables.
As a result,
`exprIsHNF`

DOES NOT imply`exprOkForSpeculation`

; if`y`

is a case-binder of lifted type, then`exprIsHNF y`

is`True`

, while`exprOkForSpeculation y`

is`False`

. See Note [exprOkForSpeculation and evaluated variables] for why. - W2: Read-effects on mutable variables are currently also included. See Note [Classifying primop effects] GHC.Builtin.PrimOps.
- W3: Currently,
`exprOkForSpeculation`

always returns`False`

for let-expressions. Lets can be stacked deeply, so we just give up. In any case, the argument of`exprOkForSpeculation`

is usually in a strict context, so any lets will have been floated away.

As an example of the considerations in this test, consider:

let x = case y# +# 1# of { r# -> I# r# } in E

being translated to:

case y# +# 1# of { r# -> let x = I# r# in E }

We can only do this if the `y# +# 1#`

is ok for speculation: it has no
side effects, and can't diverge or raise an exception.

See also Note [Classifying primop effects] in GHC.Builtin.PrimOps and Note [Transformations affected by primop effects].

`exprOkForSpeculation`

is used to define Core's let-can-float
invariant. (See Note [Core let-can-float invariant] in
GHC.Core.) It is therefore frequently called on arguments of
unlifted type, especially via `needsCaseBinding`

. But it is
sometimes called on expressions of lifted type as well. For
example, see Note [Speculative evaluation] in GHC.CoreToStg.Prep.

exprOkToDiscard :: CoreExpr -> Bool Source #

To a first approximation, `exprOkForSpeculation`

returns True of
an expression that is:

- Safe to evaluate even if normal order eval might not evaluate the expression at all, and
- Safe
*not*to evaluate even if normal order would do so

More specifically, this means that: * A: Evaluation of the expression reaches weak-head-normal-form, * B: soon, * C: without causing a write side effect (e.g. writing a mutable variable).

In particular, an expression that may
* throw a synchronous Haskell exception, or
* risk an unchecked runtime exception (e.g. array
out of bounds, divide by zero)
is *not* considered OK-for-speculation, as these violate condition A.

For `exprOkToDiscard`

, condition A is weakened to allow expressions
that might risk an unchecked runtime exception but must otherwise
reach weak-head-normal-form.
(Note that `exprOkForSpeculation`

implies `exprOkToDiscard`

)

But in fact both functions are a bit more conservative than the above, in at least the following ways:

- W1: We do not take advantage of already-evaluated lifted variables.
As a result,
`exprIsHNF`

DOES NOT imply`exprOkForSpeculation`

; if`y`

is a case-binder of lifted type, then`exprIsHNF y`

is`True`

, while`exprOkForSpeculation y`

is`False`

. See Note [exprOkForSpeculation and evaluated variables] for why. - W2: Read-effects on mutable variables are currently also included. See Note [Classifying primop effects] GHC.Builtin.PrimOps.
- W3: Currently,
`exprOkForSpeculation`

always returns`False`

for let-expressions. Lets can be stacked deeply, so we just give up. In any case, the argument of`exprOkForSpeculation`

is usually in a strict context, so any lets will have been floated away.

As an example of the considerations in this test, consider:

let x = case y# +# 1# of { r# -> I# r# } in E

being translated to:

case y# +# 1# of { r# -> let x = I# r# in E }

We can only do this if the `y# +# 1#`

is ok for speculation: it has no
side effects, and can't diverge or raise an exception.

See also Note [Classifying primop effects] in GHC.Builtin.PrimOps and Note [Transformations affected by primop effects].

`exprOkForSpeculation`

is used to define Core's let-can-float
invariant. (See Note [Core let-can-float invariant] in
GHC.Core.) It is therefore frequently called on arguments of
unlifted type, especially via `needsCaseBinding`

. But it is
sometimes called on expressions of lifted type as well. For
example, see Note [Speculative evaluation] in GHC.CoreToStg.Prep.

exprOkForSpecEval :: (Id -> Bool) -> CoreExpr -> Bool Source #

A special version of `exprOkForSpeculation`

used during
Note [Speculative evaluation]. When the predicate arg `fun_ok`

returns False
for `b`

, then `b`

is never considered ok-for-spec.

exprIsWorkFree :: CoreExpr -> Bool Source #

exprIsConLike :: CoreExpr -> Bool Source #

Similar to `exprIsHNF`

but includes CONLIKE functions as well as
data constructors. Conlike arguments are considered interesting by the
inliner.

isSaturatedConApp :: CoreExpr -> Bool Source #

exprIsTickedString :: CoreExpr -> Bool Source #

Check if the expression is zero or more Ticks wrapped around a literal string.

exprIsTickedString_maybe :: CoreExpr -> Maybe ByteString Source #

Extract a literal string from an expression that is zero or more Ticks wrapped around a literal string. Returns Nothing if the expression has a different shape. Used to "look through" Ticks in places that need to handle literal strings.

exprIsTopLevelBindable :: CoreExpr -> Type -> Bool Source #

Can we bind this `CoreExpr`

at the top level?

altsAreExhaustive :: [Alt b] -> Bool Source #

etaExpansionTick :: forall (pass :: TickishPass). Id -> GenTickish pass -> Bool Source #

Should we look past this tick when eta-expanding the given function?

See Note [Ticks and mandatory eta expansion] Takes the function we are applying as argument.

# Equality

cheapEqExpr :: Expr b -> Expr b -> Bool Source #

A cheap equality test which bales out fast!
If it returns `True`

the arguments are definitely equal,
otherwise, they may or may not be equal.

cheapEqExpr' :: (CoreTickish -> Bool) -> Expr b -> Expr b -> Bool Source #

Cheap expression equality test, can ignore ticks by type.

diffBinds :: Bool -> RnEnv2 -> [(Var, CoreExpr)] -> [(Var, CoreExpr)] -> ([SDoc], RnEnv2) Source #

Finds differences between core bindings, see `diffExpr`

.

The main problem here is that while we expect the binds to have the same order in both lists, this is not guaranteed. To do this properly we'd either have to do some sort of unification or check all possible mappings, which would be seriously expensive. So instead we simply match single bindings as far as we can. This leaves us just with mutually recursive and/or mismatching bindings, which we then speculatively match by ordering them. It's by no means perfect, but gets the job done well enough.

Only used in GHC.Core.Lint.lintAnnots

# Manipulating data constructors and types

exprToType :: CoreExpr -> Type Source #

applyTypeToArgs :: HasDebugCallStack => SDoc -> Type -> [CoreExpr] -> Type Source #

Determines the type resulting from applying an expression with given type

dataConRepFSInstPat :: [FastString] -> [Unique] -> Mult -> DataCon -> [Type] -> ([TyCoVar], [Id]) Source #

isEmptyTy :: Type -> Bool Source #

True if the type has no non-bottom elements, e.g. when it is an empty datatype, or a GADT with non-satisfiable type parameters, e.g. Int :~: Bool. See Note [Bottoming expressions]

See Note [No alternatives lint check] for another use of this function.

normSplitTyConApp_maybe :: FamInstEnvs -> Type -> Maybe (TyCon, [Type], Coercion) Source #

If `normSplitTyConApp_maybe _ ty = Just (tc, tys, co)`

then `ty |> co = tc tys`

. It's `splitTyConApp_maybe`

, but looks through
coercions via `topNormaliseType_maybe`

. Hence the "norm" prefix.

# Working with ticks

stripTicksTop :: (CoreTickish -> Bool) -> Expr b -> ([CoreTickish], Expr b) Source #

Strip ticks satisfying a predicate from top of an expression

stripTicksTopE :: (CoreTickish -> Bool) -> Expr b -> Expr b Source #

Strip ticks satisfying a predicate from top of an expression, returning the remaining expression

stripTicksTopT :: (CoreTickish -> Bool) -> Expr b -> [CoreTickish] Source #

Strip ticks satisfying a predicate from top of an expression, returning the ticks

stripTicksE :: (CoreTickish -> Bool) -> Expr b -> Expr b Source #

Completely strip ticks satisfying a predicate from an expression. Note this is O(n) in the size of the expression!

stripTicksT :: (CoreTickish -> Bool) -> Expr b -> [CoreTickish] Source #

# InScopeSet things which work over CoreBinds

mkInScopeSetBndrs :: [CoreBind] -> InScopeSet Source #

extendInScopeSetBind :: InScopeSet -> CoreBind -> InScopeSet Source #

extendInScopeSetBndrs :: InScopeSet -> [CoreBind] -> InScopeSet Source #

# StaticPtr

collectMakeStaticArgs :: CoreExpr -> Maybe (CoreExpr, Type, CoreExpr, CoreExpr) Source #

`collectMakeStaticArgs (makeStatic t srcLoc e)`

yields
`Just (makeStatic, t, srcLoc, e)`

.

Returns `Nothing`

for every other expression.

# Join points

isJoinBind :: CoreBind -> Bool Source #

Does this binding bind a join point (or a recursive group of join points)?

# Tag inference

mkStrictFieldSeqs :: [(Id, StrictnessMark)] -> CoreExpr -> CoreExpr Source #

shouldStrictifyIdForCbv :: Var -> Bool Source #

Do we expect there to be any benefit if we make this var strict in order for it to get treated as as cbv argument? See Note [Which Ids should be strictified] See Note [CBV Function Ids] for more background.

shouldUseCbvForId :: Var -> Bool Source #

# unsafeEqualityProof

# Dumping stuff

dumpIdInfoOfProgram :: Bool -> (IdInfo -> SDoc) -> CoreProgram -> SDoc Source #