2 % (c) The AQUA Project, Glasgow University, 1993-1998
4 \section[SimplMonad]{The simplifier Monad}
8 -- The above warning supression flag is a temporary kludge.
9 -- While working on this module you are encouraged to remove it and fix
10 -- any warnings in the module. See
11 -- http://hackage.haskell.org/trac/ghc/wiki/Commentary/CodingStyle#Warnings
15 InId, InBind, InExpr, InAlt, InArg, InType, InBndr,
16 OutId, OutTyVar, OutBind, OutExpr, OutAlt, OutArg, OutType, OutBndr,
17 InCoercion, OutCoercion,
19 -- The simplifier mode
23 SwitchChecker, SwitchResult(..), getSwitchChecker, getSimplIntSwitch,
24 isAmongSimpl, intSwitchSet, switchIsOn,
26 setEnclosingCC, getEnclosingCC,
29 SimplEnv(..), pprSimplEnv, -- Temp not abstract
30 mkSimplEnv, extendIdSubst, SimplEnv.extendTvSubst,
31 zapSubstEnv, setSubstEnv,
32 getInScope, setInScope, setInScopeSet, modifyInScope, addNewInScopeIds,
35 SimplSR(..), mkContEx, substId, lookupRecBndr,
37 simplNonRecBndr, simplRecBndrs, simplLamBndr, simplLamBndrs,
38 simplBinder, simplBinders, addBndrRules,
39 substExpr, substWorker, substTy,
42 Floats, emptyFloats, isEmptyFloats, addNonRec, addFloats, extendFloats,
43 wrapFloats, floatBinds, setFloats, zapFloats, addRecFloats,
44 doFloatFromRhs, getFloats
47 #include "HsVersions.h"
60 import qualified CoreSubst ( Subst, mkSubst, substExpr, substSpec, substWorker )
61 import qualified Type ( substTy, substTyVarBndr )
62 import Type hiding ( substTy, substTyVarBndr )
72 %************************************************************************
74 \subsection[Simplify-types]{Type declarations}
76 %************************************************************************
79 type InBndr = CoreBndr
80 type InId = Id -- Not yet cloned
81 type InType = Type -- Ditto
82 type InBind = CoreBind
83 type InExpr = CoreExpr
86 type InCoercion = Coercion
88 type OutBndr = CoreBndr
89 type OutId = Id -- Cloned
90 type OutTyVar = TyVar -- Cloned
91 type OutType = Type -- Cloned
92 type OutCoercion = Coercion
93 type OutBind = CoreBind
94 type OutExpr = CoreExpr
99 %************************************************************************
101 \subsubsection{The @SimplEnv@ type}
103 %************************************************************************
109 seMode :: SimplifierMode,
110 seChkr :: SwitchChecker,
111 seCC :: CostCentreStack, -- The enclosing CCS (when profiling)
113 -- The current set of in-scope variables
114 -- They are all OutVars, and all bound in this module
115 seInScope :: InScopeSet, -- OutVars only
116 -- Includes all variables bound by seFloats
118 -- See Note [Simplifier floats]
120 -- The current substitution
121 seTvSubst :: TvSubstEnv, -- InTyVar |--> OutType
122 seIdSubst :: SimplIdSubst -- InId |--> OutExpr
126 pprSimplEnv :: SimplEnv -> SDoc
127 -- Used for debugging; selective
129 = vcat [ptext SLIT("TvSubst:") <+> ppr (seTvSubst env),
130 ptext SLIT("IdSubst:") <+> ppr (seIdSubst env) ]
132 type SimplIdSubst = IdEnv SimplSR -- IdId |--> OutExpr
133 -- See Note [Extending the Subst] in CoreSubst
136 = DoneEx OutExpr -- Completed term
137 | DoneId OutId -- Completed term variable
138 | ContEx TvSubstEnv -- A suspended substitution
142 instance Outputable SimplSR where
143 ppr (DoneEx e) = ptext SLIT("DoneEx") <+> ppr e
144 ppr (DoneId v) = ptext SLIT("DoneId") <+> ppr v
145 ppr (ContEx tv id e) = vcat [ptext SLIT("ContEx") <+> ppr e {-,
146 ppr (filter_env tv), ppr (filter_env id) -}]
148 -- fvs = exprFreeVars e
149 -- filter_env env = filterVarEnv_Directly keep env
150 -- keep uniq _ = uniq `elemUFM_Directly` fvs
155 The in-scope part of Subst includes *all* in-scope TyVars and Ids
156 The elements of the set may have better IdInfo than the
157 occurrences of in-scope Ids, and (more important) they will
158 have a correctly-substituted type. So we use a lookup in this
159 set to replace occurrences
161 The Ids in the InScopeSet are replete with their Rules,
162 and as we gather info about the unfolding of an Id, we replace
163 it in the in-scope set.
165 The in-scope set is actually a mapping OutVar -> OutVar, and
166 in case expressions we sometimes bind
169 The substitution is *apply-once* only, because InIds and OutIds can overlap.
170 For example, we generally omit mappings
172 from the substitution, when we decide not to clone a77, but it's quite
173 legitimate to put the mapping in the substitution anyway.
175 Furthermore, consider
176 let x = case k of I# x77 -> ... in
177 let y = case k of I# x77 -> ... in ...
178 and suppose the body is strict in both x and y. Then the simplifier
179 will pull the first (case k) to the top; so the second (case k) will
180 cancel out, mapping x77 to, well, x77! But one is an in-Id and the
183 Of course, the substitution *must* applied! Things in its domain
184 simply aren't necessarily bound in the result.
186 * substId adds a binding (DoneId new_id) to the substitution if
187 the Id's unique has changed
190 Note, though that the substitution isn't necessarily extended
191 if the type changes. Why not? Because of the next point:
193 * We *always, always* finish by looking up in the in-scope set
194 any variable that doesn't get a DoneEx or DoneVar hit in the substitution.
195 Reason: so that we never finish up with a "old" Id in the result.
196 An old Id might point to an old unfolding and so on... which gives a space leak.
198 [The DoneEx and DoneVar hits map to "new" stuff.]
200 * It follows that substExpr must not do a no-op if the substitution is empty.
201 substType is free to do so, however.
203 * When we come to a let-binding (say) we generate new IdInfo, including an
204 unfolding, attach it to the binder, and add this newly adorned binder to
205 the in-scope set. So all subsequent occurrences of the binder will get mapped
206 to the full-adorned binder, which is also the one put in the binding site.
208 * The in-scope "set" usually maps x->x; we use it simply for its domain.
209 But sometimes we have two in-scope Ids that are synomyms, and should
210 map to the same target: x->x, y->x. Notably:
212 That's why the "set" is actually a VarEnv Var
216 mkSimplEnv :: SimplifierMode -> SwitchChecker -> SimplEnv
217 mkSimplEnv mode switches
218 = SimplEnv { seChkr = switches, seCC = subsumedCCS,
219 seMode = mode, seInScope = emptyInScopeSet,
220 seFloats = emptyFloats,
221 seTvSubst = emptyVarEnv, seIdSubst = emptyVarEnv }
222 -- The top level "enclosing CC" is "SUBSUMED".
224 ---------------------
225 getSwitchChecker :: SimplEnv -> SwitchChecker
226 getSwitchChecker env = seChkr env
228 ---------------------
229 getMode :: SimplEnv -> SimplifierMode
230 getMode env = seMode env
232 setMode :: SimplifierMode -> SimplEnv -> SimplEnv
233 setMode mode env = env { seMode = mode }
235 ---------------------
236 getEnclosingCC :: SimplEnv -> CostCentreStack
237 getEnclosingCC env = seCC env
239 setEnclosingCC :: SimplEnv -> CostCentreStack -> SimplEnv
240 setEnclosingCC env cc = env {seCC = cc}
242 ---------------------
243 extendIdSubst :: SimplEnv -> Id -> SimplSR -> SimplEnv
244 extendIdSubst env@(SimplEnv {seIdSubst = subst}) var res
245 = env {seIdSubst = extendVarEnv subst var res}
247 extendTvSubst :: SimplEnv -> TyVar -> Type -> SimplEnv
248 extendTvSubst env@(SimplEnv {seTvSubst = subst}) var res
249 = env {seTvSubst = extendVarEnv subst var res}
251 ---------------------
252 getInScope :: SimplEnv -> InScopeSet
253 getInScope env = seInScope env
255 setInScopeSet :: SimplEnv -> InScopeSet -> SimplEnv
256 setInScopeSet env in_scope = env {seInScope = in_scope}
258 setInScope :: SimplEnv -> SimplEnv -> SimplEnv
259 -- Set the in-scope set, and *zap* the floats
260 setInScope env env_with_scope
261 = env { seInScope = seInScope env_with_scope,
262 seFloats = emptyFloats }
264 setFloats :: SimplEnv -> SimplEnv -> SimplEnv
265 -- Set the in-scope set *and* the floats
266 setFloats env env_with_floats
267 = env { seInScope = seInScope env_with_floats,
268 seFloats = seFloats env_with_floats }
270 addNewInScopeIds :: SimplEnv -> [CoreBndr] -> SimplEnv
271 -- The new Ids are guaranteed to be freshly allocated
272 addNewInScopeIds env@(SimplEnv { seInScope = in_scope, seIdSubst = id_subst }) vs
273 = env { seInScope = in_scope `extendInScopeSetList` vs,
274 seIdSubst = id_subst `delVarEnvList` vs }
275 -- Why delete? Consider
276 -- let x = a*b in (x, \x -> x+3)
277 -- We add [x |-> a*b] to the substitution, but we must
278 -- *delete* it from the substitution when going inside
281 modifyInScope :: SimplEnv -> CoreBndr -> CoreBndr -> SimplEnv
282 modifyInScope env@(SimplEnv {seInScope = in_scope}) v v'
283 = env {seInScope = modifyInScopeSet in_scope v v'}
285 ---------------------
286 zapSubstEnv :: SimplEnv -> SimplEnv
287 zapSubstEnv env = env {seTvSubst = emptyVarEnv, seIdSubst = emptyVarEnv}
289 setSubstEnv :: SimplEnv -> TvSubstEnv -> SimplIdSubst -> SimplEnv
290 setSubstEnv env tvs ids = env { seTvSubst = tvs, seIdSubst = ids }
292 mkContEx :: SimplEnv -> InExpr -> SimplSR
293 mkContEx (SimplEnv { seTvSubst = tvs, seIdSubst = ids }) e = ContEx tvs ids e
295 isEmptySimplSubst :: SimplEnv -> Bool
296 isEmptySimplSubst (SimplEnv { seTvSubst = tvs, seIdSubst = ids })
297 = isEmptyVarEnv tvs && isEmptyVarEnv ids
302 %************************************************************************
306 %************************************************************************
308 Note [Simplifier floats]
309 ~~~~~~~~~~~~~~~~~~~~~~~~~
310 The Floats is a bunch of bindings, classified by a FloatFlag.
312 NonRec x (y:ys) FltLifted
313 Rec [(x,rhs)] FltLifted
315 NonRec x# (y +# 3) FltOkSpec -- Unboxed, but ok-for-spec'n
317 NonRec x# (a /# b) FltCareful
318 NonRec x* (f y) FltCareful -- Strict binding; might fail or diverge
319 NonRec x# (f y) FltCareful -- Unboxed binding: might fail or diverge
320 -- (where f :: Int -> Int#)
323 data Floats = Floats (OrdList OutBind) FloatFlag
324 -- See Note [Simplifier floats]
327 = FltLifted -- All bindings are lifted and lazy
328 -- Hence ok to float to top level, or recursive
330 | FltOkSpec -- All bindings are FltLifted *or*
331 -- strict (perhaps because unlifted,
332 -- perhaps because of a strict binder),
333 -- *and* ok-for-speculation
334 -- Hence ok to float out of the RHS
335 -- of a lazy non-recursive let binding
336 -- (but not to top level, or into a rec group)
338 | FltCareful -- At least one binding is strict (or unlifted)
339 -- and not guaranteed cheap
340 -- Do not float these bindings out of a lazy let
342 instance Outputable Floats where
343 ppr (Floats binds ff) = ppr ff $$ ppr (fromOL binds)
345 instance Outputable FloatFlag where
346 ppr FltLifted = ptext SLIT("FltLifted")
347 ppr FltOkSpec = ptext SLIT("FltOkSpec")
348 ppr FltCareful = ptext SLIT("FltCareful")
350 andFF :: FloatFlag -> FloatFlag -> FloatFlag
351 andFF FltCareful _ = FltCareful
352 andFF FltOkSpec FltCareful = FltCareful
353 andFF FltOkSpec flt = FltOkSpec
354 andFF FltLifted flt = flt
356 classifyFF :: CoreBind -> FloatFlag
357 classifyFF (Rec _) = FltLifted
358 classifyFF (NonRec bndr rhs)
359 | not (isStrictId bndr) = FltLifted
360 | exprOkForSpeculation rhs = FltOkSpec
361 | otherwise = FltCareful
363 doFloatFromRhs :: TopLevelFlag -> RecFlag -> Bool -> OutExpr -> SimplEnv -> Bool
364 doFloatFromRhs lvl rec str rhs (SimplEnv {seFloats = Floats fs ff})
365 = not (isNilOL fs) && want_to_float && can_float
367 want_to_float = isTopLevel lvl || exprIsCheap rhs
368 can_float = case ff of
370 FltOkSpec -> isNotTopLevel lvl && isNonRec rec
371 FltCareful -> isNotTopLevel lvl && isNonRec rec && str
376 emptyFloats :: Floats
377 emptyFloats = Floats nilOL FltLifted
379 unitFloat :: OutBind -> Floats
380 -- A single-binding float
381 unitFloat bind = Floats (unitOL bind) (classifyFF bind)
383 addNonRec :: SimplEnv -> OutId -> OutExpr -> SimplEnv
384 -- Add a non-recursive binding and extend the in-scope set
385 -- The latter is important; the binder may already be in the
386 -- in-scope set (although it might also have been created with newId)
387 -- but it may now have more IdInfo
389 = env { seFloats = seFloats env `addFlts` unitFloat (NonRec id rhs),
390 seInScope = extendInScopeSet (seInScope env) id }
392 extendFloats :: SimplEnv -> [OutBind] -> SimplEnv
393 -- Add these bindings to the floats, and extend the in-scope env too
394 extendFloats env binds
395 = env { seFloats = seFloats env `addFlts` new_floats,
396 seInScope = extendInScopeSetList (seInScope env) bndrs }
398 bndrs = bindersOfBinds binds
399 new_floats = Floats (toOL binds)
400 (foldr (andFF . classifyFF) FltLifted binds)
402 addFloats :: SimplEnv -> SimplEnv -> SimplEnv
403 -- Add the floats for env2 to env1;
404 -- *plus* the in-scope set for env2, which is bigger
405 -- than that for env1
407 = env1 {seFloats = seFloats env1 `addFlts` seFloats env2,
408 seInScope = seInScope env2 }
410 addFlts :: Floats -> Floats -> Floats
411 addFlts (Floats bs1 l1) (Floats bs2 l2)
412 = Floats (bs1 `appOL` bs2) (l1 `andFF` l2)
414 zapFloats :: SimplEnv -> SimplEnv
415 zapFloats env = env { seFloats = emptyFloats }
417 addRecFloats :: SimplEnv -> SimplEnv -> SimplEnv
418 -- Flattens the floats from env2 into a single Rec group,
419 -- prepends the floats from env1, and puts the result back in env2
420 -- This is all very specific to the way recursive bindings are
421 -- handled; see Simplify.simplRecBind
422 addRecFloats env1 env2@(SimplEnv {seFloats = Floats bs ff})
423 = ASSERT2( case ff of { FltLifted -> True; other -> False }, ppr (fromOL bs) )
424 env2 {seFloats = seFloats env1 `addFlts` unitFloat (Rec (flattenBinds (fromOL bs)))}
426 wrapFloats :: SimplEnv -> OutExpr -> OutExpr
427 wrapFloats env expr = wrapFlts (seFloats env) expr
429 wrapFlts :: Floats -> OutExpr -> OutExpr
430 -- Wrap the floats around the expression, using case-binding where necessary
431 wrapFlts (Floats bs _) body = foldrOL wrap body bs
433 wrap (Rec prs) body = Let (Rec prs) body
434 wrap (NonRec b r) body = bindNonRec b r body
436 getFloats :: SimplEnv -> [CoreBind]
437 getFloats (SimplEnv {seFloats = Floats bs _}) = fromOL bs
439 isEmptyFloats :: SimplEnv -> Bool
440 isEmptyFloats env = isEmptyFlts (seFloats env)
442 isEmptyFlts :: Floats -> Bool
443 isEmptyFlts (Floats bs _) = isNilOL bs
445 floatBinds :: Floats -> [OutBind]
446 floatBinds (Floats bs _) = fromOL bs
450 %************************************************************************
454 %************************************************************************
458 substId :: SimplEnv -> InId -> SimplSR
459 -- Returns DoneEx only on a non-Var expression
460 substId (SimplEnv { seInScope = in_scope, seIdSubst = ids }) v
463 | otherwise -- A local Id
464 = case lookupVarEnv ids v of
465 Nothing -> DoneId (refine in_scope v)
466 Just (DoneId v) -> DoneId (refine in_scope v)
467 Just (DoneEx (Var v))
468 | isLocalId v -> DoneId (refine in_scope v)
469 | otherwise -> DoneId v
470 Just res -> res -- DoneEx non-var, or ContEx
473 -- Get the most up-to-date thing from the in-scope set
474 -- Even though it isn't in the substitution, it may be in
475 -- the in-scope set with better IdInfo
476 refine in_scope v = case lookupInScope in_scope v of
478 Nothing -> WARN( True, ppr v ) v -- This is an error!
480 lookupRecBndr :: SimplEnv -> InId -> OutId
481 -- Look up an Id which has been put into the envt by simplRecBndrs,
482 -- but where we have not yet done its RHS
483 lookupRecBndr (SimplEnv { seInScope = in_scope, seIdSubst = ids }) v
484 = case lookupVarEnv ids v of
486 Just res -> pprPanic "lookupRecBndr" (ppr v)
487 Nothing -> refine in_scope v
491 %************************************************************************
493 \section{Substituting an Id binder}
495 %************************************************************************
498 These functions are in the monad only so that they can be made strict via seq.
501 simplBinders, simplLamBndrs
502 :: SimplEnv -> [InBndr] -> SimplM (SimplEnv, [OutBndr])
503 simplBinders env bndrs = mapAccumLSmpl simplBinder env bndrs
504 simplLamBndrs env bndrs = mapAccumLSmpl simplLamBndr env bndrs
507 simplBinder :: SimplEnv -> InBndr -> SimplM (SimplEnv, OutBndr)
508 -- Used for lambda and case-bound variables
509 -- Clone Id if necessary, substitute type
510 -- Return with IdInfo already substituted, but (fragile) occurrence info zapped
511 -- The substitution is extended only if the variable is cloned, because
512 -- we *don't* need to use it to track occurrence info.
514 | isTyVar bndr = do { let (env', tv) = substTyVarBndr env bndr
515 ; seqTyVar tv `seq` return (env', tv) }
516 | otherwise = do { let (env', id) = substIdBndr env bndr
517 ; seqId id `seq` return (env', id) }
520 simplLamBndr :: SimplEnv -> Var -> SimplM (SimplEnv, Var)
521 -- Used for lambda binders. These sometimes have unfoldings added by
522 -- the worker/wrapper pass that must be preserved, becuase they can't
523 -- be reconstructed from context. For example:
524 -- f x = case x of (a,b) -> fw a b x
525 -- fw a b x{=(a,b)} = ...
526 -- The "{=(a,b)}" is an unfolding we can't reconstruct otherwise.
527 simplLamBndr env bndr
528 | not (isId bndr && hasSomeUnfolding old_unf) = simplBinder env bndr -- Normal case
529 | otherwise = seqId id2 `seq` return (env', id2)
531 old_unf = idUnfolding bndr
532 (env', id1) = substIdBndr env bndr
533 id2 = id1 `setIdUnfolding` substUnfolding env old_unf
536 simplNonRecBndr :: SimplEnv -> InBndr -> SimplM (SimplEnv, OutBndr)
537 -- A non-recursive let binder
538 simplNonRecBndr env id
539 = do { let (env1, id1) = substIdBndr env id
540 ; seqId id1 `seq` return (env1, id1) }
543 simplRecBndrs :: SimplEnv -> [InBndr] -> SimplM SimplEnv
544 -- Recursive let binders
545 simplRecBndrs env@(SimplEnv { seInScope = in_scope, seIdSubst = id_subst }) ids
546 = do { let (env1, ids1) = mapAccumL substIdBndr env ids
547 ; seqIds ids1 `seq` return env1 }
550 substIdBndr :: SimplEnv
551 -> InBndr -- Env and binder to transform
552 -> (SimplEnv, OutBndr)
553 -- Clone Id if necessary, substitute its type
554 -- Return an Id with its
555 -- * Type substituted
556 -- * UnfoldingInfo, Rules, WorkerInfo zapped
557 -- * Fragile OccInfo (only) zapped: Note [Robust OccInfo]
558 -- * Robust info, retained especially arity and demand info,
559 -- so that they are available to occurrences that occur in an
560 -- earlier binding of a letrec
562 -- For the robust info, see Note [Arity robustness]
564 -- Augment the substitution if the unique changed
565 -- Extend the in-scope set with the new Id
567 -- Similar to CoreSubst.substIdBndr, except that
568 -- the type of id_subst differs
569 -- all fragile info is zapped
571 substIdBndr env@(SimplEnv { seInScope = in_scope, seIdSubst = id_subst })
573 = (env { seInScope = in_scope `extendInScopeSet` new_id,
574 seIdSubst = new_subst }, new_id)
576 id1 = uniqAway in_scope old_id
577 id2 = substIdType env id1
578 new_id = zapFragileIdInfo id2 -- Zaps rules, worker-info, unfolding
579 -- and fragile OccInfo
581 -- Extend the substitution if the unique has changed,
582 -- or there's some useful occurrence information
583 -- See the notes with substTyVarBndr for the delSubstEnv
584 new_subst | new_id /= old_id
585 = extendVarEnv id_subst old_id (DoneId new_id)
587 = delVarEnv id_subst old_id
591 ------------------------------------
592 seqTyVar :: TyVar -> ()
593 seqTyVar b = b `seq` ()
596 seqId id = seqType (idType id) `seq`
602 seqIds (id:ids) = seqId id `seq` seqIds ids
606 Note [Arity robustness]
607 ~~~~~~~~~~~~~~~~~~~~~~~
608 We *do* transfer the arity from from the in_id of a let binding to the
609 out_id. This is important, so that the arity of an Id is visible in
610 its own RHS. For example:
611 f = \x. ....g (\y. f y)....
612 We can eta-reduce the arg to g, becuase f is a value. But that
615 This interacts with the 'state hack' too:
620 Can we eta-expand f? Only if we see that f has arity 1, and then we
621 take advantage of the 'state hack' on the result of
622 (f y) :: State# -> (State#, Int) to expand the arity one more.
624 There is a disadvantage though. Making the arity visible in the RHS
625 allows us to eta-reduce
629 which technically is not sound. This is very much a corner case, so
630 I'm not worried about it. Another idea is to ensure that f's arity
631 never decreases; its arity started as 1, and we should never eta-reduce
635 Note [Robust OccInfo]
636 ~~~~~~~~~~~~~~~~~~~~~
637 It's important that we *do* retain the loop-breaker OccInfo, because
638 that's what stops the Id getting inlined infinitely, in the body of
642 Note [Rules in a letrec]
643 ~~~~~~~~~~~~~~~~~~~~~~~~
644 After creating fresh binders for the binders of a letrec, we
645 substitute the RULES and add them back onto the binders; this is done
646 *before* processing any of the RHSs. This is important. Manuel found
647 cases where he really, really wanted a RULE for a recursive function
648 to apply in that function's own right-hand side.
650 See Note [Loop breaking and RULES] in OccAnal.
654 addBndrRules :: SimplEnv -> InBndr -> OutBndr -> (SimplEnv, OutBndr)
655 -- Rules are added back in to to hte bin
656 addBndrRules env in_id out_id
657 | isEmptySpecInfo old_rules = (env, out_id)
658 | otherwise = (modifyInScope env out_id final_id, final_id)
660 subst = mkCoreSubst env
661 old_rules = idSpecialisation in_id
662 new_rules = CoreSubst.substSpec subst out_id old_rules
663 final_id = out_id `setIdSpecialisation` new_rules
666 substIdType :: SimplEnv -> Id -> Id
667 substIdType env@(SimplEnv { seInScope = in_scope, seTvSubst = tv_env}) id
668 | isEmptyVarEnv tv_env || isEmptyVarSet (tyVarsOfType old_ty) = id
669 | otherwise = Id.setIdType id (Type.substTy (TvSubst in_scope tv_env) old_ty)
670 -- The tyVarsOfType is cheaper than it looks
671 -- because we cache the free tyvars of the type
672 -- in a Note in the id's type itself
677 substUnfolding :: SimplEnv -> Unfolding -> Unfolding
678 substUnfolding env NoUnfolding = NoUnfolding
679 substUnfolding env (OtherCon cons) = OtherCon cons
680 substUnfolding env (CompulsoryUnfolding rhs) = CompulsoryUnfolding (substExpr env rhs)
681 substUnfolding env (CoreUnfolding rhs t v w g) = CoreUnfolding (substExpr env rhs) t v w g
684 substWorker :: SimplEnv -> WorkerInfo -> WorkerInfo
685 substWorker env NoWorker = NoWorker
686 substWorker env wkr_info = CoreSubst.substWorker (mkCoreSubst env) wkr_info
690 %************************************************************************
692 Impedence matching to type substitution
694 %************************************************************************
697 substTy :: SimplEnv -> Type -> Type
698 substTy (SimplEnv { seInScope = in_scope, seTvSubst = tv_env }) ty
699 = Type.substTy (TvSubst in_scope tv_env) ty
701 substTyVarBndr :: SimplEnv -> TyVar -> (SimplEnv, TyVar)
702 substTyVarBndr env@(SimplEnv { seInScope = in_scope, seTvSubst = tv_env }) tv
703 = case Type.substTyVarBndr (TvSubst in_scope tv_env) tv of
704 (TvSubst in_scope' tv_env', tv')
705 -> (env { seInScope = in_scope', seTvSubst = tv_env'}, tv')
707 -- When substituting in rules etc we can get CoreSubst to do the work
708 -- But CoreSubst uses a simpler form of IdSubstEnv, so we must impedence-match
709 -- here. I think the this will not usually result in a lot of work;
710 -- the substitutions are typically small, and laziness will avoid work in many cases.
712 mkCoreSubst :: SimplEnv -> CoreSubst.Subst
713 mkCoreSubst (SimplEnv { seInScope = in_scope, seTvSubst = tv_env, seIdSubst = id_env })
714 = mk_subst tv_env id_env
716 mk_subst tv_env id_env = CoreSubst.mkSubst in_scope tv_env (mapVarEnv fiddle id_env)
718 fiddle (DoneEx e) = e
719 fiddle (DoneId v) = Var v
720 fiddle (ContEx tv id e) = CoreSubst.substExpr (mk_subst tv id) e
722 substExpr :: SimplEnv -> CoreExpr -> CoreExpr
724 | isEmptySimplSubst env = expr
725 | otherwise = CoreSubst.substExpr (mkCoreSubst env) expr