+\begin{code}
+completeTrivialBinding old_bndr new_bndr black_listed loop_breaker new_rhs thing_inside
+ -- We're looking at a binding with a trivial RHS, so
+ -- perhaps we can discard it altogether!
+ --
+ -- NB: a loop breaker never has postInlineUnconditionally True
+ -- and non-loop-breakers only have *forward* references
+ -- Hence, it's safe to discard the binding
+ --
+ -- NB: You might think that postInlineUnconditionally is an optimisation,
+ -- but if we have
+ -- let x = f Bool in (x, y)
+ -- then because of the constructor, x will not be *inlined* in the pair,
+ -- so the trivial binding will stay. But in this postInlineUnconditionally
+ -- gag we use the *substitution* to substitute (f Bool) for x, and that *will*
+ -- happen.
+
+ -- NOTE: This isn't our last opportunity to inline.
+ -- We're at the binding site right now, and
+ -- we'll get another opportunity when we get to the ocurrence(s)
+
+ -- Note that we do this unconditional inlining only for trival RHSs.
+ -- Don't inline even WHNFs inside lambdas; doing so may
+ -- simply increase allocation when the function is called
+ -- This isn't the last chance; see NOTE above.
+ --
+ -- NB: Even inline pragmas (e.g. IMustBeINLINEd) are ignored here
+ -- Why? Because we don't even want to inline them into the
+ -- RHS of constructor arguments. See NOTE above
+ --
+ -- NB: Even NOINLINEis ignored here: if the rhs is trivial
+ -- it's best to inline it anyway. We often get a=E; b=a
+ -- from desugaring, with both a and b marked NOINLINE.
+
+ | not keep_binding -- Can discard binding, inlining everywhere
+ = extendSubst old_bndr (DoneEx new_rhs) $
+ tick (PostInlineUnconditionally old_bndr) `thenSmpl_`
+ thing_inside
+
+ | otherwise -- We must keep the binding, but we may still inline
+ = getSubst `thenSmpl` \ subst ->
+ let
+ new_bndr_info = substIdInfo subst (idInfo old_bndr) (idInfo new_bndr)
+ final_id = new_bndr `setIdInfo` new_bndr_info
+ in
+ addLetBind (NonRec final_id new_rhs) $
+ if dont_inline then
+ modifyInScope new_bndr final_id thing_inside
+ else
+ extendSubst old_bndr (DoneEx new_rhs) thing_inside
+ where
+ dont_inline = black_listed || loop_breaker
+ keep_binding = dont_inline || isExportedId old_bndr
+\end{code}
+
+