ghc-9.6.0.20230128: The GHC API
Safe HaskellSafe-Inferred
LanguageHaskell2010

GHC.Core.Utils

Description

Commonly useful utilities for manipulating the Core language

Synopsis

Constructing expressions

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

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

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

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

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 :: Type -> CoreExpr -> Bool Source #

Tests whether we have to use a case rather than let binding for this expression as per the invariants of CoreExpr: see GHC.Core

mkAltExpr Source #

Arguments

:: 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

findDefault :: [Alt b] -> ([Alt b], Maybe (Expr b)) Source #

Extract the default case alternative

addDefault :: [Alt b] -> Maybe (Expr b) -> [Alt b] Source #

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

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

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

filterAlts Source #

Arguments

:: TyCon

Type constructor of scrutinee's type (used to prune possibilities)

-> [Type]

And its type arguments

-> [AltCon]

imposs_cons: constructors known to be impossible due to the form of the scrutinee

-> [Alt b]

Alternatives

-> ([AltCon], [Alt b]) 

refineDefaultAlt Source #

Arguments

:: [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])

True, if a default alt was replaced with a DataAlt

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. Always uses Inferred binders.

mkLamTypes :: [Var] -> Type -> Type Source #

mkLamType for multiple type or value arguments

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

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

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 change:

case x of _ -> e

into:

e

and to decide whether it's safe to discard a seq.

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 #

exprOkForSpeculation returns True of an expression that is:

  • Safe to evaluate even if normal order eval might not evaluate the expression at all, or
  • Safe not to evaluate even if normal order would do so

It is usually called on arguments of unlifted type, but not always In particular, Simplify.rebuildCase calls it on lifted types when a 'case' is a plain seq. See the example in Note [exprOkForSpeculation: case expressions] below

Precisely, it returns True iff: a) The expression guarantees to terminate, b) soon, c) without causing a write side effect (e.g. writing a mutable variable) d) without throwing a Haskell exception e) without risking an unchecked runtime exception (array out of bounds, divide by zero)

For exprOkForSideEffects the list is the same, but omitting (e).

Note that exprIsHNF implies exprOkForSpeculation exprOkForSpeculation implies exprOkForSideEffects

See Note [PrimOp can_fail and has_side_effects] in GHC.Builtin.PrimOps and Note [Transformations affected by can_fail and has_side_effects]

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.

exprOkForSideEffects :: CoreExpr -> Bool Source #

exprOkForSpeculation returns True of an expression that is:

  • Safe to evaluate even if normal order eval might not evaluate the expression at all, or
  • Safe not to evaluate even if normal order would do so

It is usually called on arguments of unlifted type, but not always In particular, Simplify.rebuildCase calls it on lifted types when a 'case' is a plain seq. See the example in Note [exprOkForSpeculation: case expressions] below

Precisely, it returns True iff: a) The expression guarantees to terminate, b) soon, c) without causing a write side effect (e.g. writing a mutable variable) d) without throwing a Haskell exception e) without risking an unchecked runtime exception (array out of bounds, divide by zero)

For exprOkForSideEffects the list is the same, but omitting (e).

Note that exprIsHNF implies exprOkForSpeculation exprOkForSpeculation implies exprOkForSideEffects

See Note [PrimOp can_fail and has_side_effects] in GHC.Builtin.PrimOps and Note [Transformations affected by can_fail and has_side_effects]

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.

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.

exprIsConLike :: CoreExpr -> Bool Source #

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

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?

etaExpansionTick :: 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 #

If the expression is a Type, converts. Otherwise, panics. NB: This does not convert Coercion to CoercionTy.

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

Determines the type resulting from applying an expression with given type

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!

InScopeSet things which work over CoreBinds

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

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.

unsafeEqualityProof

Dumping stuff