summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--compiler/GHC/Core/Unify.hs2
-rw-r--r--compiler/GHC/Utils/Monad.hs19
2 files changed, 21 insertions, 0 deletions
diff --git a/compiler/GHC/Core/Unify.hs b/compiler/GHC/Core/Unify.hs
index fdf4d05068..bd54ecee39 100644
--- a/compiler/GHC/Core/Unify.hs
+++ b/compiler/GHC/Core/Unify.hs
@@ -1393,6 +1393,8 @@ instance Applicative UM where
(<*>) = ap
instance Monad UM where
+ {-# INLINE (>>=) #-}
+ -- See Note [INLINE pragmas and (>>)] in GHC.Utils.Monad
m >>= k = UM (\state ->
do { (state', v) <- unUM m state
; unUM (k v) state' })
diff --git a/compiler/GHC/Utils/Monad.hs b/compiler/GHC/Utils/Monad.hs
index a65947e59e..056651bdde 100644
--- a/compiler/GHC/Utils/Monad.hs
+++ b/compiler/GHC/Utils/Monad.hs
@@ -355,6 +355,25 @@ function might be required. For example in FCode we use:
where
FCode m = FCode' $ oneShot (\cgInfoDown -> oneShot (\state ->m cgInfoDown state))
+INLINE pragmas and (>>)
+~~~~~~~~~~~~~~~~~~~~~~~
+A nasty gotcha is described in #20008. In brief, be careful if you get (>>) via
+its default method:
+
+ instance Applicative M where
+ pure a = MkM (\s -> (s, a))
+ (<*>) = ap
+
+ instance Monad UM where
+ {-# INLINE (>>=) #-}
+ m >>= k = MkM (\s -> blah)
+
+Here we define (>>), via its default method, in terms of (>>=). If you do this,
+be sure to put an INLINE pragma on (>>=), as above. That tells it to inline
+(>>=) in the RHS of (>>), even when it is applied to only two arguments, which
+in turn conveys the one-shot info from (>>=) to (>>). Lacking the INLINE, GHC
+may eta-expand (>>), and with a non-one-shot lambda. #20008 has more discussion.
+
Derived instances
~~~~~~~~~~~~~~~~~
One caveat of both approaches is that derived instances don't use the smart