typecheck/TcTypeableValidity.hs

    {-
    (c) The University of Glasgow 2006
    (c) The GRASP/AQUA Project, Glasgow University, 1992-1999
    -}

    -- | This module is separate from "TcTypeable" because the functions in this
    -- module are used in "ClsInst", and importing "TcTypeable" from "ClsInst"
    -- would lead to an import cycle.
    module TcTypeableValidity (tyConIsTypeable, typeIsTypeable) where

    import GhcPrelude

    import TyCoRep
    import TyCon
    import Type

    import Data.Maybe (isJust)

    -- | Is a particular 'TyCon' representable by @Typeable@?. These exclude type
    -- families and polytypes.
    tyConIsTypeable :: TyCon -> Bool
    tyConIsTypeable tc =
           isJust (tyConRepName_maybe tc)
        && typeIsTypeable (dropForAlls $ tyConKind tc)

    -- | Is a particular 'Type' representable by @Typeable@? Here we look for
    -- polytypes and types containing casts (which may be, for instance, a type
    -- family).
    typeIsTypeable :: Type -> Bool
    -- We handle types of the form (TYPE LiftedRep) specifically to avoid
    -- looping on (tyConIsTypeable RuntimeRep). We used to consider (TYPE rr)
    -- to be typeable without inspecting rr, but this exhibits bad behavior
    -- when rr is a type family.
    typeIsTypeable ty
      | Just ty' <- coreView ty         = typeIsTypeable ty'
    typeIsTypeable ty
      | isLiftedTypeKind ty             = True
    typeIsTypeable (TyVarTy _)          = True
    typeIsTypeable (AppTy a b)          = typeIsTypeable a && typeIsTypeable b
    typeIsTypeable (FunTy a b)          = typeIsTypeable a && typeIsTypeable b
    typeIsTypeable (TyConApp tc args)   = tyConIsTypeable tc
                                       && all typeIsTypeable args
    typeIsTypeable (ForAllTy{})         = False
    typeIsTypeable (LitTy _)            = True
    typeIsTypeable (CastTy{})           = False
    typeIsTypeable (CoercionTy{})       = False