    {-
    (c) The University of Glasgow 2006
    (c) The AQUA Project, Glasgow University, 1996-1998
    -}

    -- | Zonking types within the typechecker.
    --
    -- Distinct from the final zonking pass in "GHC.Tc.Zonk.Type";
    -- see Note [Module structure for zonking] in GHC.Tc.Zonk.Type.
    module GHC.Tc.Zonk.TcType
      ( -- * Zonking (within the typechecker)

        -- ** The 'ZonkM' monad and 'ZonkGblEnv'
        module GHC.Tc.Zonk.Monad

        -- ** Zonking types
      , zonkTcType, zonkTcTypes
      , zonkTcTyVar, zonkTcTyVars
      , zonkTcTyVarToTcTyVar, zonkTcTyVarsToTcTyVars
      , zonkInvisTVBinder
      , zonkCo

        -- ** Zonking 'TyCon's
      , zonkTcTyCon

        -- *** FreeVars
      , zonkTcTypeAndFV, zonkTyCoVarsAndFV, zonkTyCoVarsAndFVList
      , zonkDTyCoVarSetAndFV

        -- ** Zonking 'CoVar's and 'Id's
      , zonkId, zonkCoVar, zonkTyCoVar, zonkTyCoVarKind, zonkTyCoVarBndrKind

        -- ** Zonking skolem info
      , zonkSkolemInfo, zonkSkolemInfoAnon

        -- ** Zonking constraints
      , zonkCt, zonkWC, zonkSimples, zonkImplication

        -- * Tidying
      , tcInitTidyEnv, tcInitOpenTidyEnv
      , tidyCt, tidyEvVar, tidyDelayedError

        -- ** Zonk & tidy
      , zonkTidyTcType, zonkTidyTcTypes
      , zonkTidyOrigin, zonkTidyOrigins
      , zonkTidyFRRInfos

        -- * Writing to metavariables
      , writeMetaTyVar, writeMetaTyVarRef

        -- * Handling coercion holes
      , checkCoercionHole

      )
      where

    import GHC.Prelude

    import GHC.Types.Name
    import GHC.Types.Var
    import GHC.Types.Var.Env
    import GHC.Types.Var.Set
    import GHC.Types.Unique.Set

    import GHC.Tc.Errors.Types
    import GHC.Tc.Errors.Ppr
    import GHC.Tc.Types.Constraint
    import GHC.Tc.Types.Origin
    import GHC.Tc.Types.TcRef
    import GHC.Tc.Types.Evidence
    import GHC.Tc.Types.BasicTypes
    import GHC.Tc.Utils.TcType
    import GHC.Tc.Zonk.Monad

    import GHC.Core.InstEnv (ClsInst(is_tys))
    import GHC.Core.TyCo.Rep
    import GHC.Core.TyCon
    import GHC.Core.Type
    import GHC.Core.Coercion
    import GHC.Core.Predicate

    import GHC.Utils.Constants
    import GHC.Utils.Outputable
    import GHC.Utils.Misc
    import GHC.Utils.Monad ( mapAccumLM )
    import GHC.Utils.Panic

    import GHC.Data.Bag
    import GHC.Data.Pair

    {- *********************************************************************
    *                                                                      *
                        Writing to metavariables
    *                                                                      *
    ************************************************************************
    -}

    -- | Write into a currently-empty MetaTyVar.
    --
    -- Works with both type and kind variables.
    writeMetaTyVar :: HasDebugCallStack
                   => TcTyVar -- ^ the type varfiable to write to
                   -> TcType  -- ^ the type to write into the mutable reference
                   -> ZonkM ()
    writeMetaTyVar :: HasDebugCallStack => CoVar -> Type -> ZonkM ()
    writeMetaTyVar CoVar
    tyvar Type
    ty
      | Bool -> Bool
    not Bool
    debugIsOn
      = HasDebugCallStack => CoVar -> TcRef MetaDetails -> Type -> ZonkM ()
    CoVar -> TcRef MetaDetails -> Type -> ZonkM ()
    writeMetaTyVarRef CoVar
    tyvar (CoVar -> TcRef MetaDetails
    metaTyVarRef CoVar
    tyvar) Type
    ty

    -- Everything from here on only happens if DEBUG is on
      | Bool -> Bool
    not (CoVar -> Bool
    isTcTyVar CoVar
    tyvar)
      = Bool -> SDoc -> ZonkM ()
    forall (m :: * -> *).
    (HasCallStack, Applicative m) =>
    Bool -> SDoc -> m ()
    massertPpr Bool
    False (String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "Writing to non-tc tyvar" SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> CoVar -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr CoVar
    tyvar)

      | MetaTv { mtv_ref :: TcTyVarDetails -> TcRef MetaDetails
    mtv_ref = TcRef MetaDetails
    ref } <- CoVar -> TcTyVarDetails
    tcTyVarDetails CoVar
    tyvar
      = HasDebugCallStack => CoVar -> TcRef MetaDetails -> Type -> ZonkM ()
    CoVar -> TcRef MetaDetails -> Type -> ZonkM ()
    writeMetaTyVarRef CoVar
    tyvar TcRef MetaDetails
    ref Type
    ty

      | Bool
    otherwise
      = Bool -> SDoc -> ZonkM ()
    forall (m :: * -> *).
    (HasCallStack, Applicative m) =>
    Bool -> SDoc -> m ()
    massertPpr Bool
    False (String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "Writing to non-meta tyvar" SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> CoVar -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr CoVar
    tyvar)
    {-# INLINE writeMetaTyVar #-} -- See NOTE [Inlining writeMetaTyVar]

    -- | Write into the 'MetaDetails' mutable references of a 'MetaTv'.
    writeMetaTyVarRef :: HasDebugCallStack
                      => TcTyVar -- ^ for debug assertions only;
                      -> TcRef MetaDetails -- ^ ref cell must be for the same tyvar
                      -> TcType -- ^ the type to write to the mutable reference
                      -> ZonkM ()
    writeMetaTyVarRef :: HasDebugCallStack => CoVar -> TcRef MetaDetails -> Type -> ZonkM ()
    writeMetaTyVarRef CoVar
    tyvar TcRef MetaDetails
    ref Type
    ty
      | Bool -> Bool
    not Bool
    debugIsOn
      = do { String -> SDoc -> ZonkM ()
    traceZonk String
    "writeMetaTyVar" (CoVar -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr CoVar
    tyvar SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> SDoc
    dcolon SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> Type -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr (CoVar -> Type
    tyVarKind CoVar
    tyvar)
                                         SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    ":=" SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> Type -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr Type
    ty)
           ; TcRef MetaDetails -> MetaDetails -> ZonkM ()
    forall (m :: * -> *) a. MonadIO m => TcRef a -> a -> m ()
    writeTcRef TcRef MetaDetails
    ref (Type -> MetaDetails
    Indirect Type
    ty) }

      -- Everything from here on only happens if DEBUG is on
      -- Need to zonk 'ty' because we may only recently have promoted
      -- its free meta-tyvars (see GHC.Tc.Utils.Unify.checkPromoteFreeVars)
      | Bool
    otherwise
      = do { meta_details <- TcRef MetaDetails -> ZonkM MetaDetails
    forall (m :: * -> *) a. MonadIO m => TcRef a -> m a
    readTcRef TcRef MetaDetails
    ref;
           -- Zonk kinds to allow the error check to work
           ; zonked_tv_kind <- zonkTcType tv_kind
           ; zonked_ty      <- zonkTcType ty
           ; let zonked_ty_kind = HasDebugCallStack => Type -> Type
    Type -> Type
    typeKind Type
    zonked_ty
                 zonked_ty_lvl  = Type -> TcLevel
    tcTypeLevel Type
    zonked_ty
                 level_check_ok  = Bool -> Bool
    not (TcLevel
    zonked_ty_lvl TcLevel -> TcLevel -> Bool
    `strictlyDeeperThan` TcLevel
    tv_lvl)
                 level_check_msg = TcLevel -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr TcLevel
    zonked_ty_lvl SDoc -> SDoc -> SDoc
    forall doc. IsDoc doc => doc -> doc -> doc
    $$ TcLevel -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr TcLevel
    tv_lvl SDoc -> SDoc -> SDoc
    forall doc. IsDoc doc => doc -> doc -> doc
    $$ CoVar -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr CoVar
    tyvar SDoc -> SDoc -> SDoc
    forall doc. IsDoc doc => doc -> doc -> doc
    $$ Type -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr Type
    ty SDoc -> SDoc -> SDoc
    forall doc. IsDoc doc => doc -> doc -> doc
    $$ Type -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr Type
    zonked_ty
                 kind_check_ok = Type
    zonked_ty_kind Type -> Type -> Bool
    `eqType` Type
    zonked_tv_kind
                 -- Note [Extra-constraint holes in partial type signatures] in GHC.Tc.Gen.HsType

                 kind_msg = SDoc -> Int -> SDoc -> SDoc
    hang (String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "Ill-kinded update to meta tyvar")
                               Int
    2 (    CoVar -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr CoVar
    tyvar SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "::" SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> (Type -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr Type
    tv_kind SDoc -> SDoc -> SDoc
    forall doc. IsDoc doc => doc -> doc -> doc
    $$ Type -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr Type
    zonked_tv_kind)
                                  SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    ":="
                                  SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> Type -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr Type
    ty SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "::" SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> (Type -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr Type
    zonked_ty_kind) )

           ; traceZonk "writeMetaTyVar" (ppr tyvar <+> text ":=" <+> ppr ty)

           -- Check for double updates
           ; massertPpr (isFlexi meta_details) (double_upd_msg meta_details)

           -- Check for level OK
           ; massertPpr level_check_ok level_check_msg

           -- Check Kinds ok
           ; massertPpr kind_check_ok kind_msg

           -- Do the write
           ; writeTcRef ref (Indirect ty) }
      where
        tv_kind :: Type
    tv_kind = CoVar -> Type
    tyVarKind CoVar
    tyvar

        tv_lvl :: TcLevel
    tv_lvl = CoVar -> TcLevel
    tcTyVarLevel CoVar
    tyvar

        double_upd_msg :: MetaDetails -> SDoc
    double_upd_msg MetaDetails
    details = SDoc -> Int -> SDoc -> SDoc
    hang (String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "Double update of meta tyvar")
                                    Int
    2 (CoVar -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr CoVar
    tyvar SDoc -> SDoc -> SDoc
    forall doc. IsDoc doc => doc -> doc -> doc
    $$ MetaDetails -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr MetaDetails
    details)
    {-# INLINE writeMetaTyVarRef #-} -- See NOTE [Inlining writeMetaTyVar]

    {- NOTE [Inlining writeMetaTyVar]
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    writeMetaTyVar is defined in the ZonkM monad, but it is often used within
    TcM with the following idiom:

      liftZonkM $ writeMetaTyVar tv ty

    Using liftZonkM within TcM generally means extracting out a ZonkGblEnv
    from the TcM monad to pass to the inner ZonkM computation (see the definition
    of liftZonkM). This can cause writeMetaTyVar to allocate a ZonkGblEnv, which we
    would much rather avoid!
    Instead, we should directly pass the bits of the ZonkGblEnv that writeMetaTyVar
    needs (the Logger and NamePprCtxt, which are needed for the traceZonk call
    in writeMetaTyVar). This is achieved by inlining writeMetaTyVar and writeMetaTyVarRef.
    These functions just wrap writeTcRef, with some extra tracing
    (and some assertions if running in debug mode), so it's fine to inline them.

    See for example test T5631, which regresses without this change.
    -}

    {-
    ************************************************************************
    *                                                                      *
         Zonking -- the main work-horses: zonkTcType, zonkTcTyVar
    *                                                                      *
    ************************************************************************
    -}

    -- For unbound, mutable tyvars, zonkType uses the function given to it
    -- For tyvars bound at a for-all, zonkType zonks them to an immutable
    --      type variable and zonks the kind too
    zonkTcType  :: TcType   -> ZonkM TcType
    zonkTcTypes :: [TcType] -> ZonkM [TcType]
    zonkCo      :: Coercion -> ZonkM Coercion
    (Type -> ZonkM Type
    zonkTcType, [Type] -> ZonkM [Type]
    zonkTcTypes, Coercion -> ZonkM Coercion
    zonkCo, [Coercion] -> ZonkM [Coercion]
    _)
      = TyCoMapper () ZonkM
    -> (Type -> ZonkM Type, [Type] -> ZonkM [Type],
        Coercion -> ZonkM Coercion, [Coercion] -> ZonkM [Coercion])
    forall (m :: * -> *).
    Monad m =>
    TyCoMapper () m
    -> (Type -> m Type, [Type] -> m [Type], Coercion -> m Coercion,
        [Coercion] -> m [Coercion])
    mapTyCo TyCoMapper () ZonkM
    zonkTcTypeMapper

    -- | A suitable TyCoMapper for zonking a type during type-checking,
    -- before all metavars are filled in.
    zonkTcTypeMapper :: TyCoMapper () ZonkM
    zonkTcTypeMapper :: TyCoMapper () ZonkM
    zonkTcTypeMapper = TyCoMapper
      { tcm_tyvar :: () -> CoVar -> ZonkM Type
    tcm_tyvar = (CoVar -> ZonkM Type) -> () -> CoVar -> ZonkM Type
    forall a b. a -> b -> a
    const CoVar -> ZonkM Type
    zonkTcTyVar
      , tcm_covar :: () -> CoVar -> ZonkM Coercion
    tcm_covar = (CoVar -> ZonkM Coercion) -> () -> CoVar -> ZonkM Coercion
    forall a b. a -> b -> a
    const (\CoVar
    cv -> CoVar -> Coercion
    mkCoVarCo (CoVar -> Coercion) -> ZonkM CoVar -> ZonkM Coercion
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> CoVar -> ZonkM CoVar
    zonkTyCoVarKind CoVar
    cv)
      , tcm_hole :: () -> CoercionHole -> ZonkM Coercion
    tcm_hole  = () -> CoercionHole -> ZonkM Coercion
    hole
      , tcm_tycobinder :: forall r.
    () -> CoVar -> ForAllTyFlag -> (() -> CoVar -> ZonkM r) -> ZonkM r
    tcm_tycobinder = \ ()
    _env CoVar
    tcv ForAllTyFlag
    _vis () -> CoVar -> ZonkM r
    k -> CoVar -> ZonkM CoVar
    zonkTyCoVarKind CoVar
    tcv ZonkM CoVar -> (CoVar -> ZonkM r) -> ZonkM r
    forall a b. ZonkM a -> (a -> ZonkM b) -> ZonkM b
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= () -> CoVar -> ZonkM r
    k ()
      , tcm_tycon :: TyCon -> ZonkM TyCon
    tcm_tycon      = TyCon -> ZonkM TyCon
    zonkTcTyCon }
      where
        hole :: () -> CoercionHole -> ZonkM Coercion
        hole :: () -> CoercionHole -> ZonkM Coercion
    hole ()
    _ hole :: CoercionHole
    hole@(CoercionHole { ch_ref :: CoercionHole -> IORef (Maybe Coercion)
    ch_ref = IORef (Maybe Coercion)
    ref, ch_co_var :: CoercionHole -> CoVar
    ch_co_var = CoVar
    cv })
          = do { contents <- IORef (Maybe Coercion) -> ZonkM (Maybe Coercion)
    forall (m :: * -> *) a. MonadIO m => TcRef a -> m a
    readTcRef IORef (Maybe Coercion)
    ref
               ; case contents of
                   Just Coercion
    co -> do { co' <- Coercion -> ZonkM Coercion
    zonkCo Coercion
    co
                                 ; checkCoercionHole cv co' }
                   Maybe Coercion
    Nothing -> do { cv' <- CoVar -> ZonkM CoVar
    zonkCoVar CoVar
    cv
                                 ; return $ HoleCo (hole { ch_co_var = cv' }) } }

    zonkTcTyCon :: TcTyCon -> ZonkM TcTyCon
    -- Only called on TcTyCons
    -- A non-poly TcTyCon may have unification
    -- variables that need zonking, but poly ones cannot
    zonkTcTyCon :: TyCon -> ZonkM TyCon
    zonkTcTyCon TyCon
    tc
     | TyCon -> Bool
    isMonoTcTyCon TyCon
    tc = do { tck' <- Type -> ZonkM Type
    zonkTcType (TyCon -> Type
    tyConKind TyCon
    tc)
                             ; return (setTcTyConKind tc tck') }
     | Bool
    otherwise        = TyCon -> ZonkM TyCon
    forall a. a -> ZonkM a
    forall (m :: * -> *) a. Monad m => a -> m a
    return TyCon
    tc

    zonkTcTyVar :: TcTyVar -> ZonkM TcType
    -- Simply look through all Flexis
    zonkTcTyVar :: CoVar -> ZonkM Type
    zonkTcTyVar CoVar
    tv
      | CoVar -> Bool
    isTcTyVar CoVar
    tv
      = case CoVar -> TcTyVarDetails
    tcTyVarDetails CoVar
    tv of
          SkolemTv {}   -> ZonkM Type
    zonk_kind_and_return
          RuntimeUnk {} -> ZonkM Type
    zonk_kind_and_return
          MetaTv { mtv_ref :: TcTyVarDetails -> TcRef MetaDetails
    mtv_ref = TcRef MetaDetails
    ref }
             -> do { cts <- TcRef MetaDetails -> ZonkM MetaDetails
    forall (m :: * -> *) a. MonadIO m => TcRef a -> m a
    readTcRef TcRef MetaDetails
    ref
                   ; case cts of
                        MetaDetails
    Flexi       -> ZonkM Type
    zonk_kind_and_return
                        Indirect Type
    ty -> do { zty <- Type -> ZonkM Type
    zonkTcType Type
    ty
                                          ; writeTcRef ref (Indirect zty)
                                            -- See Note [Sharing in zonking]
                                          ; return zty } }

      | Bool
    otherwise -- coercion variable
      = ZonkM Type
    zonk_kind_and_return
      where
        zonk_kind_and_return :: ZonkM Type
    zonk_kind_and_return = do { z_tv <- CoVar -> ZonkM CoVar
    zonkTyCoVarKind CoVar
    tv
                                  ; return (mkTyVarTy z_tv) }

    -- Variant that assumes that any result of zonking is still a TyVar.
    -- Should be used only on skolems and TyVarTvs
    zonkTcTyVarsToTcTyVars :: HasDebugCallStack => [TcTyVar] -> ZonkM [TcTyVar]
    zonkTcTyVarsToTcTyVars :: HasDebugCallStack => [CoVar] -> ZonkM [CoVar]
    zonkTcTyVarsToTcTyVars = (CoVar -> ZonkM CoVar) -> [CoVar] -> ZonkM [CoVar]
    forall (t :: * -> *) (m :: * -> *) a b.
    (Traversable t, Monad m) =>
    (a -> m b) -> t a -> m (t b)
    forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [b]
    mapM HasDebugCallStack => CoVar -> ZonkM CoVar
    CoVar -> ZonkM CoVar
    zonkTcTyVarToTcTyVar

    zonkTcTyVarToTcTyVar :: HasDebugCallStack => TcTyVar -> ZonkM TcTyVar
    zonkTcTyVarToTcTyVar :: HasDebugCallStack => CoVar -> ZonkM CoVar
    zonkTcTyVarToTcTyVar CoVar
    tv
      = do { ty <- CoVar -> ZonkM Type
    zonkTcTyVar CoVar
    tv
           ; let tv' = case Type -> Maybe CoVar
    getTyVar_maybe Type
    ty of
                         Just CoVar
    tv' -> CoVar
    tv'
                         Maybe CoVar
    Nothing  -> String -> SDoc -> CoVar
    forall a. HasCallStack => String -> SDoc -> a
    pprPanic String
    "zonkTcTyVarToTcTyVar"
                                              (CoVar -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr CoVar
    tv SDoc -> SDoc -> SDoc
    forall doc. IsDoc doc => doc -> doc -> doc
    $$ Type -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr Type
    ty)
           ; return tv' }

    zonkInvisTVBinder :: VarBndr TcTyVar spec -> ZonkM (VarBndr TcTyVar spec)
    zonkInvisTVBinder :: forall spec. VarBndr CoVar spec -> ZonkM (VarBndr CoVar spec)
    zonkInvisTVBinder (Bndr CoVar
    tv spec
    spec) = do { tv' <- HasDebugCallStack => CoVar -> ZonkM CoVar
    CoVar -> ZonkM CoVar
    zonkTcTyVarToTcTyVar CoVar
    tv
                                          ; return (Bndr tv' spec) }

    {- *********************************************************************
    *                                                                      *
                  Zonking types
    *                                                                      *
    ********************************************************************* -}

    zonkTcTypeAndFV :: TcType -> ZonkM DTyCoVarSet
    -- Zonk a type and take its free variables
    -- With kind polymorphism it can be essential to zonk *first*
    -- so that we find the right set of free variables.  Eg
    --    forall k1. forall (a:k2). a
    -- where k2:=k1 is in the substitution.  We don't want
    -- k2 to look free in this type!
    zonkTcTypeAndFV :: Type -> ZonkM DTyCoVarSet
    zonkTcTypeAndFV Type
    ty
      = Type -> DTyCoVarSet
    tyCoVarsOfTypeDSet (Type -> DTyCoVarSet) -> ZonkM Type -> ZonkM DTyCoVarSet
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Type -> ZonkM Type
    zonkTcType Type
    ty

    zonkTyCoVar :: TyCoVar -> ZonkM TcType
    -- Works on TyVars and TcTyVars
    zonkTyCoVar :: CoVar -> ZonkM Type
    zonkTyCoVar CoVar
    tv | CoVar -> Bool
    isTcTyVar CoVar
    tv = CoVar -> ZonkM Type
    zonkTcTyVar CoVar
    tv
                   | CoVar -> Bool
    isTyVar   CoVar
    tv = CoVar -> Type
    mkTyVarTy (CoVar -> Type) -> ZonkM CoVar -> ZonkM Type
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> CoVar -> ZonkM CoVar
    zonkTyCoVarKind CoVar
    tv
                   | Bool
    otherwise    = Bool -> SDoc -> ZonkM Type -> ZonkM Type
    forall a. HasCallStack => Bool -> SDoc -> a -> a
    assertPpr (CoVar -> Bool
    isCoVar CoVar
    tv) (CoVar -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr CoVar
    tv) (ZonkM Type -> ZonkM Type) -> ZonkM Type -> ZonkM Type
    forall a b. (a -> b) -> a -> b
    $
                                    Coercion -> Type
    mkCoercionTy (Coercion -> Type) -> (CoVar -> Coercion) -> CoVar -> Type
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . CoVar -> Coercion
    mkCoVarCo (CoVar -> Type) -> ZonkM CoVar -> ZonkM Type
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> CoVar -> ZonkM CoVar
    zonkTyCoVarKind CoVar
    tv
       -- Hackily, when typechecking type and class decls
       -- we have TyVars in scope added (only) in
       -- GHC.Tc.Gen.HsType.bindTyClTyVars, but it seems
       -- painful to make them into TcTyVars there

    zonkTyCoVarsAndFV :: TyCoVarSet -> ZonkM TyCoVarSet
    zonkTyCoVarsAndFV :: TyCoVarSet -> ZonkM TyCoVarSet
    zonkTyCoVarsAndFV TyCoVarSet
    tycovars
      = [Type] -> TyCoVarSet
    tyCoVarsOfTypes ([Type] -> TyCoVarSet) -> ZonkM [Type] -> ZonkM TyCoVarSet
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> (CoVar -> ZonkM Type) -> [CoVar] -> ZonkM [Type]
    forall (t :: * -> *) (m :: * -> *) a b.
    (Traversable t, Monad m) =>
    (a -> m b) -> t a -> m (t b)
    forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [b]
    mapM CoVar -> ZonkM Type
    zonkTyCoVar (TyCoVarSet -> [CoVar]
    forall elt. UniqSet elt -> [elt]
    nonDetEltsUniqSet TyCoVarSet
    tycovars)
      -- It's OK to use nonDetEltsUniqSet here because we immediately forget about
      -- the ordering by turning it into a nondeterministic set and the order
      -- of zonking doesn't matter for determinism.

    zonkDTyCoVarSetAndFV :: DTyCoVarSet -> ZonkM DTyCoVarSet
    zonkDTyCoVarSetAndFV :: DTyCoVarSet -> ZonkM DTyCoVarSet
    zonkDTyCoVarSetAndFV DTyCoVarSet
    tycovars
      = [CoVar] -> DTyCoVarSet
    mkDVarSet ([CoVar] -> DTyCoVarSet) -> ZonkM [CoVar] -> ZonkM DTyCoVarSet
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> ([CoVar] -> ZonkM [CoVar]
    zonkTyCoVarsAndFVList ([CoVar] -> ZonkM [CoVar]) -> [CoVar] -> ZonkM [CoVar]
    forall a b. (a -> b) -> a -> b
    $ DTyCoVarSet -> [CoVar]
    dVarSetElems DTyCoVarSet
    tycovars)

    -- Takes a list of TyCoVars, zonks them and returns a
    -- deterministically ordered list of their free variables.
    zonkTyCoVarsAndFVList :: [TyCoVar] -> ZonkM [TyCoVar]
    zonkTyCoVarsAndFVList :: [CoVar] -> ZonkM [CoVar]
    zonkTyCoVarsAndFVList [CoVar]
    tycovars
      = [Type] -> [CoVar]
    tyCoVarsOfTypesList ([Type] -> [CoVar]) -> ZonkM [Type] -> ZonkM [CoVar]
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> (CoVar -> ZonkM Type) -> [CoVar] -> ZonkM [Type]
    forall (t :: * -> *) (m :: * -> *) a b.
    (Traversable t, Monad m) =>
    (a -> m b) -> t a -> m (t b)
    forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [b]
    mapM CoVar -> ZonkM Type
    zonkTyCoVar [CoVar]
    tycovars

    zonkTcTyVars :: [TcTyVar] -> ZonkM [TcType]
    zonkTcTyVars :: [CoVar] -> ZonkM [Type]
    zonkTcTyVars [CoVar]
    tyvars = (CoVar -> ZonkM Type) -> [CoVar] -> ZonkM [Type]
    forall (t :: * -> *) (m :: * -> *) a b.
    (Traversable t, Monad m) =>
    (a -> m b) -> t a -> m (t b)
    forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [b]
    mapM CoVar -> ZonkM Type
    zonkTcTyVar [CoVar]
    tyvars

    -----------------  Types
    zonkTyCoVarKind :: TyCoVar -> ZonkM TyCoVar
    zonkTyCoVarKind :: CoVar -> ZonkM CoVar
    zonkTyCoVarKind CoVar
    tv = do { kind' <- Type -> ZonkM Type
    zonkTcType (CoVar -> Type
    tyVarKind CoVar
    tv)
                            ; return (setTyVarKind tv kind') }

    zonkTyCoVarBndrKind :: VarBndr TyCoVar flag -> ZonkM (VarBndr TyCoVar flag)
    zonkTyCoVarBndrKind :: forall spec. VarBndr CoVar spec -> ZonkM (VarBndr CoVar spec)
    zonkTyCoVarBndrKind (Bndr CoVar
    tv flag
    flag) =
      do { tv' <- CoVar -> ZonkM CoVar
    zonkTyCoVarKind CoVar
    tv
         ; return (Bndr tv' flag) }

    -- | zonkId is used *during* typechecking just to zonk the 'Id''s type
    zonkId :: TcId -> ZonkM TcId
    zonkId :: CoVar -> ZonkM CoVar
    zonkId CoVar
    id = (Type -> ZonkM Type) -> CoVar -> ZonkM CoVar
    forall (m :: * -> *).
    Monad m =>
    (Type -> m Type) -> CoVar -> m CoVar
    updateIdTypeAndMultM Type -> ZonkM Type
    zonkTcType CoVar
    id

    zonkCoVar :: CoVar -> ZonkM CoVar
    zonkCoVar :: CoVar -> ZonkM CoVar
    zonkCoVar = CoVar -> ZonkM CoVar
    zonkId

    {-
    ************************************************************************
    *                                                                      *
            Coercion holes
    *                                                                      *
    ************************************************************************
    -}

    -- | Check that a coercion is appropriate for filling a hole. (The hole
    -- itself is needed only for printing.)
    -- Always returns the checked coercion, but this return value is necessary
    -- so that the input coercion is forced only when the output is forced.
    checkCoercionHole :: CoVar -> Coercion -> ZonkM Coercion
    checkCoercionHole :: CoVar -> Coercion -> ZonkM Coercion
    checkCoercionHole CoVar
    cv Coercion
    co
      | Bool
    debugIsOn
      = do { cv_ty <- Type -> ZonkM Type
    zonkTcType (CoVar -> Type
    varType CoVar
    cv)
                      -- co is already zonked, but cv might not be
           ; return $
             assertPpr (ok cv_ty)
                       (text "Bad coercion hole" <+>
                        ppr cv <> colon <+> vcat [ ppr t1, ppr t2, ppr role
                                                 , ppr cv_ty ])
             co }
      | Bool
    otherwise
      = Coercion -> ZonkM Coercion
    forall a. a -> ZonkM a
    forall (m :: * -> *) a. Monad m => a -> m a
    return Coercion
    co

      where
        (Pair Type
    t1 Type
    t2, Role
    role) = Coercion -> (Pair Type, Role)
    coercionKindRole Coercion
    co
        ok :: Type -> Bool
    ok Type
    cv_ty | EqPred EqRel
    cv_rel Type
    cv_t1 Type
    cv_t2 <- Type -> Pred
    classifyPredType Type
    cv_ty
                 =  Type
    t1 Type -> Type -> Bool
    `eqType` Type
    cv_t1
                 Bool -> Bool -> Bool
    && Type
    t2 Type -> Type -> Bool
    `eqType` Type
    cv_t2
                 Bool -> Bool -> Bool
    && Role
    role Role -> Role -> Bool
    forall a. Eq a => a -> a -> Bool
    == EqRel -> Role
    eqRelRole EqRel
    cv_rel
                 | Bool
    otherwise
                 = Bool
    False

    {-
    ************************************************************************
    *                                                                      *
                  Zonking constraints
    *                                                                      *
    ************************************************************************
    -}

    zonkImplication :: Implication -> ZonkM Implication
    zonkImplication :: Implication -> ZonkM Implication
    zonkImplication implic :: Implication
    implic@(Implic { ic_skols :: Implication -> [CoVar]
    ic_skols  = [CoVar]
    skols
                                   , ic_given :: Implication -> [CoVar]
    ic_given  = [CoVar]
    given
                                   , ic_wanted :: Implication -> WantedConstraints
    ic_wanted = WantedConstraints
    wanted
                                   , ic_info :: Implication -> SkolemInfoAnon
    ic_info   = SkolemInfoAnon
    info })
      = do { skols'  <- (CoVar -> ZonkM CoVar) -> [CoVar] -> ZonkM [CoVar]
    forall (t :: * -> *) (m :: * -> *) a b.
    (Traversable t, Monad m) =>
    (a -> m b) -> t a -> m (t b)
    forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [b]
    mapM CoVar -> ZonkM CoVar
    zonkTyCoVarKind [CoVar]
    skols  -- Need to zonk their kinds!
                                                    -- as #7230 showed
           ; given'  <- mapM zonkEvVar given
           ; info'   <- zonkSkolemInfoAnon info
           ; wanted' <- zonkWCRec wanted
           ; return (implic { ic_skols  = skols'
                            , ic_given  = given'
                            , ic_wanted = wanted'
                            , ic_info   = info' }) }

    zonkEvVar :: EvVar -> ZonkM EvVar
    zonkEvVar :: CoVar -> ZonkM CoVar
    zonkEvVar CoVar
    var = (Type -> ZonkM Type) -> CoVar -> ZonkM CoVar
    forall (m :: * -> *).
    Monad m =>
    (Type -> m Type) -> CoVar -> m CoVar
    updateIdTypeAndMultM Type -> ZonkM Type
    zonkTcType CoVar
    var

    zonkWC :: WantedConstraints -> ZonkM WantedConstraints
    zonkWC :: WantedConstraints -> ZonkM WantedConstraints
    zonkWC WantedConstraints
    wc = WantedConstraints -> ZonkM WantedConstraints
    zonkWCRec WantedConstraints
    wc

    zonkWCRec :: WantedConstraints -> ZonkM WantedConstraints
    zonkWCRec :: WantedConstraints -> ZonkM WantedConstraints
    zonkWCRec (WC { wc_simple :: WantedConstraints -> Bag Ct
    wc_simple = Bag Ct
    simple, wc_impl :: WantedConstraints -> Bag Implication
    wc_impl = Bag Implication
    implic, wc_errors :: WantedConstraints -> Bag DelayedError
    wc_errors = Bag DelayedError
    errs })
      = do { simple' <- Bag Ct -> ZonkM (Bag Ct)
    zonkSimples Bag Ct
    simple
           ; implic' <- mapBagM zonkImplication implic
           ; errs'   <- mapBagM zonkDelayedError errs
           ; return (WC { wc_simple = simple', wc_impl = implic', wc_errors = errs' }) }

    zonkSimples :: Cts -> ZonkM Cts
    zonkSimples :: Bag Ct -> ZonkM (Bag Ct)
    zonkSimples Bag Ct
    cts = do { cts' <- (Ct -> ZonkM Ct) -> Bag Ct -> ZonkM (Bag Ct)
    forall (m :: * -> *) a b.
    Monad m =>
    (a -> m b) -> Bag a -> m (Bag b)
    mapBagM Ct -> ZonkM Ct
    zonkCt Bag Ct
    cts
                         ; traceZonk "zonkSimples done:" (ppr cts')
                         ; return cts' }

    zonkDelayedError :: DelayedError -> ZonkM DelayedError
    zonkDelayedError :: DelayedError -> ZonkM DelayedError
    zonkDelayedError (DE_Hole Hole
    hole)
      = Hole -> DelayedError
    DE_Hole (Hole -> DelayedError) -> ZonkM Hole -> ZonkM DelayedError
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Hole -> ZonkM Hole
    zonkHole Hole
    hole
    zonkDelayedError (DE_NotConcrete NotConcreteError
    err)
      = NotConcreteError -> DelayedError
    DE_NotConcrete (NotConcreteError -> DelayedError)
    -> ZonkM NotConcreteError -> ZonkM DelayedError
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> NotConcreteError -> ZonkM NotConcreteError
    zonkNotConcreteError NotConcreteError
    err

    zonkHole :: Hole -> ZonkM Hole
    zonkHole :: Hole -> ZonkM Hole
    zonkHole hole :: Hole
    hole@(Hole { hole_ty :: Hole -> Type
    hole_ty = Type
    ty })
      = do { ty' <- Type -> ZonkM Type
    zonkTcType Type
    ty
           ; return (hole { hole_ty = ty' }) }

    zonkNotConcreteError :: NotConcreteError -> ZonkM NotConcreteError
    zonkNotConcreteError :: NotConcreteError -> ZonkM NotConcreteError
    zonkNotConcreteError err :: NotConcreteError
    err@(NCE_FRR { nce_frr_origin :: NotConcreteError -> FixedRuntimeRepOrigin
    nce_frr_origin = FixedRuntimeRepOrigin
    frr_orig })
      = do { frr_orig  <- FixedRuntimeRepOrigin -> ZonkM FixedRuntimeRepOrigin
    zonkFRROrigin FixedRuntimeRepOrigin
    frr_orig
           ; return $ err { nce_frr_origin = frr_orig  } }

    zonkFRROrigin :: FixedRuntimeRepOrigin -> ZonkM FixedRuntimeRepOrigin
    zonkFRROrigin :: FixedRuntimeRepOrigin -> ZonkM FixedRuntimeRepOrigin
    zonkFRROrigin (FixedRuntimeRepOrigin Type
    ty FixedRuntimeRepContext
    orig)
      = do { ty' <- Type -> ZonkM Type
    zonkTcType Type
    ty
           ; return $ FixedRuntimeRepOrigin ty' orig }

    {- Note [zonkCt behaviour]
    ~~~~~~~~~~~~~~~~~~~~~~~~~~
    zonkCt tries to maintain the canonical form of a Ct.  For example,
      - a CDictCan should stay a CDictCan;
      - a CIrredCan should stay a CIrredCan with its cc_reason flag intact

    Why?, for example:
    - For CDictCan, the @GHC.Tc.Solver.expandSuperClasses@ step, which runs after the
      simple wanted and plugin loop, looks for @CDictCan@s. If a plugin is in use,
      constraints are zonked before being passed to the plugin. This means if we
      don't preserve a canonical form, @expandSuperClasses@ fails to expand
      superclasses. This is what happened in #11525.

    - For CIrredCan we want to see if a constraint is insoluble with insolubleWC

    On the other hand, we change CEqCan to CNonCanonical, because of all of
    CEqCan's invariants, which can break during zonking. (Example: a ~R alpha, where
    we have alpha := N Int, where N is a newtype.) Besides, the constraint
    will be canonicalised again, so there is little benefit in keeping the
    CEqCan structure.

    NB: Constraints are always rewritten etc by the canonicaliser in
    GHC.Tc.Solver.Solve.solveCt even if they come in as CDictCan. Only canonical
    constraints that are actually in the inert set carry all the guarantees. So it
    is okay if zonkCt creates e.g. a CDictCan where the cc_tyars are /not/ fully
    reduced.
    -}

    zonkCt :: Ct -> ZonkM Ct
    -- See Note [zonkCt behaviour]
    zonkCt :: Ct -> ZonkM Ct
    zonkCt (CDictCan dict :: DictCt
    dict@(DictCt { di_ev :: DictCt -> CtEvidence
    di_ev = CtEvidence
    ev, di_tys :: DictCt -> [Type]
    di_tys = [Type]
    args }))
      = do { ev'   <- CtEvidence -> ZonkM CtEvidence
    zonkCtEvidence CtEvidence
    ev
           ; args' <- mapM zonkTcType args
           ; return (CDictCan (dict { di_ev = ev', di_tys = args' })) }

    zonkCt (CEqCan (EqCt { eq_ev :: EqCt -> CtEvidence
    eq_ev = CtEvidence
    ev }))
      = CtEvidence -> Ct
    mkNonCanonical (CtEvidence -> Ct) -> ZonkM CtEvidence -> ZonkM Ct
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> CtEvidence -> ZonkM CtEvidence
    zonkCtEvidence CtEvidence
    ev

    zonkCt (CIrredCan ir :: IrredCt
    ir@(IrredCt { ir_ev :: IrredCt -> CtEvidence
    ir_ev = CtEvidence
    ev })) -- Preserve the ir_reason flag
      = do { ev' <- CtEvidence -> ZonkM CtEvidence
    zonkCtEvidence CtEvidence
    ev
           ; return (CIrredCan (ir { ir_ev = ev' })) }

    zonkCt Ct
    ct
      = do { fl' <- CtEvidence -> ZonkM CtEvidence
    zonkCtEvidence (Ct -> CtEvidence
    ctEvidence Ct
    ct)
           ; return (mkNonCanonical fl') }

    zonkCtEvidence :: CtEvidence -> ZonkM CtEvidence
    zonkCtEvidence :: CtEvidence -> ZonkM CtEvidence
    zonkCtEvidence CtEvidence
    ctev
      = do { let pred :: Type
    pred = CtEvidence -> Type
    ctev_pred CtEvidence
    ctev
           ; pred' <- Type -> ZonkM Type
    zonkTcType Type
    pred
           ; return (setCtEvPredType ctev pred') }

    zonkSkolemInfo :: SkolemInfo -> ZonkM SkolemInfo
    zonkSkolemInfo :: SkolemInfo -> ZonkM SkolemInfo
    zonkSkolemInfo (SkolemInfo Unique
    u SkolemInfoAnon
    sk) = Unique -> SkolemInfoAnon -> SkolemInfo
    SkolemInfo Unique
    u (SkolemInfoAnon -> SkolemInfo)
    -> ZonkM SkolemInfoAnon -> ZonkM SkolemInfo
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> SkolemInfoAnon -> ZonkM SkolemInfoAnon
    zonkSkolemInfoAnon SkolemInfoAnon
    sk

    zonkSkolemInfoAnon :: SkolemInfoAnon -> ZonkM SkolemInfoAnon
    zonkSkolemInfoAnon :: SkolemInfoAnon -> ZonkM SkolemInfoAnon
    zonkSkolemInfoAnon (SigSkol UserTypeCtxt
    cx Type
    ty [(Name, CoVar)]
    tv_prs) = do { ty' <- Type -> ZonkM Type
    zonkTcType Type
    ty
                                                   ; return (SigSkol cx ty' tv_prs) }
    zonkSkolemInfoAnon (InferSkol [(Name, Type)]
    ntys) = do { ntys' <- ((Name, Type) -> ZonkM (Name, Type))
    -> [(Name, Type)] -> ZonkM [(Name, Type)]
    forall (t :: * -> *) (m :: * -> *) a b.
    (Traversable t, Monad m) =>
    (a -> m b) -> t a -> m (t b)
    forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [b]
    mapM (Name, Type) -> ZonkM (Name, Type)
    forall {a}. (a, Type) -> ZonkM (a, Type)
    do_one [(Name, Type)]
    ntys
                                         ; return (InferSkol ntys') }
      where
        do_one :: (a, Type) -> ZonkM (a, Type)
    do_one (a
    n, Type
    ty) = do { ty' <- Type -> ZonkM Type
    zonkTcType Type
    ty; return (n, ty') }
    zonkSkolemInfoAnon SkolemInfoAnon
    skol_info = SkolemInfoAnon -> ZonkM SkolemInfoAnon
    forall a. a -> ZonkM a
    forall (m :: * -> *) a. Monad m => a -> m a
    return SkolemInfoAnon
    skol_info

    {- Note [Sharing in zonking]
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    Suppose we have
       alpha :-> beta :-> gamma :-> ty
    where the ":->" means that the unification variable has been
    filled in with Indirect. Then when zonking alpha, it'd be nice
    to short-circuit beta too, so we end up with
       alpha :-> zty
       beta  :-> zty
       gamma :-> zty
    where zty is the zonked version of ty.  That way, if we come across
    beta later, we'll have less work to do.  (And indeed the same for
    alpha.)

    This is easily achieved: just overwrite (Indirect ty) with (Indirect
    zty).  Non-systematic perf comparisons suggest that this is a modest
    win.

    But c.f Note [Sharing when zonking to Type] in GHC.Tc.Zonk.Type.

    %************************************************************************
    %*                                                                      *
                     Tidying
    *                                                                      *
    ************************************************************************
    -}

    tcInitTidyEnv :: ZonkM TidyEnv
    -- We initialise the "tidy-env", used for tidying types before printing,
    -- by building a reverse map from the in-scope type variables to the
    -- OccName that the programmer originally used for them
    tcInitTidyEnv :: ZonkM TidyEnv
    tcInitTidyEnv
      = do  { ZonkGblEnv { zge_binder_stack = bndrs } <- ZonkM ZonkGblEnv
    getZonkGblEnv
            ; go emptyTidyEnv bndrs }
      where
        go :: TidyEnv -> TcBinderStack -> ZonkM TidyEnv
    go (TidyOccEnv
    env, VarEnv CoVar
    subst) []
          = TidyEnv -> ZonkM TidyEnv
    forall a. a -> ZonkM a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (TidyOccEnv
    env, VarEnv CoVar
    subst)
        go (TidyOccEnv
    env, VarEnv CoVar
    subst) (TcBinder
    b : TcBinderStack
    bs)
          | TcTvBndr Name
    name CoVar
    tyvar <- TcBinder
    b
           = do { let (TidyOccEnv
    env', OccName
    occ') = TidyOccEnv -> OccName -> (TidyOccEnv, OccName)
    tidyOccName TidyOccEnv
    env (Name -> OccName
    nameOccName Name
    name)
                      name' :: Name
    name'  = Name -> OccName -> Name
    tidyNameOcc Name
    name OccName
    occ'
                      tyvar1 :: CoVar
    tyvar1 = CoVar -> Name -> CoVar
    setTyVarName CoVar
    tyvar Name
    name'
                ; tyvar2 <- HasDebugCallStack => CoVar -> ZonkM CoVar
    CoVar -> ZonkM CoVar
    zonkTcTyVarToTcTyVar CoVar
    tyvar1
                  -- Be sure to zonk here!  Tidying applies to zonked
                  -- types, so if we don't zonk we may create an
                  -- ill-kinded type (#14175)
                ; go (env', extendVarEnv subst tyvar tyvar2) bs }
          | Bool
    otherwise
          = TidyEnv -> TcBinderStack -> ZonkM TidyEnv
    go (TidyOccEnv
    env, VarEnv CoVar
    subst) TcBinderStack
    bs

    -- | Get a 'TidyEnv' that includes mappings for all vars free in the given
    -- type. Useful when tidying open types.
    tcInitOpenTidyEnv :: [TyCoVar] -> ZonkM TidyEnv
    tcInitOpenTidyEnv :: [CoVar] -> ZonkM TidyEnv
    tcInitOpenTidyEnv [CoVar]
    tvs
      = do { env1 <- ZonkM TidyEnv
    tcInitTidyEnv
           ; let env2 = TidyEnv -> [CoVar] -> TidyEnv
    tidyFreeTyCoVars TidyEnv
    env1 [CoVar]
    tvs
           ; return env2 }

    zonkTidyTcType :: TidyEnv -> TcType -> ZonkM (TidyEnv, TcType)
    zonkTidyTcType :: TidyEnv -> Type -> ZonkM (TidyEnv, Type)
    zonkTidyTcType TidyEnv
    env Type
    ty = do { ty' <- Type -> ZonkM Type
    zonkTcType Type
    ty
                               ; return (tidyOpenType env ty') }

    zonkTidyTcTypes :: TidyEnv -> [TcType] -> ZonkM (TidyEnv, [TcType])
    zonkTidyTcTypes :: TidyEnv -> [Type] -> ZonkM (TidyEnv, [Type])
    zonkTidyTcTypes = [Type] -> TidyEnv -> [Type] -> ZonkM (TidyEnv, [Type])
    zonkTidyTcTypes' []
      where zonkTidyTcTypes' :: [Type] -> TidyEnv -> [Type] -> ZonkM (TidyEnv, [Type])
    zonkTidyTcTypes' [Type]
    zs TidyEnv
    env [] = (TidyEnv, [Type]) -> ZonkM (TidyEnv, [Type])
    forall a. a -> ZonkM a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (TidyEnv
    env, [Type] -> [Type]
    forall a. [a] -> [a]
    reverse [Type]
    zs)
            zonkTidyTcTypes' [Type]
    zs TidyEnv
    env (Type
    ty:[Type]
    tys)
              = do { (env', ty') <- TidyEnv -> Type -> ZonkM (TidyEnv, Type)
    zonkTidyTcType TidyEnv
    env Type
    ty
                   ; zonkTidyTcTypes' (ty':zs) env' tys }

    zonkTidyOrigin :: TidyEnv -> CtOrigin -> ZonkM (TidyEnv, CtOrigin)
    zonkTidyOrigin :: TidyEnv -> CtOrigin -> ZonkM (TidyEnv, CtOrigin)
    zonkTidyOrigin TidyEnv
    env (GivenOrigin SkolemInfoAnon
    skol_info)
      = do { skol_info1 <- SkolemInfoAnon -> ZonkM SkolemInfoAnon
    zonkSkolemInfoAnon SkolemInfoAnon
    skol_info
           ; let skol_info2 = TidyEnv -> SkolemInfoAnon -> SkolemInfoAnon
    tidySkolemInfoAnon TidyEnv
    env SkolemInfoAnon
    skol_info1
           ; return (env, GivenOrigin skol_info2) }
    zonkTidyOrigin TidyEnv
    env (GivenSCOrigin SkolemInfoAnon
    skol_info Int
    sc_depth Bool
    blocked)
      = do { skol_info1 <- SkolemInfoAnon -> ZonkM SkolemInfoAnon
    zonkSkolemInfoAnon SkolemInfoAnon
    skol_info
           ; let skol_info2 = TidyEnv -> SkolemInfoAnon -> SkolemInfoAnon
    tidySkolemInfoAnon TidyEnv
    env SkolemInfoAnon
    skol_info1
           ; return (env, GivenSCOrigin skol_info2 sc_depth blocked) }
    zonkTidyOrigin TidyEnv
    env orig :: CtOrigin
    orig@(TypeEqOrigin { uo_actual :: CtOrigin -> Type
    uo_actual   = Type
    act
                                          , uo_expected :: CtOrigin -> Type
    uo_expected = Type
    exp })
      = do { (env1, act') <- TidyEnv -> Type -> ZonkM (TidyEnv, Type)
    zonkTidyTcType TidyEnv
    env  Type
    act
           ; (env2, exp') <- zonkTidyTcType env1 exp
           ; return ( env2, orig { uo_actual   = act'
                                 , uo_expected = exp' }) }
    zonkTidyOrigin TidyEnv
    env (KindEqOrigin Type
    ty1 Type
    ty2 CtOrigin
    orig Maybe TypeOrKind
    t_or_k)
      = do { (env1, ty1')  <- TidyEnv -> Type -> ZonkM (TidyEnv, Type)
    zonkTidyTcType TidyEnv
    env  Type
    ty1
           ; (env2, ty2')  <- zonkTidyTcType env1 ty2
           ; (env3, orig') <- zonkTidyOrigin env2 orig
           ; return (env3, KindEqOrigin ty1' ty2' orig' t_or_k) }
    zonkTidyOrigin TidyEnv
    env (FunDepOrigin1 Type
    p1 CtOrigin
    o1 RealSrcSpan
    l1 Type
    p2 CtOrigin
    o2 RealSrcSpan
    l2)
      = do { (env1, p1') <- TidyEnv -> Type -> ZonkM (TidyEnv, Type)
    zonkTidyTcType TidyEnv
    env  Type
    p1
           ; (env2, o1') <- zonkTidyOrigin env1 o1
           ; (env3, p2') <- zonkTidyTcType env2 p2
           ; (env4, o2') <- zonkTidyOrigin env3 o2
           ; return (env4, FunDepOrigin1 p1' o1' l1 p2' o2' l2) }
    zonkTidyOrigin TidyEnv
    env (FunDepOrigin2 Type
    p1 CtOrigin
    o1 Type
    p2 SrcSpan
    l2)
      = do { (env1, p1') <- TidyEnv -> Type -> ZonkM (TidyEnv, Type)
    zonkTidyTcType TidyEnv
    env  Type
    p1
           ; (env2, p2') <- zonkTidyTcType env1 p2
           ; (env3, o1') <- zonkTidyOrigin env2 o1
           ; return (env3, FunDepOrigin2 p1' o1' p2' l2) }
    zonkTidyOrigin TidyEnv
    env (InjTFOrigin1 Type
    pred1 CtOrigin
    orig1 RealSrcSpan
    loc1 Type
    pred2 CtOrigin
    orig2 RealSrcSpan
    loc2)
      = do { (env1, pred1') <- TidyEnv -> Type -> ZonkM (TidyEnv, Type)
    zonkTidyTcType TidyEnv
    env  Type
    pred1
           ; (env2, orig1') <- zonkTidyOrigin env1 orig1
           ; (env3, pred2') <- zonkTidyTcType env2 pred2
           ; (env4, orig2') <- zonkTidyOrigin env3 orig2
           ; return (env4, InjTFOrigin1 pred1' orig1' loc1 pred2' orig2' loc2) }
    zonkTidyOrigin TidyEnv
    env (CycleBreakerOrigin CtOrigin
    orig)
      = do { (env1, orig') <- TidyEnv -> CtOrigin -> ZonkM (TidyEnv, CtOrigin)
    zonkTidyOrigin TidyEnv
    env CtOrigin
    orig
           ; return (env1, CycleBreakerOrigin orig') }
    zonkTidyOrigin TidyEnv
    env (InstProvidedOrigin Module
    mod ClsInst
    cls_inst)
      = do { (env1, is_tys') <- (TidyEnv -> Type -> ZonkM (TidyEnv, Type))
    -> TidyEnv -> [Type] -> ZonkM (TidyEnv, [Type])
    forall (m :: * -> *) (t :: * -> *) acc x y.
    (Monad m, Traversable t) =>
    (acc -> x -> m (acc, y)) -> acc -> t x -> m (acc, t y)
    mapAccumLM TidyEnv -> Type -> ZonkM (TidyEnv, Type)
    zonkTidyTcType TidyEnv
    env (ClsInst -> [Type]
    is_tys ClsInst
    cls_inst)
           ; return (env1, InstProvidedOrigin mod (cls_inst {is_tys = is_tys'})) }
    zonkTidyOrigin TidyEnv
    env (WantedSuperclassOrigin Type
    pty CtOrigin
    orig)
      = do { (env1, pty')  <- TidyEnv -> Type -> ZonkM (TidyEnv, Type)
    zonkTidyTcType TidyEnv
    env Type
    pty
           ; (env2, orig') <- zonkTidyOrigin env1 orig
           ; return (env2, WantedSuperclassOrigin pty' orig') }
    zonkTidyOrigin TidyEnv
    env CtOrigin
    orig = (TidyEnv, CtOrigin) -> ZonkM (TidyEnv, CtOrigin)
    forall a. a -> ZonkM a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (TidyEnv
    env, CtOrigin
    orig)

    zonkTidyOrigins :: TidyEnv -> [CtOrigin] -> ZonkM (TidyEnv, [CtOrigin])
    zonkTidyOrigins :: TidyEnv -> [CtOrigin] -> ZonkM (TidyEnv, [CtOrigin])
    zonkTidyOrigins = (TidyEnv -> CtOrigin -> ZonkM (TidyEnv, CtOrigin))
    -> TidyEnv -> [CtOrigin] -> ZonkM (TidyEnv, [CtOrigin])
    forall (m :: * -> *) (t :: * -> *) acc x y.
    (Monad m, Traversable t) =>
    (acc -> x -> m (acc, y)) -> acc -> t x -> m (acc, t y)
    mapAccumLM TidyEnv -> CtOrigin -> ZonkM (TidyEnv, CtOrigin)
    zonkTidyOrigin

    zonkTidyFRRInfos :: TidyEnv
                     -> [FixedRuntimeRepErrorInfo]
                     -> ZonkM (TidyEnv, [FixedRuntimeRepErrorInfo])
    zonkTidyFRRInfos :: TidyEnv
    -> [FixedRuntimeRepErrorInfo]
    -> ZonkM (TidyEnv, [FixedRuntimeRepErrorInfo])
    zonkTidyFRRInfos = [FixedRuntimeRepErrorInfo]
    -> TidyEnv
    -> [FixedRuntimeRepErrorInfo]
    -> ZonkM (TidyEnv, [FixedRuntimeRepErrorInfo])
    go []
      where
        go :: [FixedRuntimeRepErrorInfo]
    -> TidyEnv
    -> [FixedRuntimeRepErrorInfo]
    -> ZonkM (TidyEnv, [FixedRuntimeRepErrorInfo])
    go [FixedRuntimeRepErrorInfo]
    zs TidyEnv
    env [] = (TidyEnv, [FixedRuntimeRepErrorInfo])
    -> ZonkM (TidyEnv, [FixedRuntimeRepErrorInfo])
    forall a. a -> ZonkM a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (TidyEnv
    env, [FixedRuntimeRepErrorInfo] -> [FixedRuntimeRepErrorInfo]
    forall a. [a] -> [a]
    reverse [FixedRuntimeRepErrorInfo]
    zs)
        go [FixedRuntimeRepErrorInfo]
    zs TidyEnv
    env (FRR_Info { frr_info_origin :: FixedRuntimeRepErrorInfo -> FixedRuntimeRepOrigin
    frr_info_origin = FixedRuntimeRepOrigin Type
    ty FixedRuntimeRepContext
    orig
                            , frr_info_not_concrete :: FixedRuntimeRepErrorInfo -> Maybe (CoVar, Type)
    frr_info_not_concrete = Maybe (CoVar, Type)
    mb_not_conc } : [FixedRuntimeRepErrorInfo]
    tys)
          = do { (env, ty) <- TidyEnv -> Type -> ZonkM (TidyEnv, Type)
    zonkTidyTcType TidyEnv
    env Type
    ty
               ; (env, mb_not_conc) <- go_mb_not_conc env mb_not_conc
               ; let info = FRR_Info { frr_info_origin :: FixedRuntimeRepOrigin
    frr_info_origin = Type -> FixedRuntimeRepContext -> FixedRuntimeRepOrigin
    FixedRuntimeRepOrigin Type
    ty FixedRuntimeRepContext
    orig
                                     , frr_info_not_concrete :: Maybe (CoVar, Type)
    frr_info_not_concrete = Maybe (CoVar, Type)
    mb_not_conc }
               ; go (info:zs) env tys }

        go_mb_not_conc :: TidyEnv
    -> Maybe (CoVar, Type) -> ZonkM (TidyEnv, Maybe (CoVar, Type))
    go_mb_not_conc TidyEnv
    env Maybe (CoVar, Type)
    Nothing = (TidyEnv, Maybe (CoVar, Type))
    -> ZonkM (TidyEnv, Maybe (CoVar, Type))
    forall a. a -> ZonkM a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (TidyEnv
    env, Maybe (CoVar, Type)
    forall a. Maybe a
    Nothing)
        go_mb_not_conc TidyEnv
    env (Just (CoVar
    tv, Type
    ty))
          = do { (env, tv) <- (TidyEnv, CoVar) -> ZonkM (TidyEnv, CoVar)
    forall a. a -> ZonkM a
    forall (m :: * -> *) a. Monad m => a -> m a
    return ((TidyEnv, CoVar) -> ZonkM (TidyEnv, CoVar))
    -> (TidyEnv, CoVar) -> ZonkM (TidyEnv, CoVar)
    forall a b. (a -> b) -> a -> b
    $ TidyEnv -> CoVar -> (TidyEnv, CoVar)
    tidyOpenTyCoVar TidyEnv
    env CoVar
    tv
               ; (env, ty) <- zonkTidyTcType env ty
               ; return (env, Just (tv, ty)) }

    ----------------
    tidyCt :: TidyEnv -> Ct -> Ct
    -- Used only in error reporting
    tidyCt :: TidyEnv -> Ct -> Ct
    tidyCt TidyEnv
    env = (CtEvidence -> CtEvidence) -> Ct -> Ct
    updCtEvidence (TidyEnv -> CtEvidence -> CtEvidence
    tidyCtEvidence TidyEnv
    env)

    tidyCtEvidence :: TidyEnv -> CtEvidence -> CtEvidence
         -- NB: we do not tidy the ctev_evar field because we don't
         --     show it in error messages
    tidyCtEvidence :: TidyEnv -> CtEvidence -> CtEvidence
    tidyCtEvidence TidyEnv
    env CtEvidence
    ctev = CtEvidence
    ctev { ctev_pred = tidyType env ty }
      where
        ty :: Type
    ty  = CtEvidence -> Type
    ctev_pred CtEvidence
    ctev

    tidyHole :: TidyEnv -> Hole -> Hole
    tidyHole :: TidyEnv -> Hole -> Hole
    tidyHole TidyEnv
    env h :: Hole
    h@(Hole { hole_ty :: Hole -> Type
    hole_ty = Type
    ty }) = Hole
    h { hole_ty = tidyType env ty }

    tidyDelayedError :: TidyEnv -> DelayedError -> DelayedError
    tidyDelayedError :: TidyEnv -> DelayedError -> DelayedError
    tidyDelayedError TidyEnv
    env (DE_Hole Hole
    hole)
      = Hole -> DelayedError
    DE_Hole (Hole -> DelayedError) -> Hole -> DelayedError
    forall a b. (a -> b) -> a -> b
    $ TidyEnv -> Hole -> Hole
    tidyHole TidyEnv
    env Hole
    hole
    tidyDelayedError TidyEnv
    env (DE_NotConcrete NotConcreteError
    err)
      = NotConcreteError -> DelayedError
    DE_NotConcrete (NotConcreteError -> DelayedError)
    -> NotConcreteError -> DelayedError
    forall a b. (a -> b) -> a -> b
    $ TidyEnv -> NotConcreteError -> NotConcreteError
    tidyConcreteError TidyEnv
    env NotConcreteError
    err

    tidyConcreteError :: TidyEnv -> NotConcreteError -> NotConcreteError
    tidyConcreteError :: TidyEnv -> NotConcreteError -> NotConcreteError
    tidyConcreteError TidyEnv
    env err :: NotConcreteError
    err@(NCE_FRR { nce_frr_origin :: NotConcreteError -> FixedRuntimeRepOrigin
    nce_frr_origin = FixedRuntimeRepOrigin
    frr_orig })
      = NotConcreteError
    err { nce_frr_origin = tidyFRROrigin env frr_orig }

    tidyFRROrigin :: TidyEnv -> FixedRuntimeRepOrigin -> FixedRuntimeRepOrigin
    tidyFRROrigin :: TidyEnv -> FixedRuntimeRepOrigin -> FixedRuntimeRepOrigin
    tidyFRROrigin TidyEnv
    env (FixedRuntimeRepOrigin Type
    ty FixedRuntimeRepContext
    orig)
      = Type -> FixedRuntimeRepContext -> FixedRuntimeRepOrigin
    FixedRuntimeRepOrigin (TidyEnv -> Type -> Type
    tidyType TidyEnv
    env Type
    ty) FixedRuntimeRepContext
    orig

    ----------------
    tidyEvVar :: TidyEnv -> EvVar -> EvVar
    tidyEvVar :: TidyEnv -> CoVar -> CoVar
    tidyEvVar TidyEnv
    env CoVar
    var = (Type -> Type) -> CoVar -> CoVar
    updateIdTypeAndMult (TidyEnv -> Type -> Type
    tidyType TidyEnv
    env) CoVar
    var