I was perplexed about why an arity-related WARN was tripping. It took
me _day_ (sigh) to find that it was because SimplEnv.substExpr was taking
a short cut when the substitution was empty, thereby not subsituting for
Ids in scope, which must be done (CoreSubst Note [Extending the Subst]).
The fix is a matter of deleting the "optimisation". Same with
CoreSubst.substSpec, although I don't know if that actually caused a
probem.
-- Types.TvSubstEnv
--
-- INVARIANT 3: See Note [Extending the Subst]
-- Types.TvSubstEnv
--
-- INVARIANT 3: See Note [Extending the Subst]
Note [Extending the Subst]
~~~~~~~~~~~~~~~~~~~~~~~~~~
For a core Subst, which binds Ids as well, we make a different choice for Ids
Note [Extending the Subst]
~~~~~~~~~~~~~~~~~~~~~~~~~~
For a core Subst, which binds Ids as well, we make a different choice for Ids
so we only extend the in-scope set. Then we must look up in the in-scope
set when we find the occurrence of x.
so we only extend the in-scope set. Then we must look up in the in-scope
set when we find the occurrence of x.
+* The requirement to look up the Id in the in-scope set means that we
+ must NOT take no-op short cut in the case the substitution is empty.
+ We must still look up every Id in the in-scope set.
+
+* (However, we don't need to do so for expressions found in the IdSubst
+ itself, whose range is assumed to be correct wrt the in-scope set.)
+
Why do we make a different choice for the IdSubstEnv than the TvSubstEnv?
* For Ids, we change the IdInfo all the time (e.g. deleting the
Why do we make a different choice for the IdSubstEnv than the TvSubstEnv?
* For Ids, we change the IdInfo all the time (e.g. deleting the
* For TyVars, only coercion variables can possibly change, and they are
easy to spot
* For TyVars, only coercion variables can possibly change, and they are
easy to spot
-- | An environment for substituting for 'Id's
type IdSubstEnv = IdEnv CoreExpr
-- | An environment for substituting for 'Id's
type IdSubstEnv = IdEnv CoreExpr
\begin{code}
-- | Apply a substititon to an entire 'CoreExpr'. Rememeber, you may only
-- apply the substitution /once/: see "CoreSubst#apply_once"
\begin{code}
-- | Apply a substititon to an entire 'CoreExpr'. Rememeber, you may only
-- apply the substitution /once/: see "CoreSubst#apply_once"
+--
+-- Do *not* attempt to short-cut in the case of an empty substitution!
+-- See Note [Extending the Subst]
substExpr :: Subst -> CoreExpr -> CoreExpr
substExpr subst expr
= go expr
substExpr :: Subst -> CoreExpr -> CoreExpr
substExpr subst expr
= go expr
------------------
-- | Substitutes for the 'Id's within the 'WorkerInfo' given the new function 'Id'
substSpec :: Subst -> Id -> SpecInfo -> SpecInfo
------------------
-- | Substitutes for the 'Id's within the 'WorkerInfo' given the new function 'Id'
substSpec :: Subst -> Id -> SpecInfo -> SpecInfo
-
-substSpec subst new_fn spec@(SpecInfo rules rhs_fvs)
- | isEmptySubst subst
- = spec
- | otherwise
+substSpec subst new_fn (SpecInfo rules rhs_fvs)
= seqSpecInfo new_rules `seq` new_rules
where
new_name = idName new_fn
= seqSpecInfo new_rules `seq` new_rules
where
new_name = idName new_fn
mkContEx :: SimplEnv -> InExpr -> SimplSR
mkContEx (SimplEnv { seTvSubst = tvs, seIdSubst = ids }) e = ContEx tvs ids e
mkContEx :: SimplEnv -> InExpr -> SimplSR
mkContEx (SimplEnv { seTvSubst = tvs, seIdSubst = ids }) e = ContEx tvs ids e
-
-isEmptySimplSubst :: SimplEnv -> Bool
-isEmptySimplSubst (SimplEnv { seTvSubst = tvs, seIdSubst = ids })
- = isEmptyVarEnv tvs && isEmptyVarEnv ids
fiddle (ContEx tv id e) = CoreSubst.substExpr (mk_subst tv id) e
substExpr :: SimplEnv -> CoreExpr -> CoreExpr
fiddle (ContEx tv id e) = CoreSubst.substExpr (mk_subst tv id) e
substExpr :: SimplEnv -> CoreExpr -> CoreExpr
-substExpr env expr
- | isEmptySimplSubst env = expr
- | otherwise = CoreSubst.substExpr (mkCoreSubst env) expr
+substExpr env expr = CoreSubst.substExpr (mkCoreSubst env) expr
+ -- Do *not* short-cut in the case of an empty substitution
+ -- See CoreSubst: Note [Extending the Subst]