summaryrefslogtreecommitdiff
path: root/compiler/GHC/Types/Id/Make.hs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/GHC/Types/Id/Make.hs')
-rw-r--r--compiler/GHC/Types/Id/Make.hs40
1 files changed, 29 insertions, 11 deletions
diff --git a/compiler/GHC/Types/Id/Make.hs b/compiler/GHC/Types/Id/Make.hs
index 9aa91e3017..dd5657f419 100644
--- a/compiler/GHC/Types/Id/Make.hs
+++ b/compiler/GHC/Types/Id/Make.hs
@@ -1657,18 +1657,36 @@ Implementing 'lazy' is a bit tricky:
Note [noinlineId magic]
~~~~~~~~~~~~~~~~~~~~~~~
-noinline :: forall a. a -> a
-
'noinline' is used to make sure that a function f is never inlined,
-e.g., as in 'noinline f x'. Ordinarily, the identity function with NOINLINE
-could be used to achieve this effect; however, this has the unfortunate
-result of leaving a (useless) call to noinline at runtime. So we have
-a little bit of magic to optimize away 'noinline' after we are done
-running the simplifier.
-
-'noinline' needs to be wired-in because it gets inserted automatically
-when we serialize an expression to the interface format. See
-Note [Inlining and hs-boot files] in GHC.CoreToIface
+e.g., as in 'noinline f x'. We won't inline f because we never inline
+lone variables (see Note [Lone variables] in GHC.Core.Unfold
+
+You might think that we could implement noinline like this:
+ {-# NOINLINE #-}
+ noinline :: forall a. a -> a
+ noinline x = x
+
+But actually we give 'noinline' a wired-in name for three distinct reasons:
+
+1. We don't want to leave a (useless) call to noinline in the final program,
+ to be executed at runtime. So we have a little bit of magic to
+ optimize away 'noinline' after we are done running the simplifier.
+ This is done in GHC.CoreToStg.Prep.cpeApp.
+
+2. 'noinline' sometimes gets inserted automatically when we serialize an
+ expression to the interface format, in GHC.CoreToIface.toIfaceVar.
+ See Note [Inlining and hs-boot files] in GHC.CoreToIface
+
+3. Given foo :: Eq a => [a] -> Bool, the expression
+ noinline foo x xs
+ where x::Int, will naturally desugar to
+ noinline @Int (foo @Int dEqInt) x xs
+ But now it's entirely possible htat (foo @Int dEqInt) will inline foo,
+ since 'foo' is no longer a lone variable -- see #18995
+
+ Solution: in the desugarer, rewrite
+ noinline (f x y) ==> noinline f x y
+ This is done in GHC.HsToCore.Utils.mkCoreAppDs.
Note that noinline as currently implemented can hide some simplifications since
it hides strictness from the demand analyser. Specifically, the demand analyser