    {-# OPTIONS_GHC -fno-warn-duplicate-exports -fno-warn-orphans #-}

    -- | This module is not used by GHC itself.  Rather, it exports all of
    -- the functions and types you are likely to need when writing a
    -- plugin for GHC. So authors of plugins can probably get away simply
    -- with saying "import GHC.Plugins".
    --
    -- Particularly interesting modules for plugin writers include
    -- "GHC.Core" and "GHC.Core.Opt.Monad".
    module GHC.Plugins
       ( module GHC.Driver.Plugins
       , module GHC.Types.Name.Reader
       , module GHC.Types.Name.Occurrence
       , module GHC.Types.Name
       , module GHC.Types.Var
       , module GHC.Types.Id
       , module GHC.Types.Id.Info
       , module GHC.Core.Opt.Monad
       , module GHC.Core
       , module GHC.Types.Literal
       , module GHC.Core.DataCon
       , module GHC.Core.Utils
       , module GHC.Core.Make
       , module GHC.Core.FVs
       , module GHC.Core.Subst
       , module GHC.Core.Rules
       , module GHC.Types.Annotations
       , module GHC.Driver.Session
       , module GHC.Driver.Ppr
       , module GHC.Unit.State
       , module GHC.Unit.Module
       , module GHC.Core.Type
       , module GHC.Core.TyCon
       , module GHC.Core.Coercion
       , module GHC.Builtin.Types
       , module GHC.Driver.Env
       , module GHC.Types.Basic
       , module GHC.Types.Var.Set
       , module GHC.Types.Var.Env
       , module GHC.Types.Name.Set
       , module GHC.Types.Name.Env
       , module GHC.Types.Unique
       , module GHC.Types.Unique.Set
       , module GHC.Types.Unique.FM
       , module GHC.Data.FiniteMap
       , module GHC.Utils.Misc
       , module GHC.Serialized
       , module GHC.Types.SrcLoc
       , module GHC.Utils.Outputable
       , module GHC.Utils.Panic
       , module GHC.Types.Unique.Supply
       , module GHC.Data.FastString
       , module GHC.Tc.Errors.Hole.FitTypes   -- for hole-fit plugins
       , module GHC.Unit.Module.ModGuts
       , module GHC.Unit.Module.ModSummary
       , module GHC.Unit.Module.ModIface
       , module GHC.Types.Meta
       , module GHC.Types.SourceError
       , -- * Getting 'Name's
         thNameToGhcName
       )
    where

    -- Plugin stuff itself
    import GHC.Driver.Plugins

    -- Variable naming
    import GHC.Types.TyThing
    import GHC.Types.SourceError
    import GHC.Types.Name.Reader
    import GHC.Types.Name.Occurrence  hiding  ( varName {- conflicts with Var.varName -} )
    import GHC.Types.Name     hiding  ( varName {- reexport from OccName, conflicts with Var.varName -} )
    import GHC.Types.Var
    import GHC.Types.Id       hiding  ( lazySetIdInfo, setIdExported, setIdNotExported {- all three conflict with Var -} )
    import GHC.Types.Id.Info

    -- Core
    import GHC.Core.Opt.Monad
    import GHC.Core
    import GHC.Types.Literal
    import GHC.Core.DataCon
    import GHC.Core.Utils
    import GHC.Core.Make
    import GHC.Core.FVs
    import GHC.Core.Subst hiding( substTyVarBndr, substCoVarBndr, extendCvSubst )
           -- These names are also exported by Type

    import GHC.Core.Rules
    import GHC.Types.Annotations
    import GHC.Types.Meta

    import GHC.Driver.Session
    import GHC.Unit.State

    import GHC.Unit.Module
    import GHC.Unit.Module.ModGuts
    import GHC.Unit.Module.ModSummary
    import GHC.Unit.Module.ModIface
    import GHC.Core.Type hiding {- conflict with GHC.Core.Subst -}
                    ( substTy, extendTvSubst, extendTvSubstList, isInScope )
    import GHC.Core.Coercion hiding {- conflict with GHC.Core.Subst -}
                    ( substCo )
    import GHC.Core.TyCon
    import GHC.Builtin.Types
    import GHC.Driver.Env
    import GHC.Types.Basic

    -- Collections and maps
    import GHC.Types.Var.Set
    import GHC.Types.Var.Env
    import GHC.Types.Name.Set
    import GHC.Types.Name.Env
    import GHC.Types.Unique.Set
    import GHC.Types.Unique.FM
    -- Conflicts with UniqFM:
    --import LazyUniqFM
    import GHC.Data.FiniteMap

    -- Common utilities
    import GHC.Utils.Misc
    import GHC.Serialized
    import GHC.Types.SrcLoc
    import GHC.Utils.Outputable
    import GHC.Utils.Panic
    import GHC.Driver.Ppr
    import GHC.Types.Unique.Supply
    import GHC.Types.Unique ( Unique, Uniquable(..) )
    import GHC.Data.FastString
    import Data.Maybe

    import GHC.Iface.Env    ( lookupOrigIO )
    import GHC.Prelude
    import GHC.Utils.Monad  ( mapMaybeM )
    import GHC.ThToHs       ( thRdrNameGuesses )
    import GHC.Tc.Utils.Env ( lookupGlobal )

    import GHC.Tc.Errors.Hole.FitTypes

    import qualified Language.Haskell.TH as TH

    {- This instance is defined outside GHC.Core.Opt.Monad so that
       GHC.Core.Opt.Monad does not depend on GHC.Tc.Utils.Env -}
    instance MonadThings CoreM where
        lookupThing :: Name -> CoreM TyThing
    lookupThing Name
    name = do { HscEnv
    hsc_env <- CoreM HscEnv
    getHscEnv
                              ; forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO forall a b. (a -> b) -> a -> b
    $ HscEnv -> Name -> IO TyThing
    lookupGlobal HscEnv
    hsc_env Name
    name }

    {-
    ************************************************************************
    *                                                                      *
                   Template Haskell interoperability
    *                                                                      *
    ************************************************************************
    -}

    -- | Attempt to convert a Template Haskell name to one that GHC can
    -- understand. Original TH names such as those you get when you use
    -- the @'foo@ syntax will be translated to their equivalent GHC name
    -- exactly. Qualified or unqualified TH names will be dynamically bound
    -- to names in the module being compiled, if possible. Exact TH names
    -- will be bound to the name they represent, exactly.
    thNameToGhcName :: TH.Name -> CoreM (Maybe Name)
    thNameToGhcName :: Name -> CoreM (Maybe Name)
    thNameToGhcName Name
    th_name
      =  do { [Name]
    names <- forall (m :: * -> *) a b.
    Applicative m =>
    (a -> m (Maybe b)) -> [a] -> m [b]
    mapMaybeM RdrName -> CoreM (Maybe Name)
    lookup (Name -> [RdrName]
    thRdrNameGuesses Name
    th_name)
              -- Pick the first that works
              -- E.g. reify (mkName "A") will pick the class A in preference
              -- to the data constructor A
            ; forall (m :: * -> *) a. Monad m => a -> m a
    return (forall a. [a] -> Maybe a
    listToMaybe [Name]
    names) }
      where
        lookup :: RdrName -> CoreM (Maybe Name)
    lookup RdrName
    rdr_name
          | Just Name
    n <- RdrName -> Maybe Name
    isExact_maybe RdrName
    rdr_name   -- This happens in derived code
          = forall (m :: * -> *) a. Monad m => a -> m a
    return forall a b. (a -> b) -> a -> b
    $ if Name -> Bool
    isExternalName Name
    n then forall a. a -> Maybe a
    Just Name
    n else forall a. Maybe a
    Nothing
          | Just (Module
    rdr_mod, OccName
    rdr_occ) <- RdrName -> Maybe (Module, OccName)
    isOrig_maybe RdrName
    rdr_name
          = do { HscEnv
    hsc_env <- CoreM HscEnv
    getHscEnv
               ; forall a. a -> Maybe a
    Just forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (HscEnv -> Module -> OccName -> IO Name
    lookupOrigIO HscEnv
    hsc_env Module
    rdr_mod OccName
    rdr_occ) }
          | Bool
    otherwise = forall (m :: * -> *) a. Monad m => a -> m a
    return forall a. Maybe a
    Nothing