summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon Peyton Jones <simonpj@microsoft.com>2022-06-29 16:43:36 +0100
committerZubin <zubin.duggal@gmail.com>2022-07-12 13:26:52 +0000
commit6e8d90560b4a9269c56f7c1ee4d29d1077680f7b (patch)
tree1de4f2a15e6de26e7e0a65f350d88cedb370df82
parent460505345e500eb902da9737c75c077d5fc5ef66 (diff)
downloadhaskell-6e8d90560b4a9269c56f7c1ee4d29d1077680f7b.tar.gz
Edit Note [idArity varies independently of dmdTypeDepth]
...and refer to it in GHC.Core.Lint.lintLetBind. Fixes #21452
-rw-r--r--compiler/GHC/Core/Lint.hs15
-rw-r--r--compiler/GHC/Core/Opt/DmdAnal.hs32
-rw-r--r--compiler/GHC/Core/Opt/Simplify.hs6
-rw-r--r--compiler/GHC/Types/Id/Info.hs5
4 files changed, 34 insertions, 24 deletions
diff --git a/compiler/GHC/Core/Lint.hs b/compiler/GHC/Core/Lint.hs
index 7486086406..00636ec444 100644
--- a/compiler/GHC/Core/Lint.hs
+++ b/compiler/GHC/Core/Lint.hs
@@ -640,7 +640,8 @@ lintLetBind top_lvl rec_flag binder rhs rhs_ty
ppr (typeArity (idType binder)) <> colon <+>
ppr binder)
- -- See Note [Check arity on bottoming functions]
+ -- See Note [idArity varies independently of dmdTypeDepth]
+ -- in GHC.Core.Opt.DmdAnal
; case splitDmdSig (idDmdSig binder) of
(demands, result_info) | isDeadEndDiv result_info ->
checkL (demands `lengthAtLeast` idArity binder)
@@ -648,6 +649,7 @@ lintLetBind top_lvl rec_flag binder rhs rhs_ty
text "exceeds arity imposed by the strictness signature" <+>
ppr (idDmdSig binder) <> colon <+>
ppr binder)
+
_ -> return ()
; addLoc (RuleOf binder) $ mapM_ (lintCoreRule binder binder_ty) (idCoreRules binder)
@@ -724,15 +726,8 @@ lintIdUnfolding _ _ _
= return () -- Do not Lint unstable unfoldings, because that leads
-- to exponential behaviour; c.f. GHC.Core.FVs.idUnfoldingVars
-{-
-Note [Check arity on bottoming functions]
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-If a function has a strictness signature like [S]b, it claims to
-return bottom when applied to one argument. So its arity should not
-be greater than 1! We check this claim in Lint.
-
-Note [Checking for INLINE loop breakers]
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+{- Note [Checking for INLINE loop breakers]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
It's very suspicious if a strong loop breaker is marked INLINE.
However, the desugarer generates instance methods with INLINE pragmas
diff --git a/compiler/GHC/Core/Opt/DmdAnal.hs b/compiler/GHC/Core/Opt/DmdAnal.hs
index 59d18fefaf..d41b97ac87 100644
--- a/compiler/GHC/Core/Opt/DmdAnal.hs
+++ b/compiler/GHC/Core/Opt/DmdAnal.hs
@@ -1177,18 +1177,27 @@ complexity.
Note [idArity varies independently of dmdTypeDepth]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+In general, an Id `f` has two independently varying attributes:
+
+* f's idArity, and
+* the dmdTypeDepth of f's demand signature
+
+For example, if f's demand signature is <L><L>, f's arity could be
+greater than, or less than 2. Why? Because both are conservative
+approximations:
+
+* Arity n means "does no work until applied to at least n args"
+ (e.g. (f x1..xm) is cheap to bring to HNF for m<n)
+
+* Dmd sig with n args means "here is how to transform the incoming demand
+ when applied to n args". This is /semantic/ property, unrelated to
+ arity. See GHC.Types.Demand Note [Understanding DmdType and DmdSig]
+
We used to check in GHC.Core.Lint that dmdTypeDepth <= idArity for a let-bound
identifier. But that means we would have to zap demand signatures every time we
-reset or decrease arity. That's an unnecessary dependency, because
-
- * The demand signature captures a semantic property that is independent of
- what the binding's current arity is
- * idArity is analysis information itself, thus volatile
- * We already *have* dmdTypeDepth, wo why not just use it to encode the
- threshold for when to unleash the signature
- (cf. Note [Understanding DmdType and DmdSig] in GHC.Types.Demand)
+reset or decrease arity.
-Consider the following expression, for example:
+For example, consider the following expression, for example:
(let go x y = `x` seq ... in go) |> co
@@ -1201,6 +1210,11 @@ coercion into the binding, leading to an arity decrease:
With the CoreLint check, we would have to zap `go`'s perfectly viable strictness
signature.
+However, in the case of a /bottoming/ signature, f : <L><L>b, we /can/
+say that f's arity is no greater than 2, because it'd be false to say
+that f does no work when applied to 3 args. Lint checks this constraint,
+in `GHC.Core.Lint.lintLetBind`.
+
Note [Demand analysis for trivial right-hand sides]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Consider
diff --git a/compiler/GHC/Core/Opt/Simplify.hs b/compiler/GHC/Core/Opt/Simplify.hs
index d26fd28de2..0f842be2d3 100644
--- a/compiler/GHC/Core/Opt/Simplify.hs
+++ b/compiler/GHC/Core/Opt/Simplify.hs
@@ -1025,9 +1025,9 @@ to eta-expand to
in ...(f a b c)...
But now f's strictness signature has too short an arity; see
-GHC.Core.Lint Note [Check arity on bottoming functions].
-Fortuitously, the same strictness-signature-fixup code gives the
-function a new strictness signature with the right number of
+GHC.Core.Opt.DmdAnal Note [idArity varies independently of dmdTypeDepth].
+Fortuitously, the same strictness-signature-fixup code
+gives the function a new strictness signature with the right number of
arguments. Example in stranal/should_compile/EtaExpansion.
Note [Setting the demand info]
diff --git a/compiler/GHC/Types/Id/Info.hs b/compiler/GHC/Types/Id/Info.hs
index 5834fa8b06..a35845f612 100644
--- a/compiler/GHC/Types/Id/Info.hs
+++ b/compiler/GHC/Types/Id/Info.hs
@@ -353,8 +353,9 @@ data IdInfo
occInfo :: OccInfo,
-- ^ How the 'Id' occurs in the program
dmdSigInfo :: DmdSig,
- -- ^ A strictness signature. Digests how a function uses its arguments
- -- if applied to at least 'arityInfo' arguments.
+ -- ^ A strictness signature. Describes how a function uses its arguments
+ -- See Note [idArity varies independently of dmdTypeDepth]
+ -- in GHC.Core.Opt.DmdAnal
cprSigInfo :: CprSig,
-- ^ Information on whether the function will ultimately return a
-- freshly allocated constructor.