Note [Cloning CoVars and TyVars]
Normally we don't need to clone TyVars and CoVars, but there is one occasion when we do (see #24463). When we have case unsafeEqualityProof ... of UnsafeRefl g -> ... we try to float it, using UnsafeEqualityCase. Why? See (U3) in Note [Implementing unsafeCoerce] Alas, floating it widens the scope of `g`, and that led to catastrophe in #24463, when two identically-named g's shadowed. Solution: clone `g`; see `cpCloneCoVarBndr`. BUT once we clone `g` we must apply the cloning substitution to all types and coercions. But that in turn means that, given a binder like /\ (a :: kind |> g). blah we must substitute in a's kind, and hence need to substitute for `a` itself in `blah`. So our plan is: * Maintain a full Subst in `cpe_subst` * Clone a CoVar when we we meet an `isUnsafeEqualityCase`; otherwise TyVar/CoVar binders are never cloned. * So generally the TCvSubst is empty * Apply the substitution to type and coercion arguments in Core; but happily `substTy` has a no-op short-cut for an empty TCvSubst, so this is usually very cheap. * In `cpCloneBndr`, for a tyvar/covar binder, check for an empty substitution; in that case just do nothing
References 1
- Implementing unsafeCoerce GHC.Internal.Unsafe.Coerce
Referenced by 5
- GHC.CoreToStg.Prep call site ×3
- Cloning in CorePrep GHC.CoreToStg.Prep
- CorePrepEnv: cpe_subst GHC.CoreToStg.Prep