    {-
    (c) The University of Glasgow 2006
    (c) The GRASP/AQUA Project, Glasgow University, 1998
    Type and Coercion - friends' interface
    -}

    {-# LANGUAGE CPP #-}
    {-# LANGUAGE BangPatterns #-}
    {-# OPTIONS_GHC -Wno-incomplete-record-updates #-}

    -- | Substitution into types and coercions.
    module GHC.Core.TyCo.Subst
      (
            -- * Substitutions
            TCvSubst(..), TvSubstEnv, CvSubstEnv,
            emptyTvSubstEnv, emptyCvSubstEnv, composeTCvSubstEnv, composeTCvSubst,
            emptyTCvSubst, mkEmptyTCvSubst, isEmptyTCvSubst,
            mkTCvSubst, mkTvSubst, mkCvSubst,
            getTvSubstEnv,
            getCvSubstEnv, getTCvInScope, getTCvSubstRangeFVs,
            isInScope, elemTCvSubst, notElemTCvSubst,
            setTvSubstEnv, setCvSubstEnv, zapTCvSubst,
            extendTCvInScope, extendTCvInScopeList, extendTCvInScopeSet,
            extendTCvSubst, extendTCvSubstWithClone,
            extendCvSubst, extendCvSubstWithClone,
            extendTvSubst, extendTvSubstBinderAndInScope, extendTvSubstWithClone,
            extendTvSubstList, extendTvSubstAndInScope,
            extendTCvSubstList,
            unionTCvSubst, zipTyEnv, zipCoEnv,
            zipTvSubst, zipCvSubst,
            zipTCvSubst,
            mkTvSubstPrs,

            substTyWith, substTyWithCoVars, substTysWith, substTysWithCoVars,
            substCoWith,
            substTy, substTyAddInScope, substScaledTy,
            substTyUnchecked, substTysUnchecked, substScaledTysUnchecked, substThetaUnchecked,
            substTyWithUnchecked, substScaledTyUnchecked,
            substCoUnchecked, substCoWithUnchecked,
            substTyWithInScope,
            substTys, substScaledTys, substTheta,
            lookupTyVar,
            substCo, substCos, substCoVar, substCoVars, lookupCoVar,
            cloneTyVarBndr, cloneTyVarBndrs,
            substVarBndr, substVarBndrs,
            substTyVarBndr, substTyVarBndrs,
            substCoVarBndr,
            substTyVar, substTyVars, substTyCoVars,
            substTyCoBndr,
            substForAllCoBndr,
            substVarBndrUsing, substForAllCoBndrUsing,
            checkValidSubst, isValidTCvSubst,
      ) where

    #include "HsVersions.h"

    import GHC.Prelude

    import {-# SOURCE #-} GHC.Core.Type
       ( mkCastTy, mkAppTy, isCoercionTy, mkTyConApp )
    import {-# SOURCE #-} GHC.Core.Coercion
       ( mkCoVarCo, mkKindCo, mkNthCo, mkTransCo
       , mkNomReflCo, mkSubCo, mkSymCo
       , mkFunCo, mkForAllCo, mkUnivCo
       , mkAxiomInstCo, mkAppCo, mkGReflCo
       , mkInstCo, mkLRCo, mkTyConAppCo
       , mkCoercionType
       , coercionKind, coercionLKind, coVarKindsTypesRole )
    import {-# SOURCE #-} GHC.Core.TyCo.Ppr ( pprTyVar )

    import GHC.Core.TyCo.Rep
    import GHC.Core.TyCo.FVs

    import GHC.Types.Var
    import GHC.Types.Var.Set
    import GHC.Types.Var.Env

    import GHC.Data.Pair
    import GHC.Utils.Misc
    import GHC.Types.Unique.Supply
    import GHC.Types.Unique
    import GHC.Types.Unique.FM
    import GHC.Types.Unique.Set
    import GHC.Utils.Outputable
    import GHC.Utils.Panic

    import Data.List (mapAccumL)

    {-
    %************************************************************************
    %*                                                                      *
                            Substitutions
          Data type defined here to avoid unnecessary mutual recursion
    %*                                                                      *
    %************************************************************************
    -}

    -- | Type & coercion substitution
    --
    -- #tcvsubst_invariant#
    -- The following invariants must hold of a 'TCvSubst':
    --
    -- 1. The in-scope set is needed /only/ to
    -- guide the generation of fresh uniques
    --
    -- 2. In particular, the /kind/ of the type variables in
    -- the in-scope set is not relevant
    --
    -- 3. The substitution is only applied ONCE! This is because
    -- in general such application will not reach a fixed point.
    data TCvSubst
      = TCvSubst InScopeSet -- The in-scope type and kind variables
                 TvSubstEnv -- Substitutes both type and kind variables
                 CvSubstEnv -- Substitutes coercion variables
            -- See Note [Substitutions apply only once]
            -- and Note [Extending the TvSubstEnv]
            -- and Note [Substituting types and coercions]
            -- and Note [The substitution invariant]

    -- | A substitution of 'Type's for 'TyVar's
    --                 and 'Kind's for 'KindVar's
    type TvSubstEnv = TyVarEnv Type
      -- NB: A TvSubstEnv is used
      --   both inside a TCvSubst (with the apply-once invariant
      --        discussed in Note [Substitutions apply only once],
      --   and  also independently in the middle of matching,
      --        and unification (see Types.Unify).
      -- So you have to look at the context to know if it's idempotent or
      -- apply-once or whatever

    -- | A substitution of 'Coercion's for 'CoVar's
    type CvSubstEnv = CoVarEnv Coercion

    {- Note [The substitution invariant]
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    When calling (substTy subst ty) it should be the case that
    the in-scope set in the substitution is a superset of both:

      (SIa) The free vars of the range of the substitution
      (SIb) The free vars of ty minus the domain of the substitution

    The same rules apply to other substitutions (notably GHC.Core.Subst.Subst)

    * Reason for (SIa). Consider
          substTy [a :-> Maybe b] (forall b. b->a)
      we must rename the forall b, to get
          forall b2. b2 -> Maybe b
      Making 'b' part of the in-scope set forces this renaming to
      take place.

    * Reason for (SIb). Consider
         substTy [a :-> Maybe b] (forall b. (a,b,x))
      Then if we use the in-scope set {b}, satisfying (SIa), there is
      a danger we will rename the forall'd variable to 'x' by mistake,
      getting this:
          forall x. (Maybe b, x, x)
      Breaking (SIb) caused the bug from #11371.

    Note: if the free vars of the range of the substitution are freshly created,
    then the problems of (SIa) can't happen, and so it would be sound to
    ignore (SIa).

    Note [Substitutions apply only once]
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    We use TCvSubsts to instantiate things, and we might instantiate
            forall a b. ty
    with the types
            [a, b], or [b, a].
    So the substitution might go [a->b, b->a].  A similar situation arises in Core
    when we find a beta redex like
            (/\ a /\ b -> e) b a
    Then we also end up with a substitution that permutes type variables. Other
    variations happen to; for example [a -> (a, b)].

            ********************************************************
            *** So a substitution must be applied precisely once ***
            ********************************************************

    A TCvSubst is not idempotent, but, unlike the non-idempotent substitution
    we use during unifications, it must not be repeatedly applied.

    Note [Extending the TvSubstEnv]
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    See #tcvsubst_invariant# for the invariants that must hold.

    This invariant allows a short-cut when the subst envs are empty:
    if the TvSubstEnv and CvSubstEnv are empty --- i.e. (isEmptyTCvSubst subst)
    holds --- then (substTy subst ty) does nothing.

    For example, consider:
            (/\a. /\b:(a~Int). ...b..) Int
    We substitute Int for 'a'.  The Unique of 'b' does not change, but
    nevertheless we add 'b' to the TvSubstEnv, because b's kind does change

    This invariant has several crucial consequences:

    * In substVarBndr, we need extend the TvSubstEnv
            - if the unique has changed
            - or if the kind has changed

    * In substTyVar, we do not need to consult the in-scope set;
      the TvSubstEnv is enough

    * In substTy, substTheta, we can short-circuit when the TvSubstEnv is empty

    Note [Substituting types and coercions]
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    Types and coercions are mutually recursive, and either may have variables
    "belonging" to the other. Thus, every time we wish to substitute in a
    type, we may also need to substitute in a coercion, and vice versa.
    However, the constructor used to create type variables is distinct from
    that of coercion variables, so we carry two VarEnvs in a TCvSubst. Note
    that it would be possible to use the CoercionTy constructor to combine
    these environments, but that seems like a false economy.

    Note that the TvSubstEnv should *never* map a CoVar (built with the Id
    constructor) and the CvSubstEnv should *never* map a TyVar. Furthermore,
    the range of the TvSubstEnv should *never* include a type headed with
    CoercionTy.
    -}

    emptyTvSubstEnv :: TvSubstEnv
    emptyTvSubstEnv :: TvSubstEnv
    emptyTvSubstEnv = TvSubstEnv
    forall a. VarEnv a
    emptyVarEnv

    emptyCvSubstEnv :: CvSubstEnv
    emptyCvSubstEnv :: CvSubstEnv
    emptyCvSubstEnv = CvSubstEnv
    forall a. VarEnv a
    emptyVarEnv

    composeTCvSubstEnv :: InScopeSet
                       -> (TvSubstEnv, CvSubstEnv)
                       -> (TvSubstEnv, CvSubstEnv)
                       -> (TvSubstEnv, CvSubstEnv)
    -- ^ @(compose env1 env2)(x)@ is @env1(env2(x))@; i.e. apply @env2@ then @env1@.
    -- It assumes that both are idempotent.
    -- Typically, @env1@ is the refinement to a base substitution @env2@
    composeTCvSubstEnv :: InScopeSet
    -> (TvSubstEnv, CvSubstEnv)
    -> (TvSubstEnv, CvSubstEnv)
    -> (TvSubstEnv, CvSubstEnv)
    composeTCvSubstEnv InScopeSet
    in_scope (TvSubstEnv
    tenv1, CvSubstEnv
    cenv1) (TvSubstEnv
    tenv2, CvSubstEnv
    cenv2)
      = ( TvSubstEnv
    tenv1 TvSubstEnv -> TvSubstEnv -> TvSubstEnv
    forall a. VarEnv a -> VarEnv a -> VarEnv a
    `plusVarEnv` (Type -> Type) -> TvSubstEnv -> TvSubstEnv
    forall a b. (a -> b) -> VarEnv a -> VarEnv b
    mapVarEnv (HasCallStack => TCvSubst -> Type -> Type
    TCvSubst -> Type -> Type
    substTy TCvSubst
    subst1) TvSubstEnv
    tenv2
        , CvSubstEnv
    cenv1 CvSubstEnv -> CvSubstEnv -> CvSubstEnv
    forall a. VarEnv a -> VarEnv a -> VarEnv a
    `plusVarEnv` (Coercion -> Coercion) -> CvSubstEnv -> CvSubstEnv
    forall a b. (a -> b) -> VarEnv a -> VarEnv b
    mapVarEnv (HasCallStack => TCvSubst -> Coercion -> Coercion
    TCvSubst -> Coercion -> Coercion
    substCo TCvSubst
    subst1) CvSubstEnv
    cenv2 )
            -- First apply env1 to the range of env2
            -- Then combine the two, making sure that env1 loses if
            -- both bind the same variable; that's why env1 is the
            --  *left* argument to plusVarEnv, because the right arg wins
      where
        subst1 :: TCvSubst
    subst1 = InScopeSet -> TvSubstEnv -> CvSubstEnv -> TCvSubst
    TCvSubst InScopeSet
    in_scope TvSubstEnv
    tenv1 CvSubstEnv
    cenv1

    -- | Composes two substitutions, applying the second one provided first,
    -- like in function composition.
    composeTCvSubst :: TCvSubst -> TCvSubst -> TCvSubst
    composeTCvSubst :: TCvSubst -> TCvSubst -> TCvSubst
    composeTCvSubst (TCvSubst InScopeSet
    is1 TvSubstEnv
    tenv1 CvSubstEnv
    cenv1) (TCvSubst InScopeSet
    is2 TvSubstEnv
    tenv2 CvSubstEnv
    cenv2)
      = InScopeSet -> TvSubstEnv -> CvSubstEnv -> TCvSubst
    TCvSubst InScopeSet
    is3 TvSubstEnv
    tenv3 CvSubstEnv
    cenv3
      where
        is3 :: InScopeSet
    is3 = InScopeSet
    is1 InScopeSet -> InScopeSet -> InScopeSet
    `unionInScope` InScopeSet
    is2
        (TvSubstEnv
    tenv3, CvSubstEnv
    cenv3) = InScopeSet
    -> (TvSubstEnv, CvSubstEnv)
    -> (TvSubstEnv, CvSubstEnv)
    -> (TvSubstEnv, CvSubstEnv)
    composeTCvSubstEnv InScopeSet
    is3 (TvSubstEnv
    tenv1, CvSubstEnv
    cenv1) (TvSubstEnv
    tenv2, CvSubstEnv
    cenv2)

    emptyTCvSubst :: TCvSubst
    emptyTCvSubst :: TCvSubst
    emptyTCvSubst = InScopeSet -> TvSubstEnv -> CvSubstEnv -> TCvSubst
    TCvSubst InScopeSet
    emptyInScopeSet TvSubstEnv
    emptyTvSubstEnv CvSubstEnv
    emptyCvSubstEnv

    mkEmptyTCvSubst :: InScopeSet -> TCvSubst
    mkEmptyTCvSubst :: InScopeSet -> TCvSubst
    mkEmptyTCvSubst InScopeSet
    is = InScopeSet -> TvSubstEnv -> CvSubstEnv -> TCvSubst
    TCvSubst InScopeSet
    is TvSubstEnv
    emptyTvSubstEnv CvSubstEnv
    emptyCvSubstEnv

    isEmptyTCvSubst :: TCvSubst -> Bool
             -- See Note [Extending the TvSubstEnv]
    isEmptyTCvSubst :: TCvSubst -> Bool
    isEmptyTCvSubst (TCvSubst InScopeSet
    _ TvSubstEnv
    tenv CvSubstEnv
    cenv) = TvSubstEnv -> Bool
    forall a. VarEnv a -> Bool
    isEmptyVarEnv TvSubstEnv
    tenv Bool -> Bool -> Bool
    && CvSubstEnv -> Bool
    forall a. VarEnv a -> Bool
    isEmptyVarEnv CvSubstEnv
    cenv

    mkTCvSubst :: InScopeSet -> (TvSubstEnv, CvSubstEnv) -> TCvSubst
    mkTCvSubst :: InScopeSet -> (TvSubstEnv, CvSubstEnv) -> TCvSubst
    mkTCvSubst InScopeSet
    in_scope (TvSubstEnv
    tenv, CvSubstEnv
    cenv) = InScopeSet -> TvSubstEnv -> CvSubstEnv -> TCvSubst
    TCvSubst InScopeSet
    in_scope TvSubstEnv
    tenv CvSubstEnv
    cenv

    mkTvSubst :: InScopeSet -> TvSubstEnv -> TCvSubst
    -- ^ Make a TCvSubst with specified tyvar subst and empty covar subst
    mkTvSubst :: InScopeSet -> TvSubstEnv -> TCvSubst
    mkTvSubst InScopeSet
    in_scope TvSubstEnv
    tenv = InScopeSet -> TvSubstEnv -> CvSubstEnv -> TCvSubst
    TCvSubst InScopeSet
    in_scope TvSubstEnv
    tenv CvSubstEnv
    emptyCvSubstEnv

    mkCvSubst :: InScopeSet -> CvSubstEnv -> TCvSubst
    -- ^ Make a TCvSubst with specified covar subst and empty tyvar subst
    mkCvSubst :: InScopeSet -> CvSubstEnv -> TCvSubst
    mkCvSubst InScopeSet
    in_scope CvSubstEnv
    cenv = InScopeSet -> TvSubstEnv -> CvSubstEnv -> TCvSubst
    TCvSubst InScopeSet
    in_scope TvSubstEnv
    emptyTvSubstEnv CvSubstEnv
    cenv

    getTvSubstEnv :: TCvSubst -> TvSubstEnv
    getTvSubstEnv :: TCvSubst -> TvSubstEnv
    getTvSubstEnv (TCvSubst InScopeSet
    _ TvSubstEnv
    env CvSubstEnv
    _) = TvSubstEnv
    env

    getCvSubstEnv :: TCvSubst -> CvSubstEnv
    getCvSubstEnv :: TCvSubst -> CvSubstEnv
    getCvSubstEnv (TCvSubst InScopeSet
    _ TvSubstEnv
    _ CvSubstEnv
    env) = CvSubstEnv
    env

    getTCvInScope :: TCvSubst -> InScopeSet
    getTCvInScope :: TCvSubst -> InScopeSet
    getTCvInScope (TCvSubst InScopeSet
    in_scope TvSubstEnv
    _ CvSubstEnv
    _) = InScopeSet
    in_scope

    -- | Returns the free variables of the types in the range of a substitution as
    -- a non-deterministic set.
    getTCvSubstRangeFVs :: TCvSubst -> VarSet
    getTCvSubstRangeFVs :: TCvSubst -> VarSet
    getTCvSubstRangeFVs (TCvSubst InScopeSet
    _ TvSubstEnv
    tenv CvSubstEnv
    cenv)
        = VarSet -> VarSet -> VarSet
    unionVarSet VarSet
    tenvFVs VarSet
    cenvFVs
      where
        tenvFVs :: VarSet
    tenvFVs = TvSubstEnv -> VarSet
    shallowTyCoVarsOfTyVarEnv TvSubstEnv
    tenv
        cenvFVs :: VarSet
    cenvFVs = CvSubstEnv -> VarSet
    shallowTyCoVarsOfCoVarEnv CvSubstEnv
    cenv

    isInScope :: Var -> TCvSubst -> Bool
    isInScope :: Var -> TCvSubst -> Bool
    isInScope Var
    v (TCvSubst InScopeSet
    in_scope TvSubstEnv
    _ CvSubstEnv
    _) = Var
    v Var -> InScopeSet -> Bool
    `elemInScopeSet` InScopeSet
    in_scope

    elemTCvSubst :: Var -> TCvSubst -> Bool
    elemTCvSubst :: Var -> TCvSubst -> Bool
    elemTCvSubst Var
    v (TCvSubst InScopeSet
    _ TvSubstEnv
    tenv CvSubstEnv
    cenv)
      | Var -> Bool
    isTyVar Var
    v
      = Var
    v Var -> TvSubstEnv -> Bool
    forall a. Var -> VarEnv a -> Bool
    `elemVarEnv` TvSubstEnv
    tenv
      | Bool
    otherwise
      = Var
    v Var -> CvSubstEnv -> Bool
    forall a. Var -> VarEnv a -> Bool
    `elemVarEnv` CvSubstEnv
    cenv

    notElemTCvSubst :: Var -> TCvSubst -> Bool
    notElemTCvSubst :: Var -> TCvSubst -> Bool
    notElemTCvSubst Var
    v = Bool -> Bool
    not (Bool -> Bool) -> (TCvSubst -> Bool) -> TCvSubst -> Bool
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Var -> TCvSubst -> Bool
    elemTCvSubst Var
    v

    setTvSubstEnv :: TCvSubst -> TvSubstEnv -> TCvSubst
    setTvSubstEnv :: TCvSubst -> TvSubstEnv -> TCvSubst
    setTvSubstEnv (TCvSubst InScopeSet
    in_scope TvSubstEnv
    _ CvSubstEnv
    cenv) TvSubstEnv
    tenv = InScopeSet -> TvSubstEnv -> CvSubstEnv -> TCvSubst
    TCvSubst InScopeSet
    in_scope TvSubstEnv
    tenv CvSubstEnv
    cenv

    setCvSubstEnv :: TCvSubst -> CvSubstEnv -> TCvSubst
    setCvSubstEnv :: TCvSubst -> CvSubstEnv -> TCvSubst
    setCvSubstEnv (TCvSubst InScopeSet
    in_scope TvSubstEnv
    tenv CvSubstEnv
    _) CvSubstEnv
    cenv = InScopeSet -> TvSubstEnv -> CvSubstEnv -> TCvSubst
    TCvSubst InScopeSet
    in_scope TvSubstEnv
    tenv CvSubstEnv
    cenv

    zapTCvSubst :: TCvSubst -> TCvSubst
    zapTCvSubst :: TCvSubst -> TCvSubst
    zapTCvSubst (TCvSubst InScopeSet
    in_scope TvSubstEnv
    _ CvSubstEnv
    _) = InScopeSet -> TvSubstEnv -> CvSubstEnv -> TCvSubst
    TCvSubst InScopeSet
    in_scope TvSubstEnv
    forall a. VarEnv a
    emptyVarEnv CvSubstEnv
    forall a. VarEnv a
    emptyVarEnv

    extendTCvInScope :: TCvSubst -> Var -> TCvSubst
    extendTCvInScope :: TCvSubst -> Var -> TCvSubst
    extendTCvInScope (TCvSubst InScopeSet
    in_scope TvSubstEnv
    tenv CvSubstEnv
    cenv) Var
    var
      = InScopeSet -> TvSubstEnv -> CvSubstEnv -> TCvSubst
    TCvSubst (InScopeSet -> Var -> InScopeSet
    extendInScopeSet InScopeSet
    in_scope Var
    var) TvSubstEnv
    tenv CvSubstEnv
    cenv

    extendTCvInScopeList :: TCvSubst -> [Var] -> TCvSubst
    extendTCvInScopeList :: TCvSubst -> [Var] -> TCvSubst
    extendTCvInScopeList (TCvSubst InScopeSet
    in_scope TvSubstEnv
    tenv CvSubstEnv
    cenv) [Var]
    vars
      = InScopeSet -> TvSubstEnv -> CvSubstEnv -> TCvSubst
    TCvSubst (InScopeSet -> [Var] -> InScopeSet
    extendInScopeSetList InScopeSet
    in_scope [Var]
    vars) TvSubstEnv
    tenv CvSubstEnv
    cenv

    extendTCvInScopeSet :: TCvSubst -> VarSet -> TCvSubst
    extendTCvInScopeSet :: TCvSubst -> VarSet -> TCvSubst
    extendTCvInScopeSet (TCvSubst InScopeSet
    in_scope TvSubstEnv
    tenv CvSubstEnv
    cenv) VarSet
    vars
      = InScopeSet -> TvSubstEnv -> CvSubstEnv -> TCvSubst
    TCvSubst (InScopeSet -> VarSet -> InScopeSet
    extendInScopeSetSet InScopeSet
    in_scope VarSet
    vars) TvSubstEnv
    tenv CvSubstEnv
    cenv

    extendTCvSubst :: TCvSubst -> TyCoVar -> Type -> TCvSubst
    extendTCvSubst :: TCvSubst -> Var -> Type -> TCvSubst
    extendTCvSubst TCvSubst
    subst Var
    v Type
    ty
      | Var -> Bool
    isTyVar Var
    v
      = TCvSubst -> Var -> Type -> TCvSubst
    extendTvSubst TCvSubst
    subst Var
    v Type
    ty
      | CoercionTy Coercion
    co <- Type
    ty
      = TCvSubst -> Var -> Coercion -> TCvSubst
    extendCvSubst TCvSubst
    subst Var
    v Coercion
    co
      | Bool
    otherwise
      = String -> SDoc -> TCvSubst
    forall a. HasCallStack => String -> SDoc -> a
    pprPanic String
    "extendTCvSubst" (Var -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr Var
    v SDoc -> SDoc -> SDoc
    <+> String -> SDoc
    text String
    "|->" SDoc -> SDoc -> SDoc
    <+> Type -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr Type
    ty)

    extendTCvSubstWithClone :: TCvSubst -> TyCoVar -> TyCoVar -> TCvSubst
    extendTCvSubstWithClone :: TCvSubst -> Var -> Var -> TCvSubst
    extendTCvSubstWithClone TCvSubst
    subst Var
    tcv
      | Var -> Bool
    isTyVar Var
    tcv = TCvSubst -> Var -> Var -> TCvSubst
    extendTvSubstWithClone TCvSubst
    subst Var
    tcv
      | Bool
    otherwise   = TCvSubst -> Var -> Var -> TCvSubst
    extendCvSubstWithClone TCvSubst
    subst Var
    tcv

    extendTvSubst :: TCvSubst -> TyVar -> Type -> TCvSubst
    extendTvSubst :: TCvSubst -> Var -> Type -> TCvSubst
    extendTvSubst (TCvSubst InScopeSet
    in_scope TvSubstEnv
    tenv CvSubstEnv
    cenv) Var
    tv Type
    ty
      = InScopeSet -> TvSubstEnv -> CvSubstEnv -> TCvSubst
    TCvSubst InScopeSet
    in_scope (TvSubstEnv -> Var -> Type -> TvSubstEnv
    forall a. VarEnv a -> Var -> a -> VarEnv a
    extendVarEnv TvSubstEnv
    tenv Var
    tv Type
    ty) CvSubstEnv
    cenv

    extendTvSubstBinderAndInScope :: TCvSubst -> TyCoBinder -> Type -> TCvSubst
    extendTvSubstBinderAndInScope :: TCvSubst -> TyCoBinder -> Type -> TCvSubst
    extendTvSubstBinderAndInScope TCvSubst
    subst (Named (Bndr Var
    v ArgFlag
    _)) Type
    ty
      = ASSERT( isTyVar v )
        TCvSubst -> Var -> Type -> TCvSubst
    extendTvSubstAndInScope TCvSubst
    subst Var
    v Type
    ty
    extendTvSubstBinderAndInScope TCvSubst
    subst (Anon {}) Type
    _
      = TCvSubst
    subst

    extendTvSubstWithClone :: TCvSubst -> TyVar -> TyVar -> TCvSubst
    -- Adds a new tv -> tv mapping, /and/ extends the in-scope set
    extendTvSubstWithClone :: TCvSubst -> Var -> Var -> TCvSubst
    extendTvSubstWithClone (TCvSubst InScopeSet
    in_scope TvSubstEnv
    tenv CvSubstEnv
    cenv) Var
    tv Var
    tv'
      = InScopeSet -> TvSubstEnv -> CvSubstEnv -> TCvSubst
    TCvSubst (InScopeSet -> VarSet -> InScopeSet
    extendInScopeSetSet InScopeSet
    in_scope VarSet
    new_in_scope)
                 (TvSubstEnv -> Var -> Type -> TvSubstEnv
    forall a. VarEnv a -> Var -> a -> VarEnv a
    extendVarEnv TvSubstEnv
    tenv Var
    tv (Var -> Type
    mkTyVarTy Var
    tv'))
                 CvSubstEnv
    cenv
      where
        new_in_scope :: VarSet
    new_in_scope = Type -> VarSet
    tyCoVarsOfType (Var -> Type
    tyVarKind Var
    tv') VarSet -> Var -> VarSet
    `extendVarSet` Var
    tv'

    extendCvSubst :: TCvSubst -> CoVar -> Coercion -> TCvSubst
    extendCvSubst :: TCvSubst -> Var -> Coercion -> TCvSubst
    extendCvSubst (TCvSubst InScopeSet
    in_scope TvSubstEnv
    tenv CvSubstEnv
    cenv) Var
    v Coercion
    co
      = InScopeSet -> TvSubstEnv -> CvSubstEnv -> TCvSubst
    TCvSubst InScopeSet
    in_scope TvSubstEnv
    tenv (CvSubstEnv -> Var -> Coercion -> CvSubstEnv
    forall a. VarEnv a -> Var -> a -> VarEnv a
    extendVarEnv CvSubstEnv
    cenv Var
    v Coercion
    co)

    extendCvSubstWithClone :: TCvSubst -> CoVar -> CoVar -> TCvSubst
    extendCvSubstWithClone :: TCvSubst -> Var -> Var -> TCvSubst
    extendCvSubstWithClone (TCvSubst InScopeSet
    in_scope TvSubstEnv
    tenv CvSubstEnv
    cenv) Var
    cv Var
    cv'
      = InScopeSet -> TvSubstEnv -> CvSubstEnv -> TCvSubst
    TCvSubst (InScopeSet -> VarSet -> InScopeSet
    extendInScopeSetSet InScopeSet
    in_scope VarSet
    new_in_scope)
                 TvSubstEnv
    tenv
                 (CvSubstEnv -> Var -> Coercion -> CvSubstEnv
    forall a. VarEnv a -> Var -> a -> VarEnv a
    extendVarEnv CvSubstEnv
    cenv Var
    cv (Var -> Coercion
    mkCoVarCo Var
    cv'))
      where
        new_in_scope :: VarSet
    new_in_scope = Type -> VarSet
    tyCoVarsOfType (Var -> Type
    varType Var
    cv') VarSet -> Var -> VarSet
    `extendVarSet` Var
    cv'

    extendTvSubstAndInScope :: TCvSubst -> TyVar -> Type -> TCvSubst
    -- Also extends the in-scope set
    extendTvSubstAndInScope :: TCvSubst -> Var -> Type -> TCvSubst
    extendTvSubstAndInScope (TCvSubst InScopeSet
    in_scope TvSubstEnv
    tenv CvSubstEnv
    cenv) Var
    tv Type
    ty
      = InScopeSet -> TvSubstEnv -> CvSubstEnv -> TCvSubst
    TCvSubst (InScopeSet
    in_scope InScopeSet -> VarSet -> InScopeSet
    `extendInScopeSetSet` Type -> VarSet
    tyCoVarsOfType Type
    ty)
                 (TvSubstEnv -> Var -> Type -> TvSubstEnv
    forall a. VarEnv a -> Var -> a -> VarEnv a
    extendVarEnv TvSubstEnv
    tenv Var
    tv Type
    ty)
                 CvSubstEnv
    cenv

    extendTvSubstList :: TCvSubst -> [Var] -> [Type] -> TCvSubst
    extendTvSubstList :: TCvSubst -> [Var] -> [Type] -> TCvSubst
    extendTvSubstList TCvSubst
    subst [Var]
    tvs [Type]
    tys
      = (TCvSubst -> Var -> Type -> TCvSubst)
    -> TCvSubst -> [Var] -> [Type] -> TCvSubst
    forall acc a b. (acc -> a -> b -> acc) -> acc -> [a] -> [b] -> acc
    foldl2 TCvSubst -> Var -> Type -> TCvSubst
    extendTvSubst TCvSubst
    subst [Var]
    tvs [Type]
    tys

    extendTCvSubstList :: TCvSubst -> [Var] -> [Type] -> TCvSubst
    extendTCvSubstList :: TCvSubst -> [Var] -> [Type] -> TCvSubst
    extendTCvSubstList TCvSubst
    subst [Var]
    tvs [Type]
    tys
      = (TCvSubst -> Var -> Type -> TCvSubst)
    -> TCvSubst -> [Var] -> [Type] -> TCvSubst
    forall acc a b. (acc -> a -> b -> acc) -> acc -> [a] -> [b] -> acc
    foldl2 TCvSubst -> Var -> Type -> TCvSubst
    extendTCvSubst TCvSubst
    subst [Var]
    tvs [Type]
    tys

    unionTCvSubst :: TCvSubst -> TCvSubst -> TCvSubst
    -- Works when the ranges are disjoint
    unionTCvSubst :: TCvSubst -> TCvSubst -> TCvSubst
    unionTCvSubst (TCvSubst InScopeSet
    in_scope1 TvSubstEnv
    tenv1 CvSubstEnv
    cenv1) (TCvSubst InScopeSet
    in_scope2 TvSubstEnv
    tenv2 CvSubstEnv
    cenv2)
      = ASSERT( tenv1 `disjointVarEnv` tenv2
             && cenv1 `disjointVarEnv` cenv2 )
        InScopeSet -> TvSubstEnv -> CvSubstEnv -> TCvSubst
    TCvSubst (InScopeSet
    in_scope1 InScopeSet -> InScopeSet -> InScopeSet
    `unionInScope` InScopeSet
    in_scope2)
                 (TvSubstEnv
    tenv1     TvSubstEnv -> TvSubstEnv -> TvSubstEnv
    forall a. VarEnv a -> VarEnv a -> VarEnv a
    `plusVarEnv`   TvSubstEnv
    tenv2)
                 (CvSubstEnv
    cenv1     CvSubstEnv -> CvSubstEnv -> CvSubstEnv
    forall a. VarEnv a -> VarEnv a -> VarEnv a
    `plusVarEnv`   CvSubstEnv
    cenv2)

    -- mkTvSubstPrs and zipTvSubst generate the in-scope set from
    -- the types given; but it's just a thunk so with a bit of luck
    -- it'll never be evaluated

    -- | Generates the in-scope set for the 'TCvSubst' from the types in the incoming
    -- environment. No CoVars, please!
    zipTvSubst :: HasDebugCallStack => [TyVar] -> [Type] -> TCvSubst
    zipTvSubst :: HasDebugCallStack => [Var] -> [Type] -> TCvSubst
    zipTvSubst [Var]
    tvs [Type]
    tys
      = InScopeSet -> TvSubstEnv -> TCvSubst
    mkTvSubst (VarSet -> InScopeSet
    mkInScopeSet ([Type] -> VarSet
    shallowTyCoVarsOfTypes [Type]
    tys)) TvSubstEnv
    tenv
      where
        tenv :: TvSubstEnv
    tenv = [Var] -> [Type] -> TvSubstEnv
    HasDebugCallStack => [Var] -> [Type] -> TvSubstEnv
    zipTyEnv [Var]
    tvs [Type]
    tys

    -- | Generates the in-scope set for the 'TCvSubst' from the types in the incoming
    -- environment.  No TyVars, please!
    zipCvSubst :: HasDebugCallStack => [CoVar] -> [Coercion] -> TCvSubst
    zipCvSubst :: HasDebugCallStack => [Var] -> [Coercion] -> TCvSubst
    zipCvSubst [Var]
    cvs [Coercion]
    cos
      = InScopeSet -> TvSubstEnv -> CvSubstEnv -> TCvSubst
    TCvSubst (VarSet -> InScopeSet
    mkInScopeSet ([Coercion] -> VarSet
    shallowTyCoVarsOfCos [Coercion]
    cos)) TvSubstEnv
    emptyTvSubstEnv CvSubstEnv
    cenv
      where
        cenv :: CvSubstEnv
    cenv = [Var] -> [Coercion] -> CvSubstEnv
    HasDebugCallStack => [Var] -> [Coercion] -> CvSubstEnv
    zipCoEnv [Var]
    cvs [Coercion]
    cos

    zipTCvSubst :: HasDebugCallStack => [TyCoVar] -> [Type] -> TCvSubst
    zipTCvSubst :: HasDebugCallStack => [Var] -> [Type] -> TCvSubst
    zipTCvSubst [Var]
    tcvs [Type]
    tys
      = [Var] -> [Type] -> TCvSubst -> TCvSubst
    zip_tcvsubst [Var]
    tcvs [Type]
    tys (TCvSubst -> TCvSubst) -> TCvSubst -> TCvSubst
    forall a b. (a -> b) -> a -> b
    $
        InScopeSet -> TCvSubst
    mkEmptyTCvSubst (InScopeSet -> TCvSubst) -> InScopeSet -> TCvSubst
    forall a b. (a -> b) -> a -> b
    $ VarSet -> InScopeSet
    mkInScopeSet (VarSet -> InScopeSet) -> VarSet -> InScopeSet
    forall a b. (a -> b) -> a -> b
    $ [Type] -> VarSet
    shallowTyCoVarsOfTypes [Type]
    tys
      where zip_tcvsubst :: [TyCoVar] -> [Type] -> TCvSubst -> TCvSubst
            zip_tcvsubst :: [Var] -> [Type] -> TCvSubst -> TCvSubst
    zip_tcvsubst (Var
    tv:[Var]
    tvs) (Type
    ty:[Type]
    tys) TCvSubst
    subst
              = [Var] -> [Type] -> TCvSubst -> TCvSubst
    zip_tcvsubst [Var]
    tvs [Type]
    tys (TCvSubst -> Var -> Type -> TCvSubst
    extendTCvSubst TCvSubst
    subst Var
    tv Type
    ty)
            zip_tcvsubst [] [] TCvSubst
    subst = TCvSubst
    subst -- empty case
            zip_tcvsubst [Var]
    _  [Type]
    _  TCvSubst
    _     = String -> SDoc -> TCvSubst
    forall a. HasCallStack => String -> SDoc -> a
    pprPanic String
    "zipTCvSubst: length mismatch"
                                                ([Var] -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr [Var]
    tcvs SDoc -> SDoc -> SDoc
    <+> [Type] -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr [Type]
    tys)

    -- | Generates the in-scope set for the 'TCvSubst' from the types in the
    -- incoming environment. No CoVars, please!
    mkTvSubstPrs :: [(TyVar, Type)] -> TCvSubst
    mkTvSubstPrs :: [(Var, Type)] -> TCvSubst
    mkTvSubstPrs []  = TCvSubst
    emptyTCvSubst
    mkTvSubstPrs [(Var, Type)]
    prs =
        ASSERT2( onlyTyVarsAndNoCoercionTy, text "prs" <+> ppr prs )
        InScopeSet -> TvSubstEnv -> TCvSubst
    mkTvSubst InScopeSet
    in_scope TvSubstEnv
    tenv
      where tenv :: TvSubstEnv
    tenv = [(Var, Type)] -> TvSubstEnv
    forall a. [(Var, a)] -> VarEnv a
    mkVarEnv [(Var, Type)]
    prs
            in_scope :: InScopeSet
    in_scope = VarSet -> InScopeSet
    mkInScopeSet (VarSet -> InScopeSet) -> VarSet -> InScopeSet
    forall a b. (a -> b) -> a -> b
    $ [Type] -> VarSet
    shallowTyCoVarsOfTypes ([Type] -> VarSet) -> [Type] -> VarSet
    forall a b. (a -> b) -> a -> b
    $ ((Var, Type) -> Type) -> [(Var, Type)] -> [Type]
    forall a b. (a -> b) -> [a] -> [b]
    map (Var, Type) -> Type
    forall a b. (a, b) -> b
    snd [(Var, Type)]
    prs
            onlyTyVarsAndNoCoercionTy :: Bool
    onlyTyVarsAndNoCoercionTy =
              [Bool] -> Bool
    forall (t :: * -> *). Foldable t => t Bool -> Bool
    and [ Var -> Bool
    isTyVar Var
    tv Bool -> Bool -> Bool
    && Bool -> Bool
    not (Type -> Bool
    isCoercionTy Type
    ty)
                  | (Var
    tv, Type
    ty) <- [(Var, Type)]
    prs ]

    zipTyEnv :: HasDebugCallStack => [TyVar] -> [Type] -> TvSubstEnv
    zipTyEnv :: HasDebugCallStack => [Var] -> [Type] -> TvSubstEnv
    zipTyEnv [Var]
    tyvars [Type]
    tys
      | Bool
    debugIsOn
      , Bool -> Bool
    not ((Var -> Bool) -> [Var] -> Bool
    forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
    all Var -> Bool
    isTyVar [Var]
    tyvars Bool -> Bool -> Bool
    && ([Var]
    tyvars [Var] -> [Type] -> Bool
    forall a b. [a] -> [b] -> Bool
    `equalLength` [Type]
    tys))
      = String -> SDoc -> TvSubstEnv
    forall a. HasCallStack => String -> SDoc -> a
    pprPanic String
    "zipTyEnv" ([Var] -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr [Var]
    tyvars SDoc -> SDoc -> SDoc
    $$ [Type] -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr [Type]
    tys)
      | Bool
    otherwise
      = ASSERT( all (not . isCoercionTy) tys )
        [Var] -> [Type] -> TvSubstEnv
    forall key elt. Uniquable key => [key] -> [elt] -> UniqFM key elt
    zipToUFM [Var]
    tyvars [Type]
    tys
            -- There used to be a special case for when
            --      ty == TyVarTy tv
            -- (a not-uncommon case) in which case the substitution was dropped.
            -- But the type-tidier changes the print-name of a type variable without
            -- changing the unique, and that led to a bug.   Why?  Pre-tidying, we had
            -- a type {Foo t}, where Foo is a one-method class.  So Foo is really a newtype.
            -- And it happened that t was the type variable of the class.  Post-tiding,
            -- it got turned into {Foo t2}.  The ext-core printer expanded this using
            -- sourceTypeRep, but that said "Oh, t == t2" because they have the same unique,
            -- and so generated a rep type mentioning t not t2.
            --
            -- Simplest fix is to nuke the "optimisation"

    zipCoEnv :: HasDebugCallStack => [CoVar] -> [Coercion] -> CvSubstEnv
    zipCoEnv :: HasDebugCallStack => [Var] -> [Coercion] -> CvSubstEnv
    zipCoEnv [Var]
    cvs [Coercion]
    cos
      | Bool
    debugIsOn
      , Bool -> Bool
    not ((Var -> Bool) -> [Var] -> Bool
    forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
    all Var -> Bool
    isCoVar [Var]
    cvs)
      = String -> SDoc -> CvSubstEnv
    forall a. HasCallStack => String -> SDoc -> a
    pprPanic String
    "zipCoEnv" ([Var] -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr [Var]
    cvs SDoc -> SDoc -> SDoc
    <+> [Coercion] -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr [Coercion]
    cos)
      | Bool
    otherwise
      = [(Var, Coercion)] -> CvSubstEnv
    forall a. [(Var, a)] -> VarEnv a
    mkVarEnv (String -> [Var] -> [Coercion] -> [(Var, Coercion)]
    forall a b. String -> [a] -> [b] -> [(a, b)]
    zipEqual String
    "zipCoEnv" [Var]
    cvs [Coercion]
    cos)

    instance Outputable TCvSubst where
      ppr :: TCvSubst -> SDoc
    ppr (TCvSubst InScopeSet
    ins TvSubstEnv
    tenv CvSubstEnv
    cenv)
        = SDoc -> SDoc
    brackets (SDoc -> SDoc) -> SDoc -> SDoc
    forall a b. (a -> b) -> a -> b
    $ [SDoc] -> SDoc
    sep[ String -> SDoc
    text String
    "TCvSubst",
                          Int -> SDoc -> SDoc
    nest Int
    2 (String -> SDoc
    text String
    "In scope:" SDoc -> SDoc -> SDoc
    <+> InScopeSet -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr InScopeSet
    ins),
                          Int -> SDoc -> SDoc
    nest Int
    2 (String -> SDoc
    text String
    "Type env:" SDoc -> SDoc -> SDoc
    <+> TvSubstEnv -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr TvSubstEnv
    tenv),
                          Int -> SDoc -> SDoc
    nest Int
    2 (String -> SDoc
    text String
    "Co env:" SDoc -> SDoc -> SDoc
    <+> CvSubstEnv -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr CvSubstEnv
    cenv) ]

    {-
    %************************************************************************
    %*                                                                      *
                    Performing type or kind substitutions
    %*                                                                      *
    %************************************************************************

    Note [Sym and ForAllCo]
    ~~~~~~~~~~~~~~~~~~~~~~~
    In OptCoercion, we try to push "sym" out to the leaves of a coercion. But,
    how do we push sym into a ForAllCo? It's a little ugly.

    Here is the typing rule:

    h : k1 ~# k2
    (tv : k1) |- g : ty1 ~# ty2
    ----------------------------
    ForAllCo tv h g : (ForAllTy (tv : k1) ty1) ~#
                      (ForAllTy (tv : k2) (ty2[tv |-> tv |> sym h]))

    Here is what we want:

    ForAllCo tv h' g' : (ForAllTy (tv : k2) (ty2[tv |-> tv |> sym h])) ~#
                        (ForAllTy (tv : k1) ty1)

    Because the kinds of the type variables to the right of the colon are the kinds
    coerced by h', we know (h' : k2 ~# k1). Thus, (h' = sym h).

    Now, we can rewrite ty1 to be (ty1[tv |-> tv |> sym h' |> h']). We thus want

    ForAllCo tv h' g' :
      (ForAllTy (tv : k2) (ty2[tv |-> tv |> h'])) ~#
      (ForAllTy (tv : k1) (ty1[tv |-> tv |> h'][tv |-> tv |> sym h']))

    We thus see that we want

    g' : ty2[tv |-> tv |> h'] ~# ty1[tv |-> tv |> h']

    and thus g' = sym (g[tv |-> tv |> h']).

    Putting it all together, we get this:

    sym (ForAllCo tv h g)
    ==>
    ForAllCo tv (sym h) (sym g[tv |-> tv |> sym h])

    Note [Substituting in a coercion hole]
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    It seems highly suspicious to be substituting in a coercion that still
    has coercion holes. Yet, this can happen in a situation like this:

      f :: forall k. k :~: Type -> ()
      f Refl = let x :: forall (a :: k). [a] -> ...
                   x = ...

    When we check x's type signature, we require that k ~ Type. We indeed
    know this due to the Refl pattern match, but the eager unifier can't
    make use of givens. So, when we're done looking at x's type, a coercion
    hole will remain. Then, when we're checking x's definition, we skolemise
    x's type (in order to, e.g., bring the scoped type variable `a` into scope).
    This requires performing a substitution for the fresh skolem variables.

    This substitution needs to affect the kind of the coercion hole, too --
    otherwise, the kind will have an out-of-scope variable in it. More problematically
    in practice (we won't actually notice the out-of-scope variable ever), skolems
    in the kind might have too high a level, triggering a failure to uphold the
    invariant that no free variables in a type have a higher level than the
    ambient level in the type checker. In the event of having free variables in the
    hole's kind, I'm pretty sure we'll always have an erroneous program, so we
    don't need to worry what will happen when the hole gets filled in. After all,
    a hole relating a locally-bound type variable will be unable to be solved. This
    is why it's OK not to look through the IORef of a coercion hole during
    substitution.

    -}

    -- | Type substitution, see 'zipTvSubst'
    substTyWith :: HasCallStack => [TyVar] -> [Type] -> Type -> Type
    -- Works only if the domain of the substitution is a
    -- superset of the type being substituted into
    substTyWith :: HasCallStack => [Var] -> [Type] -> Type -> Type
    substTyWith [Var]
    tvs [Type]
    tys = {-#SCC "substTyWith" #-}
                          ASSERT( tvs `equalLength` tys )
                          HasCallStack => TCvSubst -> Type -> Type
    TCvSubst -> Type -> Type
    substTy ([Var] -> [Type] -> TCvSubst
    HasDebugCallStack => [Var] -> [Type] -> TCvSubst
    zipTvSubst [Var]
    tvs [Type]
    tys)

    -- | Type substitution, see 'zipTvSubst'. Disables sanity checks.
    -- The problems that the sanity checks in substTy catch are described in
    -- Note [The substitution invariant].
    -- The goal of #11371 is to migrate all the calls of substTyUnchecked to
    -- substTy and remove this function. Please don't use in new code.
    substTyWithUnchecked :: [TyVar] -> [Type] -> Type -> Type
    substTyWithUnchecked :: [Var] -> [Type] -> Type -> Type
    substTyWithUnchecked [Var]
    tvs [Type]
    tys
      = ASSERT( tvs `equalLength` tys )
        TCvSubst -> Type -> Type
    substTyUnchecked ([Var] -> [Type] -> TCvSubst
    HasDebugCallStack => [Var] -> [Type] -> TCvSubst
    zipTvSubst [Var]
    tvs [Type]
    tys)

    -- | Substitute tyvars within a type using a known 'InScopeSet'.
    -- Pre-condition: the 'in_scope' set should satisfy Note [The substitution
    -- invariant]; specifically it should include the free vars of 'tys',
    -- and of 'ty' minus the domain of the subst.
    substTyWithInScope :: InScopeSet -> [TyVar] -> [Type] -> Type -> Type
    substTyWithInScope :: InScopeSet -> [Var] -> [Type] -> Type -> Type
    substTyWithInScope InScopeSet
    in_scope [Var]
    tvs [Type]
    tys Type
    ty =
      ASSERT( tvs `equalLength` tys )
      HasCallStack => TCvSubst -> Type -> Type
    TCvSubst -> Type -> Type
    substTy (InScopeSet -> TvSubstEnv -> TCvSubst
    mkTvSubst InScopeSet
    in_scope TvSubstEnv
    tenv) Type
    ty
      where tenv :: TvSubstEnv
    tenv = [Var] -> [Type] -> TvSubstEnv
    HasDebugCallStack => [Var] -> [Type] -> TvSubstEnv
    zipTyEnv [Var]
    tvs [Type]
    tys

    -- | Coercion substitution, see 'zipTvSubst'
    substCoWith :: HasCallStack => [TyVar] -> [Type] -> Coercion -> Coercion
    substCoWith :: HasCallStack => [Var] -> [Type] -> Coercion -> Coercion
    substCoWith [Var]
    tvs [Type]
    tys = ASSERT( tvs `equalLength` tys )
                          HasCallStack => TCvSubst -> Coercion -> Coercion
    TCvSubst -> Coercion -> Coercion
    substCo ([Var] -> [Type] -> TCvSubst
    HasDebugCallStack => [Var] -> [Type] -> TCvSubst
    zipTvSubst [Var]
    tvs [Type]
    tys)

    -- | Coercion substitution, see 'zipTvSubst'. Disables sanity checks.
    -- The problems that the sanity checks in substCo catch are described in
    -- Note [The substitution invariant].
    -- The goal of #11371 is to migrate all the calls of substCoUnchecked to
    -- substCo and remove this function. Please don't use in new code.
    substCoWithUnchecked :: [TyVar] -> [Type] -> Coercion -> Coercion
    substCoWithUnchecked :: [Var] -> [Type] -> Coercion -> Coercion
    substCoWithUnchecked [Var]
    tvs [Type]
    tys
      = ASSERT( tvs `equalLength` tys )
        TCvSubst -> Coercion -> Coercion
    substCoUnchecked ([Var] -> [Type] -> TCvSubst
    HasDebugCallStack => [Var] -> [Type] -> TCvSubst
    zipTvSubst [Var]
    tvs [Type]
    tys)

    -- | Substitute covars within a type
    substTyWithCoVars :: [CoVar] -> [Coercion] -> Type -> Type
    substTyWithCoVars :: [Var] -> [Coercion] -> Type -> Type
    substTyWithCoVars [Var]
    cvs [Coercion]
    cos = HasCallStack => TCvSubst -> Type -> Type
    TCvSubst -> Type -> Type
    substTy ([Var] -> [Coercion] -> TCvSubst
    HasDebugCallStack => [Var] -> [Coercion] -> TCvSubst
    zipCvSubst [Var]
    cvs [Coercion]
    cos)

    -- | Type substitution, see 'zipTvSubst'
    substTysWith :: [TyVar] -> [Type] -> [Type] -> [Type]
    substTysWith :: [Var] -> [Type] -> [Type] -> [Type]
    substTysWith [Var]
    tvs [Type]
    tys = ASSERT( tvs `equalLength` tys )
                           HasCallStack => TCvSubst -> [Type] -> [Type]
    TCvSubst -> [Type] -> [Type]
    substTys ([Var] -> [Type] -> TCvSubst
    HasDebugCallStack => [Var] -> [Type] -> TCvSubst
    zipTvSubst [Var]
    tvs [Type]
    tys)

    -- | Type substitution, see 'zipTvSubst'
    substTysWithCoVars :: [CoVar] -> [Coercion] -> [Type] -> [Type]
    substTysWithCoVars :: [Var] -> [Coercion] -> [Type] -> [Type]
    substTysWithCoVars [Var]
    cvs [Coercion]
    cos = ASSERT( cvs `equalLength` cos )
                                 HasCallStack => TCvSubst -> [Type] -> [Type]
    TCvSubst -> [Type] -> [Type]
    substTys ([Var] -> [Coercion] -> TCvSubst
    HasDebugCallStack => [Var] -> [Coercion] -> TCvSubst
    zipCvSubst [Var]
    cvs [Coercion]
    cos)

    -- | Substitute within a 'Type' after adding the free variables of the type
    -- to the in-scope set. This is useful for the case when the free variables
    -- aren't already in the in-scope set or easily available.
    -- See also Note [The substitution invariant].
    substTyAddInScope :: TCvSubst -> Type -> Type
    substTyAddInScope :: TCvSubst -> Type -> Type
    substTyAddInScope TCvSubst
    subst Type
    ty =
      HasCallStack => TCvSubst -> Type -> Type
    TCvSubst -> Type -> Type
    substTy (TCvSubst -> VarSet -> TCvSubst
    extendTCvInScopeSet TCvSubst
    subst (VarSet -> TCvSubst) -> VarSet -> TCvSubst
    forall a b. (a -> b) -> a -> b
    $ Type -> VarSet
    tyCoVarsOfType Type
    ty) Type
    ty

    -- | When calling `substTy` it should be the case that the in-scope set in
    -- the substitution is a superset of the free vars of the range of the
    -- substitution.
    -- See also Note [The substitution invariant].
    isValidTCvSubst :: TCvSubst -> Bool
    isValidTCvSubst :: TCvSubst -> Bool
    isValidTCvSubst (TCvSubst InScopeSet
    in_scope TvSubstEnv
    tenv CvSubstEnv
    cenv) =
      (VarSet
    tenvFVs VarSet -> InScopeSet -> Bool
    `varSetInScope` InScopeSet
    in_scope) Bool -> Bool -> Bool
    &&
      (VarSet
    cenvFVs VarSet -> InScopeSet -> Bool
    `varSetInScope` InScopeSet
    in_scope)
      where
      tenvFVs :: VarSet
    tenvFVs = TvSubstEnv -> VarSet
    shallowTyCoVarsOfTyVarEnv TvSubstEnv
    tenv
      cenvFVs :: VarSet
    cenvFVs = CvSubstEnv -> VarSet
    shallowTyCoVarsOfCoVarEnv CvSubstEnv
    cenv

    -- | This checks if the substitution satisfies the invariant from
    -- Note [The substitution invariant].
    checkValidSubst :: HasCallStack => TCvSubst -> [Type] -> [Coercion] -> a -> a
    checkValidSubst :: forall a.
    HasCallStack =>
    TCvSubst -> [Type] -> [Coercion] -> a -> a
    checkValidSubst subst :: TCvSubst
    subst@(TCvSubst InScopeSet
    in_scope TvSubstEnv
    tenv CvSubstEnv
    cenv) [Type]
    tys [Coercion]
    cos a
    a
      = ASSERT2( isValidTCvSubst subst,
                 text "in_scope" <+> ppr in_scope $$
                 text "tenv" <+> ppr tenv $$
                 text "tenvFVs" <+> ppr (shallowTyCoVarsOfTyVarEnv tenv) $$
                 text "cenv" <+> ppr cenv $$
                 text "cenvFVs" <+> ppr (shallowTyCoVarsOfCoVarEnv cenv) $$
                 text "tys" <+> ppr tys $$
                 text "cos" <+> ppr cos )
        ASSERT2( tysCosFVsInScope,
                 text "in_scope" <+> ppr in_scope $$
                 text "tenv" <+> ppr tenv $$
                 text "cenv" <+> ppr cenv $$
                 text "tys" <+> ppr tys $$
                 text "cos" <+> ppr cos $$
                 text "needInScope" <+> ppr needInScope )
        a
    a
      where
      substDomain :: [Unique]
    substDomain = TvSubstEnv -> [Unique]
    forall key elt. UniqFM key elt -> [Unique]
    nonDetKeysUFM TvSubstEnv
    tenv [Unique] -> [Unique] -> [Unique]
    forall a. [a] -> [a] -> [a]
    ++ CvSubstEnv -> [Unique]
    forall key elt. UniqFM key elt -> [Unique]
    nonDetKeysUFM CvSubstEnv
    cenv
        -- It's OK to use nonDetKeysUFM here, because we only use this list to
        -- remove some elements from a set
      needInScope :: VarSet
    needInScope = ([Type] -> VarSet
    shallowTyCoVarsOfTypes [Type]
    tys VarSet -> VarSet -> VarSet
    `unionVarSet`
                     [Coercion] -> VarSet
    shallowTyCoVarsOfCos [Coercion]
    cos)
                    VarSet -> [Unique] -> VarSet
    forall a. UniqSet a -> [Unique] -> UniqSet a
    `delListFromUniqSet_Directly` [Unique]
    substDomain
      tysCosFVsInScope :: Bool
    tysCosFVsInScope = VarSet
    needInScope VarSet -> InScopeSet -> Bool
    `varSetInScope` InScopeSet
    in_scope

    -- | Substitute within a 'Type'
    -- The substitution has to satisfy the invariants described in
    -- Note [The substitution invariant].
    substTy :: HasCallStack => TCvSubst -> Type  -> Type
    substTy :: HasCallStack => TCvSubst -> Type -> Type
    substTy TCvSubst
    subst Type
    ty
      | TCvSubst -> Bool
    isEmptyTCvSubst TCvSubst
    subst = Type
    ty
      | Bool
    otherwise             = TCvSubst -> [Type] -> [Coercion] -> Type -> Type
    forall a.
    HasCallStack =>
    TCvSubst -> [Type] -> [Coercion] -> a -> a
    checkValidSubst TCvSubst
    subst [Type
    ty] [] (Type -> Type) -> Type -> Type
    forall a b. (a -> b) -> a -> b
    $
                                TCvSubst -> Type -> Type
    subst_ty TCvSubst
    subst Type
    ty

    -- | Substitute within a 'Type' disabling the sanity checks.
    -- The problems that the sanity checks in substTy catch are described in
    -- Note [The substitution invariant].
    -- The goal of #11371 is to migrate all the calls of substTyUnchecked to
    -- substTy and remove this function. Please don't use in new code.
    substTyUnchecked :: TCvSubst -> Type -> Type
    substTyUnchecked :: TCvSubst -> Type -> Type
    substTyUnchecked TCvSubst
    subst Type
    ty
                     | TCvSubst -> Bool
    isEmptyTCvSubst TCvSubst
    subst = Type
    ty
                     | Bool
    otherwise             = TCvSubst -> Type -> Type
    subst_ty TCvSubst
    subst Type
    ty

    substScaledTy :: HasCallStack => TCvSubst -> Scaled Type -> Scaled Type
    substScaledTy :: HasCallStack => TCvSubst -> Scaled Type -> Scaled Type
    substScaledTy TCvSubst
    subst Scaled Type
    scaled_ty = (Type -> Type) -> Scaled Type -> Scaled Type
    mapScaledType (HasCallStack => TCvSubst -> Type -> Type
    TCvSubst -> Type -> Type
    substTy TCvSubst
    subst) Scaled Type
    scaled_ty

    substScaledTyUnchecked :: HasCallStack => TCvSubst -> Scaled Type -> Scaled Type
    substScaledTyUnchecked :: HasCallStack => TCvSubst -> Scaled Type -> Scaled Type
    substScaledTyUnchecked TCvSubst
    subst Scaled Type
    scaled_ty = (Type -> Type) -> Scaled Type -> Scaled Type
    mapScaledType (TCvSubst -> Type -> Type
    substTyUnchecked TCvSubst
    subst) Scaled Type
    scaled_ty

    -- | Substitute within several 'Type's
    -- The substitution has to satisfy the invariants described in
    -- Note [The substitution invariant].
    substTys :: HasCallStack => TCvSubst -> [Type] -> [Type]
    substTys :: HasCallStack => TCvSubst -> [Type] -> [Type]
    substTys TCvSubst
    subst [Type]
    tys
      | TCvSubst -> Bool
    isEmptyTCvSubst TCvSubst
    subst = [Type]
    tys
      | Bool
    otherwise = TCvSubst -> [Type] -> [Coercion] -> [Type] -> [Type]
    forall a.
    HasCallStack =>
    TCvSubst -> [Type] -> [Coercion] -> a -> a
    checkValidSubst TCvSubst
    subst [Type]
    tys [] ([Type] -> [Type]) -> [Type] -> [Type]
    forall a b. (a -> b) -> a -> b
    $ (Type -> Type) -> [Type] -> [Type]
    forall a b. (a -> b) -> [a] -> [b]
    map (TCvSubst -> Type -> Type
    subst_ty TCvSubst
    subst) [Type]
    tys

    substScaledTys :: HasCallStack => TCvSubst -> [Scaled Type] -> [Scaled Type]
    substScaledTys :: HasCallStack => TCvSubst -> [Scaled Type] -> [Scaled Type]
    substScaledTys TCvSubst
    subst [Scaled Type]
    scaled_tys
      | TCvSubst -> Bool
    isEmptyTCvSubst TCvSubst
    subst = [Scaled Type]
    scaled_tys
      | Bool
    otherwise = TCvSubst -> [Type] -> [Coercion] -> [Scaled Type] -> [Scaled Type]
    forall a.
    HasCallStack =>
    TCvSubst -> [Type] -> [Coercion] -> a -> a
    checkValidSubst TCvSubst
    subst ((Scaled Type -> Type) -> [Scaled Type] -> [Type]
    forall a b. (a -> b) -> [a] -> [b]
    map Scaled Type -> Type
    forall a. Scaled a -> Type
    scaledMult [Scaled Type]
    scaled_tys [Type] -> [Type] -> [Type]
    forall a. [a] -> [a] -> [a]
    ++ (Scaled Type -> Type) -> [Scaled Type] -> [Type]
    forall a b. (a -> b) -> [a] -> [b]
    map Scaled Type -> Type
    forall a. Scaled a -> a
    scaledThing [Scaled Type]
    scaled_tys) [] ([Scaled Type] -> [Scaled Type]) -> [Scaled Type] -> [Scaled Type]
    forall a b. (a -> b) -> a -> b
    $
                    (Scaled Type -> Scaled Type) -> [Scaled Type] -> [Scaled Type]
    forall a b. (a -> b) -> [a] -> [b]
    map ((Type -> Type) -> Scaled Type -> Scaled Type
    mapScaledType (TCvSubst -> Type -> Type
    subst_ty TCvSubst
    subst)) [Scaled Type]
    scaled_tys

    -- | Substitute within several 'Type's disabling the sanity checks.
    -- The problems that the sanity checks in substTys catch are described in
    -- Note [The substitution invariant].
    -- The goal of #11371 is to migrate all the calls of substTysUnchecked to
    -- substTys and remove this function. Please don't use in new code.
    substTysUnchecked :: TCvSubst -> [Type] -> [Type]
    substTysUnchecked :: TCvSubst -> [Type] -> [Type]
    substTysUnchecked TCvSubst
    subst [Type]
    tys
                     | TCvSubst -> Bool
    isEmptyTCvSubst TCvSubst
    subst = [Type]
    tys
                     | Bool
    otherwise             = (Type -> Type) -> [Type] -> [Type]
    forall a b. (a -> b) -> [a] -> [b]
    map (TCvSubst -> Type -> Type
    subst_ty TCvSubst
    subst) [Type]
    tys

    substScaledTysUnchecked :: TCvSubst -> [Scaled Type] -> [Scaled Type]
    substScaledTysUnchecked :: TCvSubst -> [Scaled Type] -> [Scaled Type]
    substScaledTysUnchecked TCvSubst
    subst [Scaled Type]
    tys
                     | TCvSubst -> Bool
    isEmptyTCvSubst TCvSubst
    subst = [Scaled Type]
    tys
                     | Bool
    otherwise             = (Scaled Type -> Scaled Type) -> [Scaled Type] -> [Scaled Type]
    forall a b. (a -> b) -> [a] -> [b]
    map ((Type -> Type) -> Scaled Type -> Scaled Type
    mapScaledType (TCvSubst -> Type -> Type
    subst_ty TCvSubst
    subst)) [Scaled Type]
    tys

    -- | Substitute within a 'ThetaType'
    -- The substitution has to satisfy the invariants described in
    -- Note [The substitution invariant].
    substTheta :: HasCallStack => TCvSubst -> ThetaType -> ThetaType
    substTheta :: HasCallStack => TCvSubst -> [Type] -> [Type]
    substTheta = HasCallStack => TCvSubst -> [Type] -> [Type]
    TCvSubst -> [Type] -> [Type]
    substTys

    -- | Substitute within a 'ThetaType' disabling the sanity checks.
    -- The problems that the sanity checks in substTys catch are described in
    -- Note [The substitution invariant].
    -- The goal of #11371 is to migrate all the calls of substThetaUnchecked to
    -- substTheta and remove this function. Please don't use in new code.
    substThetaUnchecked :: TCvSubst -> ThetaType -> ThetaType
    substThetaUnchecked :: TCvSubst -> [Type] -> [Type]
    substThetaUnchecked = TCvSubst -> [Type] -> [Type]
    substTysUnchecked

    subst_ty :: TCvSubst -> Type -> Type
    -- subst_ty is the main workhorse for type substitution
    --
    -- Note that the in_scope set is poked only if we hit a forall
    -- so it may often never be fully computed
    subst_ty :: TCvSubst -> Type -> Type
    subst_ty TCvSubst
    subst Type
    ty
       = Type -> Type
    go Type
    ty
      where
        go :: Type -> Type
    go (TyVarTy Var
    tv)      = TCvSubst -> Var -> Type
    substTyVar TCvSubst
    subst Var
    tv
        go (AppTy Type
    fun Type
    arg)   = (Type -> Type -> Type
    mkAppTy (Type -> Type -> Type) -> Type -> Type -> Type
    forall a b. (a -> b) -> a -> b
    $! (Type -> Type
    go Type
    fun)) (Type -> Type) -> Type -> Type
    forall a b. (a -> b) -> a -> b
    $! (Type -> Type
    go Type
    arg)
                    -- The mkAppTy smart constructor is important
                    -- we might be replacing (a Int), represented with App
                    -- by [Int], represented with TyConApp
        go ty :: Type
    ty@(TyConApp TyCon
    tc []) = TyCon
    tc TyCon -> Type -> Type
    `seq` Type
    ty  -- avoid allocation in this common case
        go (TyConApp TyCon
    tc [Type]
    tys) = (TyCon -> [Type] -> Type
    mkTyConApp (TyCon -> [Type] -> Type) -> TyCon -> [Type] -> Type
    forall a b. (a -> b) -> a -> b
    $! TyCon
    tc) ([Type] -> Type) -> [Type] -> Type
    forall a b. (a -> b) -> a -> b
    $! (Type -> Type) -> [Type] -> [Type]
    forall a b. (a -> b) -> [a] -> [b]
    strictMap Type -> Type
    go [Type]
    tys
                                   -- NB: mkTyConApp, not TyConApp.
                                   -- mkTyConApp has optimizations.
                                   -- See Note [Prefer Type over TYPE 'LiftedRep]
                                   -- in GHC.Core.TyCo.Rep
        go ty :: Type
    ty@(FunTy { ft_mult :: Type -> Type
    ft_mult = Type
    mult, ft_arg :: Type -> Type
    ft_arg = Type
    arg, ft_res :: Type -> Type
    ft_res = Type
    res })
          = let !mult' :: Type
    mult' = Type -> Type
    go Type
    mult
                !arg' :: Type
    arg' = Type -> Type
    go Type
    arg
                !res' :: Type
    res' = Type -> Type
    go Type
    res
            in Type
    ty { ft_mult :: Type
    ft_mult = Type
    mult', ft_arg :: Type
    ft_arg = Type
    arg', ft_res :: Type
    ft_res = Type
    res' }
        go (ForAllTy (Bndr Var
    tv ArgFlag
    vis) Type
    ty)
                             = case TCvSubst -> Var -> (TCvSubst, Var)
    substVarBndrUnchecked TCvSubst
    subst Var
    tv of
                                 (TCvSubst
    subst', Var
    tv') ->
                                   (VarBndr Var ArgFlag -> Type -> Type
    ForAllTy (VarBndr Var ArgFlag -> Type -> Type)
    -> VarBndr Var ArgFlag -> Type -> Type
    forall a b. (a -> b) -> a -> b
    $! ((Var -> ArgFlag -> VarBndr Var ArgFlag
    forall var argf. var -> argf -> VarBndr var argf
    Bndr (Var -> ArgFlag -> VarBndr Var ArgFlag)
    -> Var -> ArgFlag -> VarBndr Var ArgFlag
    forall a b. (a -> b) -> a -> b
    $! Var
    tv') ArgFlag
    vis)) (Type -> Type) -> Type -> Type
    forall a b. (a -> b) -> a -> b
    $!
                                                (TCvSubst -> Type -> Type
    subst_ty TCvSubst
    subst' Type
    ty)
        go (LitTy TyLit
    n)         = TyLit -> Type
    LitTy (TyLit -> Type) -> TyLit -> Type
    forall a b. (a -> b) -> a -> b
    $! TyLit
    n
        go (CastTy Type
    ty Coercion
    co)    = (Type -> Coercion -> Type
    mkCastTy (Type -> Coercion -> Type) -> Type -> Coercion -> Type
    forall a b. (a -> b) -> a -> b
    $! (Type -> Type
    go Type
    ty)) (Coercion -> Type) -> Coercion -> Type
    forall a b. (a -> b) -> a -> b
    $! (TCvSubst -> Coercion -> Coercion
    subst_co TCvSubst
    subst Coercion
    co)
        go (CoercionTy Coercion
    co)   = Coercion -> Type
    CoercionTy (Coercion -> Type) -> Coercion -> Type
    forall a b. (a -> b) -> a -> b
    $! (TCvSubst -> Coercion -> Coercion
    subst_co TCvSubst
    subst Coercion
    co)

    substTyVar :: TCvSubst -> TyVar -> Type
    substTyVar :: TCvSubst -> Var -> Type
    substTyVar (TCvSubst InScopeSet
    _ TvSubstEnv
    tenv CvSubstEnv
    _) Var
    tv
      = ASSERT( isTyVar tv )
        case TvSubstEnv -> Var -> Maybe Type
    forall a. VarEnv a -> Var -> Maybe a
    lookupVarEnv TvSubstEnv
    tenv Var
    tv of
          Just Type
    ty -> Type
    ty
          Maybe Type
    Nothing -> Var -> Type
    TyVarTy Var
    tv

    substTyVars :: TCvSubst -> [TyVar] -> [Type]
    substTyVars :: TCvSubst -> [Var] -> [Type]
    substTyVars TCvSubst
    subst = (Var -> Type) -> [Var] -> [Type]
    forall a b. (a -> b) -> [a] -> [b]
    map ((Var -> Type) -> [Var] -> [Type])
    -> (Var -> Type) -> [Var] -> [Type]
    forall a b. (a -> b) -> a -> b
    $ TCvSubst -> Var -> Type
    substTyVar TCvSubst
    subst

    substTyCoVars :: TCvSubst -> [TyCoVar] -> [Type]
    substTyCoVars :: TCvSubst -> [Var] -> [Type]
    substTyCoVars TCvSubst
    subst = (Var -> Type) -> [Var] -> [Type]
    forall a b. (a -> b) -> [a] -> [b]
    map ((Var -> Type) -> [Var] -> [Type])
    -> (Var -> Type) -> [Var] -> [Type]
    forall a b. (a -> b) -> a -> b
    $ TCvSubst -> Var -> Type
    substTyCoVar TCvSubst
    subst

    substTyCoVar :: TCvSubst -> TyCoVar -> Type
    substTyCoVar :: TCvSubst -> Var -> Type
    substTyCoVar TCvSubst
    subst Var
    tv
      | Var -> Bool
    isTyVar Var
    tv = TCvSubst -> Var -> Type
    substTyVar TCvSubst
    subst Var
    tv
      | Bool
    otherwise = Coercion -> Type
    CoercionTy (Coercion -> Type) -> Coercion -> Type
    forall a b. (a -> b) -> a -> b
    $ TCvSubst -> Var -> Coercion
    substCoVar TCvSubst
    subst Var
    tv

    lookupTyVar :: TCvSubst -> TyVar  -> Maybe Type
            -- See Note [Extending the TCvSubst]
    lookupTyVar :: TCvSubst -> Var -> Maybe Type
    lookupTyVar (TCvSubst InScopeSet
    _ TvSubstEnv
    tenv CvSubstEnv
    _) Var
    tv
      = ASSERT( isTyVar tv )
        TvSubstEnv -> Var -> Maybe Type
    forall a. VarEnv a -> Var -> Maybe a
    lookupVarEnv TvSubstEnv
    tenv Var
    tv

    -- | Substitute within a 'Coercion'
    -- The substitution has to satisfy the invariants described in
    -- Note [The substitution invariant].
    substCo :: HasCallStack => TCvSubst -> Coercion -> Coercion
    substCo :: HasCallStack => TCvSubst -> Coercion -> Coercion
    substCo TCvSubst
    subst Coercion
    co
      | TCvSubst -> Bool
    isEmptyTCvSubst TCvSubst
    subst = Coercion
    co
      | Bool
    otherwise = TCvSubst -> [Type] -> [Coercion] -> Coercion -> Coercion
    forall a.
    HasCallStack =>
    TCvSubst -> [Type] -> [Coercion] -> a -> a
    checkValidSubst TCvSubst
    subst [] [Coercion
    co] (Coercion -> Coercion) -> Coercion -> Coercion
    forall a b. (a -> b) -> a -> b
    $ TCvSubst -> Coercion -> Coercion
    subst_co TCvSubst
    subst Coercion
    co

    -- | Substitute within a 'Coercion' disabling sanity checks.
    -- The problems that the sanity checks in substCo catch are described in
    -- Note [The substitution invariant].
    -- The goal of #11371 is to migrate all the calls of substCoUnchecked to
    -- substCo and remove this function. Please don't use in new code.
    substCoUnchecked :: TCvSubst -> Coercion -> Coercion
    substCoUnchecked :: TCvSubst -> Coercion -> Coercion
    substCoUnchecked TCvSubst
    subst Coercion
    co
      | TCvSubst -> Bool
    isEmptyTCvSubst TCvSubst
    subst = Coercion
    co
      | Bool
    otherwise = TCvSubst -> Coercion -> Coercion
    subst_co TCvSubst
    subst Coercion
    co

    -- | Substitute within several 'Coercion's
    -- The substitution has to satisfy the invariants described in
    -- Note [The substitution invariant].
    substCos :: HasCallStack => TCvSubst -> [Coercion] -> [Coercion]
    substCos :: HasCallStack => TCvSubst -> [Coercion] -> [Coercion]
    substCos TCvSubst
    subst [Coercion]
    cos
      | TCvSubst -> Bool
    isEmptyTCvSubst TCvSubst
    subst = [Coercion]
    cos
      | Bool
    otherwise = TCvSubst -> [Type] -> [Coercion] -> [Coercion] -> [Coercion]
    forall a.
    HasCallStack =>
    TCvSubst -> [Type] -> [Coercion] -> a -> a
    checkValidSubst TCvSubst
    subst [] [Coercion]
    cos ([Coercion] -> [Coercion]) -> [Coercion] -> [Coercion]
    forall a b. (a -> b) -> a -> b
    $ (Coercion -> Coercion) -> [Coercion] -> [Coercion]
    forall a b. (a -> b) -> [a] -> [b]
    map (TCvSubst -> Coercion -> Coercion
    subst_co TCvSubst
    subst) [Coercion]
    cos

    subst_co :: TCvSubst -> Coercion -> Coercion
    subst_co :: TCvSubst -> Coercion -> Coercion
    subst_co TCvSubst
    subst Coercion
    co
      = Coercion -> Coercion
    go Coercion
    co
      where
        go_ty :: Type -> Type
        go_ty :: Type -> Type
    go_ty = TCvSubst -> Type -> Type
    subst_ty TCvSubst
    subst

        go_mco :: MCoercion -> MCoercion
        go_mco :: MCoercion -> MCoercion
    go_mco MCoercion
    MRefl    = MCoercion
    MRefl
        go_mco (MCo Coercion
    co) = Coercion -> MCoercion
    MCo (Coercion -> Coercion
    go Coercion
    co)

        go :: Coercion -> Coercion
        go :: Coercion -> Coercion
    go (Refl Type
    ty)             = Type -> Coercion
    mkNomReflCo (Type -> Coercion) -> Type -> Coercion
    forall a b. (a -> b) -> a -> b
    $! (Type -> Type
    go_ty Type
    ty)
        go (GRefl Role
    r Type
    ty MCoercion
    mco)      = (Role -> Type -> MCoercion -> Coercion
    mkGReflCo Role
    r (Type -> MCoercion -> Coercion) -> Type -> MCoercion -> Coercion
    forall a b. (a -> b) -> a -> b
    $! (Type -> Type
    go_ty Type
    ty)) (MCoercion -> Coercion) -> MCoercion -> Coercion
    forall a b. (a -> b) -> a -> b
    $! (MCoercion -> MCoercion
    go_mco MCoercion
    mco)
        go (TyConAppCo Role
    r TyCon
    tc [Coercion]
    args)= let args' :: [Coercion]
    args' = (Coercion -> Coercion) -> [Coercion] -> [Coercion]
    forall a b. (a -> b) -> [a] -> [b]
    map Coercion -> Coercion
    go [Coercion]
    args
                                   in  [Coercion]
    args' [Coercion] -> Coercion -> Coercion
    forall a b. [a] -> b -> b
    `seqList` HasDebugCallStack => Role -> TyCon -> [Coercion] -> Coercion
    Role -> TyCon -> [Coercion] -> Coercion
    mkTyConAppCo Role
    r TyCon
    tc [Coercion]
    args'
        go (AppCo Coercion
    co Coercion
    arg)        = (Coercion -> Coercion -> Coercion
    mkAppCo (Coercion -> Coercion -> Coercion)
    -> Coercion -> Coercion -> Coercion
    forall a b. (a -> b) -> a -> b
    $! Coercion -> Coercion
    go Coercion
    co) (Coercion -> Coercion) -> Coercion -> Coercion
    forall a b. (a -> b) -> a -> b
    $! Coercion -> Coercion
    go Coercion
    arg
        go (ForAllCo Var
    tv Coercion
    kind_co Coercion
    co)
          = case TCvSubst -> Var -> Coercion -> (TCvSubst, Var, Coercion)
    substForAllCoBndrUnchecked TCvSubst
    subst Var
    tv Coercion
    kind_co of
             (TCvSubst
    subst', Var
    tv', Coercion
    kind_co') ->
              ((Var -> Coercion -> Coercion -> Coercion
    mkForAllCo (Var -> Coercion -> Coercion -> Coercion)
    -> Var -> Coercion -> Coercion -> Coercion
    forall a b. (a -> b) -> a -> b
    $! Var
    tv') (Coercion -> Coercion -> Coercion)
    -> Coercion -> Coercion -> Coercion
    forall a b. (a -> b) -> a -> b
    $! Coercion
    kind_co') (Coercion -> Coercion) -> Coercion -> Coercion
    forall a b. (a -> b) -> a -> b
    $! TCvSubst -> Coercion -> Coercion
    subst_co TCvSubst
    subst' Coercion
    co
        go (FunCo Role
    r Coercion
    w Coercion
    co1 Coercion
    co2)   = ((Role -> Coercion -> Coercion -> Coercion -> Coercion
    mkFunCo Role
    r (Coercion -> Coercion -> Coercion -> Coercion)
    -> Coercion -> Coercion -> Coercion -> Coercion
    forall a b. (a -> b) -> a -> b
    $! Coercion -> Coercion
    go Coercion
    w) (Coercion -> Coercion -> Coercion)
    -> Coercion -> Coercion -> Coercion
    forall a b. (a -> b) -> a -> b
    $! Coercion -> Coercion
    go Coercion
    co1) (Coercion -> Coercion) -> Coercion -> Coercion
    forall a b. (a -> b) -> a -> b
    $! Coercion -> Coercion
    go Coercion
    co2
        go (CoVarCo Var
    cv)          = TCvSubst -> Var -> Coercion
    substCoVar TCvSubst
    subst Var
    cv
        go (AxiomInstCo CoAxiom Branched
    con Int
    ind [Coercion]
    cos) = CoAxiom Branched -> Int -> [Coercion] -> Coercion
    mkAxiomInstCo CoAxiom Branched
    con Int
    ind ([Coercion] -> Coercion) -> [Coercion] -> Coercion
    forall a b. (a -> b) -> a -> b
    $! (Coercion -> Coercion) -> [Coercion] -> [Coercion]
    forall a b. (a -> b) -> [a] -> [b]
    map Coercion -> Coercion
    go [Coercion]
    cos
        go (UnivCo UnivCoProvenance
    p Role
    r Type
    t1 Type
    t2)    = (((UnivCoProvenance -> Role -> Type -> Type -> Coercion
    mkUnivCo (UnivCoProvenance -> Role -> Type -> Type -> Coercion)
    -> UnivCoProvenance -> Role -> Type -> Type -> Coercion
    forall a b. (a -> b) -> a -> b
    $! UnivCoProvenance -> UnivCoProvenance
    go_prov UnivCoProvenance
    p) (Role -> Type -> Type -> Coercion)
    -> Role -> Type -> Type -> Coercion
    forall a b. (a -> b) -> a -> b
    $! Role
    r) (Type -> Type -> Coercion) -> Type -> Type -> Coercion
    forall a b. (a -> b) -> a -> b
    $!
                                    (Type -> Type
    go_ty Type
    t1)) (Type -> Coercion) -> Type -> Coercion
    forall a b. (a -> b) -> a -> b
    $! (Type -> Type
    go_ty Type
    t2)
        go (SymCo Coercion
    co)            = Coercion -> Coercion
    mkSymCo (Coercion -> Coercion) -> Coercion -> Coercion
    forall a b. (a -> b) -> a -> b
    $! (Coercion -> Coercion
    go Coercion
    co)
        go (TransCo Coercion
    co1 Coercion
    co2)     = (Coercion -> Coercion -> Coercion
    mkTransCo (Coercion -> Coercion -> Coercion)
    -> Coercion -> Coercion -> Coercion
    forall a b. (a -> b) -> a -> b
    $! (Coercion -> Coercion
    go Coercion
    co1)) (Coercion -> Coercion) -> Coercion -> Coercion
    forall a b. (a -> b) -> a -> b
    $! (Coercion -> Coercion
    go Coercion
    co2)
        go (NthCo Role
    r Int
    d Coercion
    co)        = HasDebugCallStack => Role -> Int -> Coercion -> Coercion
    Role -> Int -> Coercion -> Coercion
    mkNthCo Role
    r Int
    d (Coercion -> Coercion) -> Coercion -> Coercion
    forall a b. (a -> b) -> a -> b
    $! (Coercion -> Coercion
    go Coercion
    co)
        go (LRCo LeftOrRight
    lr Coercion
    co)          = LeftOrRight -> Coercion -> Coercion
    mkLRCo LeftOrRight
    lr (Coercion -> Coercion) -> Coercion -> Coercion
    forall a b. (a -> b) -> a -> b
    $! (Coercion -> Coercion
    go Coercion
    co)
        go (InstCo Coercion
    co Coercion
    arg)       = (Coercion -> Coercion -> Coercion
    mkInstCo (Coercion -> Coercion -> Coercion)
    -> Coercion -> Coercion -> Coercion
    forall a b. (a -> b) -> a -> b
    $! (Coercion -> Coercion
    go Coercion
    co)) (Coercion -> Coercion) -> Coercion -> Coercion
    forall a b. (a -> b) -> a -> b
    $! Coercion -> Coercion
    go Coercion
    arg
        go (KindCo Coercion
    co)           = Coercion -> Coercion
    mkKindCo (Coercion -> Coercion) -> Coercion -> Coercion
    forall a b. (a -> b) -> a -> b
    $! (Coercion -> Coercion
    go Coercion
    co)
        go (SubCo Coercion
    co)            = HasDebugCallStack => Coercion -> Coercion
    Coercion -> Coercion
    mkSubCo (Coercion -> Coercion) -> Coercion -> Coercion
    forall a b. (a -> b) -> a -> b
    $! (Coercion -> Coercion
    go Coercion
    co)
        go (AxiomRuleCo CoAxiomRule
    c [Coercion]
    cs)    = let cs1 :: [Coercion]
    cs1 = (Coercion -> Coercion) -> [Coercion] -> [Coercion]
    forall a b. (a -> b) -> [a] -> [b]
    map Coercion -> Coercion
    go [Coercion]
    cs
                                    in [Coercion]
    cs1 [Coercion] -> Coercion -> Coercion
    forall a b. [a] -> b -> b
    `seqList` CoAxiomRule -> [Coercion] -> Coercion
    AxiomRuleCo CoAxiomRule
    c [Coercion]
    cs1
        go (HoleCo CoercionHole
    h)            = CoercionHole -> Coercion
    HoleCo (CoercionHole -> Coercion) -> CoercionHole -> Coercion
    forall a b. (a -> b) -> a -> b
    $! CoercionHole -> CoercionHole
    go_hole CoercionHole
    h

        go_prov :: UnivCoProvenance -> UnivCoProvenance
    go_prov (PhantomProv Coercion
    kco)    = Coercion -> UnivCoProvenance
    PhantomProv (Coercion -> Coercion
    go Coercion
    kco)
        go_prov (ProofIrrelProv Coercion
    kco) = Coercion -> UnivCoProvenance
    ProofIrrelProv (Coercion -> Coercion
    go Coercion
    kco)
        go_prov p :: UnivCoProvenance
    p@(PluginProv String
    _)     = UnivCoProvenance
    p
        go_prov p :: UnivCoProvenance
    p@UnivCoProvenance
    CorePrepProv       = UnivCoProvenance
    p

        -- See Note [Substituting in a coercion hole]
        go_hole :: CoercionHole -> CoercionHole
    go_hole h :: CoercionHole
    h@(CoercionHole { ch_co_var :: CoercionHole -> Var
    ch_co_var = Var
    cv })
          = CoercionHole
    h { ch_co_var :: Var
    ch_co_var = (Type -> Type) -> Var -> Var
    updateVarType Type -> Type
    go_ty Var
    cv }

    substForAllCoBndr :: TCvSubst -> TyCoVar -> KindCoercion
                      -> (TCvSubst, TyCoVar, Coercion)
    substForAllCoBndr :: TCvSubst -> Var -> Coercion -> (TCvSubst, Var, Coercion)
    substForAllCoBndr TCvSubst
    subst
      = Bool
    -> (Coercion -> Coercion)
    -> TCvSubst
    -> Var
    -> Coercion
    -> (TCvSubst, Var, Coercion)
    substForAllCoBndrUsing Bool
    False (HasCallStack => TCvSubst -> Coercion -> Coercion
    TCvSubst -> Coercion -> Coercion
    substCo TCvSubst
    subst) TCvSubst
    subst

    -- | Like 'substForAllCoBndr', but disables sanity checks.
    -- The problems that the sanity checks in substCo catch are described in
    -- Note [The substitution invariant].
    -- The goal of #11371 is to migrate all the calls of substCoUnchecked to
    -- substCo and remove this function. Please don't use in new code.
    substForAllCoBndrUnchecked :: TCvSubst -> TyCoVar -> KindCoercion
                               -> (TCvSubst, TyCoVar, Coercion)
    substForAllCoBndrUnchecked :: TCvSubst -> Var -> Coercion -> (TCvSubst, Var, Coercion)
    substForAllCoBndrUnchecked TCvSubst
    subst
      = Bool
    -> (Coercion -> Coercion)
    -> TCvSubst
    -> Var
    -> Coercion
    -> (TCvSubst, Var, Coercion)
    substForAllCoBndrUsing Bool
    False (TCvSubst -> Coercion -> Coercion
    substCoUnchecked TCvSubst
    subst) TCvSubst
    subst

    -- See Note [Sym and ForAllCo]
    substForAllCoBndrUsing :: Bool  -- apply sym to binder?
                           -> (Coercion -> Coercion)  -- transformation to kind co
                           -> TCvSubst -> TyCoVar -> KindCoercion
                           -> (TCvSubst, TyCoVar, KindCoercion)
    substForAllCoBndrUsing :: Bool
    -> (Coercion -> Coercion)
    -> TCvSubst
    -> Var
    -> Coercion
    -> (TCvSubst, Var, Coercion)
    substForAllCoBndrUsing Bool
    sym Coercion -> Coercion
    sco TCvSubst
    subst Var
    old_var
      | Var -> Bool
    isTyVar Var
    old_var = Bool
    -> (Coercion -> Coercion)
    -> TCvSubst
    -> Var
    -> Coercion
    -> (TCvSubst, Var, Coercion)
    substForAllCoTyVarBndrUsing Bool
    sym Coercion -> Coercion
    sco TCvSubst
    subst Var
    old_var
      | Bool
    otherwise       = Bool
    -> (Coercion -> Coercion)
    -> TCvSubst
    -> Var
    -> Coercion
    -> (TCvSubst, Var, Coercion)
    substForAllCoCoVarBndrUsing Bool
    sym Coercion -> Coercion
    sco TCvSubst
    subst Var
    old_var

    substForAllCoTyVarBndrUsing :: Bool  -- apply sym to binder?
                                -> (Coercion -> Coercion)  -- transformation to kind co
                                -> TCvSubst -> TyVar -> KindCoercion
                                -> (TCvSubst, TyVar, KindCoercion)
    substForAllCoTyVarBndrUsing :: Bool
    -> (Coercion -> Coercion)
    -> TCvSubst
    -> Var
    -> Coercion
    -> (TCvSubst, Var, Coercion)
    substForAllCoTyVarBndrUsing Bool
    sym Coercion -> Coercion
    sco (TCvSubst InScopeSet
    in_scope TvSubstEnv
    tenv CvSubstEnv
    cenv) Var
    old_var Coercion
    old_kind_co
      = ASSERT( isTyVar old_var )
        ( InScopeSet -> TvSubstEnv -> CvSubstEnv -> TCvSubst
    TCvSubst (InScopeSet
    in_scope InScopeSet -> Var -> InScopeSet
    `extendInScopeSet` Var
    new_var) TvSubstEnv
    new_env CvSubstEnv
    cenv
        , Var
    new_var, Coercion
    new_kind_co )
      where
        new_env :: TvSubstEnv
    new_env | Bool
    no_change Bool -> Bool -> Bool
    && Bool -> Bool
    not Bool
    sym = TvSubstEnv -> Var -> TvSubstEnv
    forall a. VarEnv a -> Var -> VarEnv a
    delVarEnv TvSubstEnv
    tenv Var
    old_var
                | Bool
    sym       = TvSubstEnv -> Var -> Type -> TvSubstEnv
    forall a. VarEnv a -> Var -> a -> VarEnv a
    extendVarEnv TvSubstEnv
    tenv Var
    old_var (Type -> TvSubstEnv) -> Type -> TvSubstEnv
    forall a b. (a -> b) -> a -> b
    $
                              Var -> Type
    TyVarTy Var
    new_var Type -> Coercion -> Type
    `CastTy` Coercion
    new_kind_co
                | Bool
    otherwise = TvSubstEnv -> Var -> Type -> TvSubstEnv
    forall a. VarEnv a -> Var -> a -> VarEnv a
    extendVarEnv TvSubstEnv
    tenv Var
    old_var (Var -> Type
    TyVarTy Var
    new_var)

        no_kind_change :: Bool
    no_kind_change = Coercion -> Bool
    noFreeVarsOfCo Coercion
    old_kind_co
        no_change :: Bool
    no_change = Bool
    no_kind_change Bool -> Bool -> Bool
    && (Var
    new_var Var -> Var -> Bool
    forall a. Eq a => a -> a -> Bool
    == Var
    old_var)

        new_kind_co :: Coercion
    new_kind_co | Bool
    no_kind_change = Coercion
    old_kind_co
                    | Bool
    otherwise      = Coercion -> Coercion
    sco Coercion
    old_kind_co

        new_ki1 :: Type
    new_ki1 = Coercion -> Type
    coercionLKind Coercion
    new_kind_co
        -- We could do substitution to (tyVarKind old_var). We don't do so because
        -- we already substituted new_kind_co, which contains the kind information
        -- we want. We don't want to do substitution once more. Also, in most cases,
        -- new_kind_co is a Refl, in which case coercionKind is really fast.

        new_var :: Var
    new_var  = InScopeSet -> Var -> Var
    uniqAway InScopeSet
    in_scope (Var -> Type -> Var
    setTyVarKind Var
    old_var Type
    new_ki1)

    substForAllCoCoVarBndrUsing :: Bool  -- apply sym to binder?
                                -> (Coercion -> Coercion)  -- transformation to kind co
                                -> TCvSubst -> CoVar -> KindCoercion
                                -> (TCvSubst, CoVar, KindCoercion)
    substForAllCoCoVarBndrUsing :: Bool
    -> (Coercion -> Coercion)
    -> TCvSubst
    -> Var
    -> Coercion
    -> (TCvSubst, Var, Coercion)
    substForAllCoCoVarBndrUsing Bool
    sym Coercion -> Coercion
    sco (TCvSubst InScopeSet
    in_scope TvSubstEnv
    tenv CvSubstEnv
    cenv)
                                Var
    old_var Coercion
    old_kind_co
      = ASSERT( isCoVar old_var )
        ( InScopeSet -> TvSubstEnv -> CvSubstEnv -> TCvSubst
    TCvSubst (InScopeSet
    in_scope InScopeSet -> Var -> InScopeSet
    `extendInScopeSet` Var
    new_var) TvSubstEnv
    tenv CvSubstEnv
    new_cenv
        , Var
    new_var, Coercion
    new_kind_co )
      where
        new_cenv :: CvSubstEnv
    new_cenv | Bool
    no_change Bool -> Bool -> Bool
    && Bool -> Bool
    not Bool
    sym = CvSubstEnv -> Var -> CvSubstEnv
    forall a. VarEnv a -> Var -> VarEnv a
    delVarEnv CvSubstEnv
    cenv Var
    old_var
                 | Bool
    otherwise = CvSubstEnv -> Var -> Coercion -> CvSubstEnv
    forall a. VarEnv a -> Var -> a -> VarEnv a
    extendVarEnv CvSubstEnv
    cenv Var
    old_var (Var -> Coercion
    mkCoVarCo Var
    new_var)

        no_kind_change :: Bool
    no_kind_change = Coercion -> Bool
    noFreeVarsOfCo Coercion
    old_kind_co
        no_change :: Bool
    no_change = Bool
    no_kind_change Bool -> Bool -> Bool
    && (Var
    new_var Var -> Var -> Bool
    forall a. Eq a => a -> a -> Bool
    == Var
    old_var)

        new_kind_co :: Coercion
    new_kind_co | Bool
    no_kind_change = Coercion
    old_kind_co
                    | Bool
    otherwise      = Coercion -> Coercion
    sco Coercion
    old_kind_co

        Pair Type
    h1 Type
    h2 = Coercion -> Pair Type
    coercionKind Coercion
    new_kind_co

        new_var :: Var
    new_var       = InScopeSet -> Var -> Var
    uniqAway InScopeSet
    in_scope (Var -> Var) -> Var -> Var
    forall a b. (a -> b) -> a -> b
    $ Name -> Type -> Var
    mkCoVar (Var -> Name
    varName Var
    old_var) Type
    new_var_type
        new_var_type :: Type
    new_var_type  | Bool
    sym       = Type
    h2
                      | Bool
    otherwise = Type
    h1

    substCoVar :: TCvSubst -> CoVar -> Coercion
    substCoVar :: TCvSubst -> Var -> Coercion
    substCoVar (TCvSubst InScopeSet
    _ TvSubstEnv
    _ CvSubstEnv
    cenv) Var
    cv
      = case CvSubstEnv -> Var -> Maybe Coercion
    forall a. VarEnv a -> Var -> Maybe a
    lookupVarEnv CvSubstEnv
    cenv Var
    cv of
          Just Coercion
    co -> Coercion
    co
          Maybe Coercion
    Nothing -> Var -> Coercion
    CoVarCo Var
    cv

    substCoVars :: TCvSubst -> [CoVar] -> [Coercion]
    substCoVars :: TCvSubst -> [Var] -> [Coercion]
    substCoVars TCvSubst
    subst [Var]
    cvs = (Var -> Coercion) -> [Var] -> [Coercion]
    forall a b. (a -> b) -> [a] -> [b]
    map (TCvSubst -> Var -> Coercion
    substCoVar TCvSubst
    subst) [Var]
    cvs

    lookupCoVar :: TCvSubst -> Var -> Maybe Coercion
    lookupCoVar :: TCvSubst -> Var -> Maybe Coercion
    lookupCoVar (TCvSubst InScopeSet
    _ TvSubstEnv
    _ CvSubstEnv
    cenv) Var
    v = CvSubstEnv -> Var -> Maybe Coercion
    forall a. VarEnv a -> Var -> Maybe a
    lookupVarEnv CvSubstEnv
    cenv Var
    v

    substTyVarBndr :: HasCallStack => TCvSubst -> TyVar -> (TCvSubst, TyVar)
    substTyVarBndr :: HasCallStack => TCvSubst -> Var -> (TCvSubst, Var)
    substTyVarBndr = (TCvSubst -> Type -> Type) -> TCvSubst -> Var -> (TCvSubst, Var)
    substTyVarBndrUsing HasCallStack => TCvSubst -> Type -> Type
    TCvSubst -> Type -> Type
    substTy

    substTyVarBndrs :: HasCallStack => TCvSubst -> [TyVar] -> (TCvSubst, [TyVar])
    substTyVarBndrs :: HasCallStack => TCvSubst -> [Var] -> (TCvSubst, [Var])
    substTyVarBndrs = (TCvSubst -> Var -> (TCvSubst, Var))
    -> TCvSubst -> [Var] -> (TCvSubst, [Var])
    forall (t :: * -> *) s a b.
    Traversable t =>
    (s -> a -> (s, b)) -> s -> t a -> (s, t b)
    mapAccumL HasCallStack => TCvSubst -> Var -> (TCvSubst, Var)
    TCvSubst -> Var -> (TCvSubst, Var)
    substTyVarBndr

    substVarBndr :: HasCallStack => TCvSubst -> TyCoVar -> (TCvSubst, TyCoVar)
    substVarBndr :: HasCallStack => TCvSubst -> Var -> (TCvSubst, Var)
    substVarBndr = (TCvSubst -> Type -> Type) -> TCvSubst -> Var -> (TCvSubst, Var)
    substVarBndrUsing HasCallStack => TCvSubst -> Type -> Type
    TCvSubst -> Type -> Type
    substTy

    substVarBndrs :: HasCallStack => TCvSubst -> [TyCoVar] -> (TCvSubst, [TyCoVar])
    substVarBndrs :: HasCallStack => TCvSubst -> [Var] -> (TCvSubst, [Var])
    substVarBndrs = (TCvSubst -> Var -> (TCvSubst, Var))
    -> TCvSubst -> [Var] -> (TCvSubst, [Var])
    forall (t :: * -> *) s a b.
    Traversable t =>
    (s -> a -> (s, b)) -> s -> t a -> (s, t b)
    mapAccumL HasCallStack => TCvSubst -> Var -> (TCvSubst, Var)
    TCvSubst -> Var -> (TCvSubst, Var)
    substVarBndr

    substCoVarBndr :: HasCallStack => TCvSubst -> CoVar -> (TCvSubst, CoVar)
    substCoVarBndr :: HasCallStack => TCvSubst -> Var -> (TCvSubst, Var)
    substCoVarBndr = (TCvSubst -> Type -> Type) -> TCvSubst -> Var -> (TCvSubst, Var)
    substCoVarBndrUsing HasCallStack => TCvSubst -> Type -> Type
    TCvSubst -> Type -> Type
    substTy

    -- | Like 'substVarBndr', but disables sanity checks.
    -- The problems that the sanity checks in substTy catch are described in
    -- Note [The substitution invariant].
    -- The goal of #11371 is to migrate all the calls of substTyUnchecked to
    -- substTy and remove this function. Please don't use in new code.
    substVarBndrUnchecked :: TCvSubst -> TyCoVar -> (TCvSubst, TyCoVar)
    substVarBndrUnchecked :: TCvSubst -> Var -> (TCvSubst, Var)
    substVarBndrUnchecked = (TCvSubst -> Type -> Type) -> TCvSubst -> Var -> (TCvSubst, Var)
    substVarBndrUsing TCvSubst -> Type -> Type
    substTyUnchecked

    substVarBndrUsing :: (TCvSubst -> Type -> Type)
                      -> TCvSubst -> TyCoVar -> (TCvSubst, TyCoVar)
    substVarBndrUsing :: (TCvSubst -> Type -> Type) -> TCvSubst -> Var -> (TCvSubst, Var)
    substVarBndrUsing TCvSubst -> Type -> Type
    subst_fn TCvSubst
    subst Var
    v
      | Var -> Bool
    isTyVar Var
    v = (TCvSubst -> Type -> Type) -> TCvSubst -> Var -> (TCvSubst, Var)
    substTyVarBndrUsing TCvSubst -> Type -> Type
    subst_fn TCvSubst
    subst Var
    v
      | Bool
    otherwise = (TCvSubst -> Type -> Type) -> TCvSubst -> Var -> (TCvSubst, Var)
    substCoVarBndrUsing TCvSubst -> Type -> Type
    subst_fn TCvSubst
    subst Var
    v

    -- | Substitute a tyvar in a binding position, returning an
    -- extended subst and a new tyvar.
    -- Use the supplied function to substitute in the kind
    substTyVarBndrUsing
      :: (TCvSubst -> Type -> Type)  -- ^ Use this to substitute in the kind
      -> TCvSubst -> TyVar -> (TCvSubst, TyVar)
    substTyVarBndrUsing :: (TCvSubst -> Type -> Type) -> TCvSubst -> Var -> (TCvSubst, Var)
    substTyVarBndrUsing TCvSubst -> Type -> Type
    subst_fn subst :: TCvSubst
    subst@(TCvSubst InScopeSet
    in_scope TvSubstEnv
    tenv CvSubstEnv
    cenv) Var
    old_var
      = ASSERT2( _no_capture, pprTyVar old_var $$ pprTyVar new_var $$ ppr subst )
        ASSERT( isTyVar old_var )
        (InScopeSet -> TvSubstEnv -> CvSubstEnv -> TCvSubst
    TCvSubst (InScopeSet
    in_scope InScopeSet -> Var -> InScopeSet
    `extendInScopeSet` Var
    new_var) TvSubstEnv
    new_env CvSubstEnv
    cenv, Var
    new_var)
      where
        new_env :: TvSubstEnv
    new_env | Bool
    no_change = TvSubstEnv -> Var -> TvSubstEnv
    forall a. VarEnv a -> Var -> VarEnv a
    delVarEnv TvSubstEnv
    tenv Var
    old_var
                | Bool
    otherwise = TvSubstEnv -> Var -> Type -> TvSubstEnv
    forall a. VarEnv a -> Var -> a -> VarEnv a
    extendVarEnv TvSubstEnv
    tenv Var
    old_var (Var -> Type
    TyVarTy Var
    new_var)

        _no_capture :: Bool
    _no_capture = Bool -> Bool
    not (Var
    new_var Var -> VarSet -> Bool
    `elemVarSet` TvSubstEnv -> VarSet
    shallowTyCoVarsOfTyVarEnv TvSubstEnv
    tenv)
        -- Assertion check that we are not capturing something in the substitution

        old_ki :: Type
    old_ki = Var -> Type
    tyVarKind Var
    old_var
        no_kind_change :: Bool
    no_kind_change = Type -> Bool
    noFreeVarsOfType Type
    old_ki -- verify that kind is closed
        no_change :: Bool
    no_change = Bool
    no_kind_change Bool -> Bool -> Bool
    && (Var
    new_var Var -> Var -> Bool
    forall a. Eq a => a -> a -> Bool
    == Var
    old_var)
            -- no_change means that the new_var is identical in
            -- all respects to the old_var (same unique, same kind)
            -- See Note [Extending the TCvSubst]
            --
            -- In that case we don't need to extend the substitution
            -- to map old to new.  But instead we must zap any
            -- current substitution for the variable. For example:
            --      (\x.e) with id_subst = [x |-> e']
            -- Here we must simply zap the substitution for x

        new_var :: Var
    new_var | Bool
    no_kind_change = InScopeSet -> Var -> Var
    uniqAway InScopeSet
    in_scope Var
    old_var
                | Bool
    otherwise = InScopeSet -> Var -> Var
    uniqAway InScopeSet
    in_scope (Var -> Var) -> Var -> Var
    forall a b. (a -> b) -> a -> b
    $
                              Var -> Type -> Var
    setTyVarKind Var
    old_var (TCvSubst -> Type -> Type
    subst_fn TCvSubst
    subst Type
    old_ki)
            -- The uniqAway part makes sure the new variable is not already in scope

    -- | Substitute a covar in a binding position, returning an
    -- extended subst and a new covar.
    -- Use the supplied function to substitute in the kind
    substCoVarBndrUsing
      :: (TCvSubst -> Type -> Type)
      -> TCvSubst -> CoVar -> (TCvSubst, CoVar)
    substCoVarBndrUsing :: (TCvSubst -> Type -> Type) -> TCvSubst -> Var -> (TCvSubst, Var)
    substCoVarBndrUsing TCvSubst -> Type -> Type
    subst_fn subst :: TCvSubst
    subst@(TCvSubst InScopeSet
    in_scope TvSubstEnv
    tenv CvSubstEnv
    cenv) Var
    old_var
      = ASSERT( isCoVar old_var )
        (InScopeSet -> TvSubstEnv -> CvSubstEnv -> TCvSubst
    TCvSubst (InScopeSet
    in_scope InScopeSet -> Var -> InScopeSet
    `extendInScopeSet` Var
    new_var) TvSubstEnv
    tenv CvSubstEnv
    new_cenv, Var
    new_var)
      where
        new_co :: Coercion
    new_co         = Var -> Coercion
    mkCoVarCo Var
    new_var
        no_kind_change :: Bool
    no_kind_change = [Type] -> Bool
    noFreeVarsOfTypes [Type
    t1, Type
    t2]
        no_change :: Bool
    no_change      = Var
    new_var Var -> Var -> Bool
    forall a. Eq a => a -> a -> Bool
    == Var
    old_var Bool -> Bool -> Bool
    && Bool
    no_kind_change

        new_cenv :: CvSubstEnv
    new_cenv | Bool
    no_change = CvSubstEnv -> Var -> CvSubstEnv
    forall a. VarEnv a -> Var -> VarEnv a
    delVarEnv CvSubstEnv
    cenv Var
    old_var
                 | Bool
    otherwise = CvSubstEnv -> Var -> Coercion -> CvSubstEnv
    forall a. VarEnv a -> Var -> a -> VarEnv a
    extendVarEnv CvSubstEnv
    cenv Var
    old_var Coercion
    new_co

        new_var :: Var
    new_var = InScopeSet -> Var -> Var
    uniqAway InScopeSet
    in_scope Var
    subst_old_var
        subst_old_var :: Var
    subst_old_var = Name -> Type -> Var
    mkCoVar (Var -> Name
    varName Var
    old_var) Type
    new_var_type

        (Type
    _, Type
    _, Type
    t1, Type
    t2, Role
    role) = HasDebugCallStack => Var -> (Type, Type, Type, Type, Role)
    Var -> (Type, Type, Type, Type, Role)
    coVarKindsTypesRole Var
    old_var
        t1' :: Type
    t1' = TCvSubst -> Type -> Type
    subst_fn TCvSubst
    subst Type
    t1
        t2' :: Type
    t2' = TCvSubst -> Type -> Type
    subst_fn TCvSubst
    subst Type
    t2
        new_var_type :: Type
    new_var_type = Role -> Type -> Type -> Type
    mkCoercionType Role
    role Type
    t1' Type
    t2'
                      -- It's important to do the substitution for coercions,
                      -- because they can have free type variables

    cloneTyVarBndr :: TCvSubst -> TyVar -> Unique -> (TCvSubst, TyVar)
    cloneTyVarBndr :: TCvSubst -> Var -> Unique -> (TCvSubst, Var)
    cloneTyVarBndr subst :: TCvSubst
    subst@(TCvSubst InScopeSet
    in_scope TvSubstEnv
    tv_env CvSubstEnv
    cv_env) Var
    tv Unique
    uniq
      = ASSERT2( isTyVar tv, ppr tv )   -- I think it's only called on TyVars
        (InScopeSet -> TvSubstEnv -> CvSubstEnv -> TCvSubst
    TCvSubst (InScopeSet -> Var -> InScopeSet
    extendInScopeSet InScopeSet
    in_scope Var
    tv')
                  (TvSubstEnv -> Var -> Type -> TvSubstEnv
    forall a. VarEnv a -> Var -> a -> VarEnv a
    extendVarEnv TvSubstEnv
    tv_env Var
    tv (Var -> Type
    mkTyVarTy Var
    tv')) CvSubstEnv
    cv_env, Var
    tv')
      where
        old_ki :: Type
    old_ki = Var -> Type
    tyVarKind Var
    tv
        no_kind_change :: Bool
    no_kind_change = Type -> Bool
    noFreeVarsOfType Type
    old_ki -- verify that kind is closed

        tv1 :: Var
    tv1 | Bool
    no_kind_change = Var
    tv
            | Bool
    otherwise      = Var -> Type -> Var
    setTyVarKind Var
    tv (HasCallStack => TCvSubst -> Type -> Type
    TCvSubst -> Type -> Type
    substTy TCvSubst
    subst Type
    old_ki)

        tv' :: Var
    tv' = Var -> Unique -> Var
    setVarUnique Var
    tv1 Unique
    uniq

    cloneTyVarBndrs :: TCvSubst -> [TyVar] -> UniqSupply -> (TCvSubst, [TyVar])
    cloneTyVarBndrs :: TCvSubst -> [Var] -> UniqSupply -> (TCvSubst, [Var])
    cloneTyVarBndrs TCvSubst
    subst []     UniqSupply
    _usupply = (TCvSubst
    subst, [])
    cloneTyVarBndrs TCvSubst
    subst (Var
    t:[Var]
    ts)  UniqSupply
    usupply = (TCvSubst
    subst'', Var
    tvVar -> [Var] -> [Var]
    forall a. a -> [a] -> [a]
    :[Var]
    tvs)
      where
        (Unique
    uniq, UniqSupply
    usupply') = UniqSupply -> (Unique, UniqSupply)
    takeUniqFromSupply UniqSupply
    usupply
        (TCvSubst
    subst' , Var
    tv )   = TCvSubst -> Var -> Unique -> (TCvSubst, Var)
    cloneTyVarBndr TCvSubst
    subst Var
    t Unique
    uniq
        (TCvSubst
    subst'', [Var]
    tvs)   = TCvSubst -> [Var] -> UniqSupply -> (TCvSubst, [Var])
    cloneTyVarBndrs TCvSubst
    subst' [Var]
    ts UniqSupply
    usupply'

    substTyCoBndr :: TCvSubst -> TyCoBinder -> (TCvSubst, TyCoBinder)
    substTyCoBndr :: TCvSubst -> TyCoBinder -> (TCvSubst, TyCoBinder)
    substTyCoBndr TCvSubst
    subst (Anon AnonArgFlag
    af Scaled Type
    ty)          = (TCvSubst
    subst, AnonArgFlag -> Scaled Type -> TyCoBinder
    Anon AnonArgFlag
    af (HasCallStack => TCvSubst -> Scaled Type -> Scaled Type
    TCvSubst -> Scaled Type -> Scaled Type
    substScaledTy TCvSubst
    subst Scaled Type
    ty))
    substTyCoBndr TCvSubst
    subst (Named (Bndr Var
    tv ArgFlag
    vis)) = (TCvSubst
    subst', VarBndr Var ArgFlag -> TyCoBinder
    Named (Var -> ArgFlag -> VarBndr Var ArgFlag
    forall var argf. var -> argf -> VarBndr var argf
    Bndr Var
    tv' ArgFlag
    vis))
                                              where
                                                (TCvSubst
    subst', Var
    tv') = HasCallStack => TCvSubst -> Var -> (TCvSubst, Var)
    TCvSubst -> Var -> (TCvSubst, Var)
    substVarBndr TCvSubst
    subst Var
    tv