diff options
| author | Simon Peyton Jones <simonpj@microsoft.com> | 2014-03-06 11:31:47 +0000 |
|---|---|---|
| committer | Simon Peyton Jones <simonpj@microsoft.com> | 2014-03-06 11:59:15 +0000 |
| commit | 4b355cd21a190e3d2c2d3a830ba2337d1c442dfe (patch) | |
| tree | f25059c9ee4faaabe79a41e68020e896ec3764c2 /compiler/stranal/WwLib.lhs | |
| parent | eeb1400a0ca9ba7d1831f8ec0b221f632dec9f68 (diff) | |
| download | haskell-4b355cd21a190e3d2c2d3a830ba2337d1c442dfe.tar.gz | |
Make the demand on a binder compatible with type (fixes Trac #8569)
Because of GADTs and casts we were getting binders whose
demand annotation was more deeply nested than made sense
for its type.
See Note [Trimming a demand to a type], in Demand.lhs,
which I reproduce here:
Note [Trimming a demand to a type]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Consider this:
f :: a -> Bool
f x = case ... of
A g1 -> case (x |> g1) of (p,q) -> ...
B -> error "urk"
where A,B are the constructors of a GADT. We'll get a U(U,U) demand
on x from the A branch, but that's a stupid demand for x itself, which
has type 'a'. Indeed we get ASSERTs going off (notably in
splitUseProdDmd, Trac #8569).
Bottom line: we really don't want to have a binder whose demand is more
deeply-nested than its type. There are various ways to tackle this.
When processing (x |> g1), we could "trim" the incoming demand U(U,U)
to match x's type. But I'm currently doing so just at the moment when
we pin a demand on a binder, in DmdAnal.findBndrDmd.
Diffstat (limited to 'compiler/stranal/WwLib.lhs')
| -rw-r--r-- | compiler/stranal/WwLib.lhs | 31 |
1 files changed, 30 insertions, 1 deletions
diff --git a/compiler/stranal/WwLib.lhs b/compiler/stranal/WwLib.lhs index f88c9ad54f..68292839ed 100644 --- a/compiler/stranal/WwLib.lhs +++ b/compiler/stranal/WwLib.lhs @@ -4,7 +4,9 @@ \section[WwLib]{A library for the ``worker\/wrapper'' back-end to the strictness analyser} \begin{code} -module WwLib ( mkWwBodies, mkWWstr, mkWorkerArgs, deepSplitProductType_maybe ) where +module WwLib ( mkWwBodies, mkWWstr, mkWorkerArgs + , deepSplitProductType_maybe, findTypeShape + ) where #include "HsVersions.h" @@ -506,6 +508,12 @@ match the number of constructor arguments; this happened in Trac #8037. If so, the worker/wrapper split doesn't work right and we get a Core Lint bug. The fix here is simply to decline to do w/w if that happens. +%************************************************************************ +%* * + Type scrutiny that is specfic to demand analysis +%* * +%************************************************************************ + \begin{code} deepSplitProductType_maybe :: FamInstEnvs -> Type -> Maybe (DataCon, [Type], [Type], Coercion) -- If deepSplitProductType_maybe ty = Just (dc, tys, arg_tys, co) @@ -534,6 +542,27 @@ deepSplitCprType_maybe fam_envs con_tag ty , let con = cons !! (con_tag - fIRST_TAG) = Just (con, tc_args, dataConInstArgTys con tc_args, co) deepSplitCprType_maybe _ _ _ = Nothing + +findTypeShape :: FamInstEnvs -> Type -> TypeShape +-- Uncover the arrow and product shape of a type +-- The data type TypeShape is defined in Demand +-- See Note [Trimming a demand to a type] in Demand +findTypeShape fam_envs ty + | Just (_, ty') <- splitForAllTy_maybe ty + = findTypeShape fam_envs ty' + + | Just (tc, tc_args) <- splitTyConApp_maybe ty + , Just con <- isDataProductTyCon_maybe tc + = TsProd (map (findTypeShape fam_envs) $ dataConInstArgTys con tc_args) + + | Just (_, res) <- splitFunTy_maybe ty + = TsFun (findTypeShape fam_envs res) + + | Just (_, ty') <- topNormaliseType_maybe fam_envs ty + = findTypeShape fam_envs ty' + + | otherwise + = TsUnk \end{code} |
