large-records-0.4.5: src/Data/Record/Internal/GHC/Shim.hs
{-# LANGUAGE CPP #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE PatternSynonyms #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE TupleSections #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE ViewPatterns #-}
{-# LANGUAGE TypeOperators #-}
#if __GLASGOW_HASKELL__ <914
#define data pattern
#else
{-# LANGUAGE ExplicitNamespaces #-}
#endif
-- | Thin compatibility layer around GHC
--
-- This should be the only module with GHC-specific CPP directives, and the
-- rest of the plugin should not import from any GHC modules directly.
module Data.Record.Internal.GHC.Shim (
-- * Names
thNameToGhcNameHsc
-- * Miscellaneous
, importDecl
, conPat
, mkFunBind
, HsModule
, LHsModule
, data GHC.HsModule
-- * Annotations
#if __GLASGOW_HASKELL__ < 902
, reLoc
, noLocA
#endif
, unLoc
-- * Extensions
, HasDefaultExt(..)
-- * Generalized @forall@
#if __GLASGOW_HASKELL__ >= 900
, HsTyVarBndr
, LHsTyVarBndr
#endif
, hsFunTy
, userTyVar
, kindedTyVar
#if __GLASGOW_HASKELL__ < 912
, hsTyVarLName
#endif
, setDefaultSpecificity
-- * Locations
, ToSrcSpan(..)
, FromSrcSpan(..)
, InheritLoc(..)
, withoutLoc
-- * New functionality
, compareHs
-- * NameCache
, NameCacheIO
, hscNameCacheIO
, takeUniqFromNameCacheIO
-- * Records
, simpleRecordUpdates
#if __GLASGOW_HASKELL__ >= 912
, mkAmbiguousFieldOcc
#endif
-- * Diagnostics
, issueError
, issueWarning
-- * Compat
#if __GLASGOW_HASKELL__ >= 910
, data LambdaExpr
#endif
, wrapBangTy
, Singleton (..)
#if __GLASGOW_HASKELL__ >= 914
, getBangType
, getBangStrictness
#endif
-- * Re-exports
-- The whole-sale module exports are not ideal for preserving compatibility
-- across ghc versions, but we'll deal with this on a case by case basis.
#if __GLASGOW_HASKELL__ < 900
, module Bag
, module BasicTypes
, module ErrUtils
, module GHC
, module GhcPlugins
, module HscMain
, module NameCache
, module TcEvidence
#else
, module GHC.Data.Bag
, module GHC.Driver.Main
, module GHC.Hs
, module GHC.Plugins
, module GHC.Tc.Types.Evidence
, module GHC.Utils.Error
#if __GLASGOW_HASKELL__ >= 902
, module GHC.Types.SourceText
, module GHC.Types.Fixity
#endif
#endif
) where
#undef data
import Control.Monad
import Data.List.NonEmpty (NonEmpty(..))
import Data.Generics (Data, GenericQ, cast, toConstr, gzipWithQ)
import qualified Data.List.NonEmpty as NE
-- ATM only 8.10.7 is <900
#if __GLASGOW_HASKELL__ < 900
import Data.IORef
import Bag (Bag, listToBag, emptyBag)
import BasicTypes (SourceText (NoSourceText))
import ConLike (ConLike)
import ErrUtils (mkErrMsg, mkWarnMsg)
import GHC hiding (AnnKeywordId(..), HsModule, exprType, typeKind, mkFunBind, unLoc)
import GhcPlugins hiding ((<>), getHscEnv, unLoc, singleton)
import HscMain (getHscEnv)
import NameCache (NameCache(nsUniqs))
import PatSyn (PatSyn)
import TcEvidence (HsWrapper(WpHole))
import qualified GHC hiding (unLoc)
import qualified GhcPlugins as GHC hiding (unLoc, singleton)
#else
import GHC.Hs hiding (LHsTyVarBndr, HsTyVarBndr, HsModule, mkFunBind)
import qualified GHC.Hs as GHC
import GHC.Core.Class (Class)
import GHC.Core.ConLike (ConLike)
import GHC.Core.PatSyn (PatSyn)
import GHC.Data.Bag (Bag, listToBag, emptyBag)
import GHC.Driver.Main (getHscEnv)
import GHC.Tc.Types.Evidence (HsWrapper(WpHole))
import GHC.Utils.Error (Severity(SevError, SevWarning))
import GHC.Plugins hiding ((<>), getHscEnv, unLoc, singleton
#if __GLASGOW_HASKELL__ >= 902
, AnnType, AnnLet, AnnRec, AnnLam, AnnCase
, Exception
#endif
#if __GLASGOW_HASKELL__ < 904
, trace
#endif
#if __GLASGOW_HASKELL__ >= 908
, fieldName
#endif
)
#if __GLASGOW_HASKELL__ < 902
import GHC.Parser.Annotation (IsUnicodeSyntax(NormalSyntax))
import GHC.Utils.Error (mkErrMsg, mkWarnMsg)
#else
import GHC.Types.Fixity
import GHC.Types.SourceText (SourceText(NoSourceText), mkIntegralLit)
#endif
#if __GLASGOW_HASKELL__ < 904
import Data.IORef
import GHC.Types.Name.Cache (NameCache(nsUniqs))
#else
import GHC.Types.Name.Cache (NameCache, takeUniqFromNameCache)
#endif
#endif
#if __GLASGOW_HASKELL__ >= 906
import Language.Haskell.Syntax.Basic (FieldLabelString (..))
import qualified GHC.Types.Basic
#endif
#if __GLASGOW_HASKELL__ >= 902
import GHC.Utils.Logger (getLogger)
#endif
#if __GLASGOW_HASKELL__ == 902
import GHC.Types.Error (mkWarnMsg, mkErr, mkDecorated)
import GHC.Driver.Errors (printOrThrowWarnings)
#endif
#if __GLASGOW_HASKELL__ >= 904
import GHC.Driver.Config.Diagnostic (initDiagOpts)
import GHC.Driver.Errors (printOrThrowDiagnostics)
import GHC.Driver.Errors.Types (GhcMessage(GhcUnknownMessage))
import GHC.Types.Error (mkPlainError, mkMessages, mkPlainDiagnostic)
import GHC.Utils.Error (mkMsgEnvelope, mkErrorMsgEnvelope)
#endif
#if __GLASGOW_HASKELL__ >= 908
import GHC.Types.Error (mkSimpleUnknownDiagnostic)
#elif __GLASGOW_HASKELL__ >= 906
import GHC.Types.Error (UnknownDiagnostic(..))
#endif
#if __GLASGOW_HASKELL__ >= 906
import GHC.Driver.Config.Diagnostic (initPrintConfig)
#endif
import qualified Language.Haskell.TH as TH
-- thNameToGhcNameIO imports
#if !MIN_VERSION_ghc(9,0,0)
import Data.Maybe (listToMaybe)
import IfaceEnv (lookupOrigIO)
import GHC.ThToHs (thRdrNameGuesses)
import MonadUtils (mapMaybeM)
#elif !MIN_VERSION_ghc(9,4,0)
import Data.Maybe (listToMaybe)
import GHC.Iface.Env (lookupOrigIO)
import GHC.ThToHs (thRdrNameGuesses)
import GHC.Utils.Monad (mapMaybeM)
#endif
{-------------------------------------------------------------------------------
Name resolution
-------------------------------------------------------------------------------}
thNameToGhcNameHsc :: TH.Name -> Hsc Name
thNameToGhcNameHsc th_name = do
hsc_env <- getHscEnv
#if __GLASGOW_HASKELL__ >= 904
let nameCache = hsc_NC hsc_env
#else
let nameCache = hsc_env
#endif
mname <- liftIO $ thNameToGhcNameIO nameCache th_name
case mname of
Just name -> return name
Nothing -> issueError noSrcSpan $ text "Cannot lookup" <+> text (show th_name)
#if !MIN_VERSION_ghc(9,4,0)
thNameToGhcNameIO :: HscEnv -> TH.Name -> IO (Maybe Name)
thNameToGhcNameIO hscEnv th_name
= do { names <- mapMaybeM do_lookup (thRdrNameGuesses th_name)
; return (listToMaybe names) }
where
do_lookup rdr_name
| Just n <- isExact_maybe rdr_name
= return $ if isExternalName n then Just n else Nothing
| Just (rdr_mod, rdr_occ) <- isOrig_maybe rdr_name
#if MIN_VERSION_ghc(9,3,0)
= Just <$> lookupNameCache (hsc_NC hscEnv) rdr_mod rdr_occ
#else
= Just <$> lookupOrigIO hscEnv rdr_mod rdr_occ
#endif
| otherwise
= return Nothing
#endif
{-------------------------------------------------------------------------------
Miscellaneous
-------------------------------------------------------------------------------}
-- | Optionally @qualified@ import declaration
importDecl :: Bool -> ModuleName -> LImportDecl GhcPs
importDecl qualified name = noLocA $ ImportDecl {
#if __GLASGOW_HASKELL__ < 906
ideclExt = defExt
#else
ideclExt = XImportDeclPass {
ideclAnn = defExt
, ideclSourceText = NoSourceText
, ideclImplicit = False
}
#endif
#if __GLASGOW_HASKELL__ < 906
, ideclSourceSrc = NoSourceText
#endif
, ideclName = noLocA name
#if __GLASGOW_HASKELL__ >= 904
, ideclPkgQual = NoRawPkgQual
#else
, ideclPkgQual = Nothing
#endif
, ideclSafe = False
#if __GLASGOW_HASKELL__ < 906
, ideclImplicit = False
#endif
, ideclAs = Nothing
#if __GLASGOW_HASKELL__ < 906
, ideclHiding = Nothing
#endif
, ideclQualified = if qualified then QualifiedPre else NotQualified
#if __GLASGOW_HASKELL__ < 900
, ideclSource = False
#else
, ideclSource = NotBoot
#endif
#if __GLASGOW_HASKELL__ >= 906
, ideclImportList = Nothing
#endif
#if __GLASGOW_HASKELL__ >= 914
, ideclLevelSpec = NotLevelled
#endif
}
conPat :: LIdP GhcPs -> HsConPatDetails GhcPs -> Pat GhcPs
#if __GLASGOW_HASKELL__ < 900
conPat x y = ConPatIn x y
#else
conPat x y = ConPat defExt x y
#endif
mkFunBind :: LIdP GhcPs -> [LMatch GhcPs (LHsExpr GhcPs)] -> HsBind GhcPs
#if __GLASGOW_HASKELL__ >= 908
mkFunBind n = GHC.mkFunBind defExt n
#else
mkFunBind n = GHC.mkFunBind Generated n
#endif
#if __GLASGOW_HASKELL__ < 900
type HsModule = GHC.HsModule GhcPs
#else
type HsModule = GHC.HsModule
#endif
#if __GLASGOW_HASKELL__ >= 906
type LHsModule = Located (HsModule GhcPs)
#else
type LHsModule = Located HsModule
#endif
{-------------------------------------------------------------------------------
NameCache
-------------------------------------------------------------------------------}
#if __GLASGOW_HASKELL__ < 904
type NameCacheIO = IORef NameCache
takeUniqFromNameCacheIO :: NameCacheIO -> IO Unique
takeUniqFromNameCacheIO = flip atomicModifyIORef aux
where
aux :: NameCache -> (NameCache, Unique)
aux nc = let (newUniq, us) = takeUniqFromSupply (nsUniqs nc)
in (nc { nsUniqs = us }, newUniq)
#else
type NameCacheIO = NameCache
takeUniqFromNameCacheIO :: NameCacheIO -> IO Unique
takeUniqFromNameCacheIO = takeUniqFromNameCache
#endif
hscNameCacheIO :: HscEnv -> NameCacheIO
hscNameCacheIO = hsc_NC
{-------------------------------------------------------------------------------
Exact-print annotations
-------------------------------------------------------------------------------}
#if __GLASGOW_HASKELL__ < 902
reLoc :: Located a -> Located a
reLoc = id
noLocA :: e -> Located e
noLocA = noLoc
#if __GLASGOW_HASKELL__ >= 900
mapXRec :: forall pass f g l. (f pass -> g pass) -> GenLocated l (f pass) -> GenLocated l (g pass)
mapXRec = fmap
#endif
#endif
{-------------------------------------------------------------------------------
Extensions
-------------------------------------------------------------------------------}
-- | This class has evolved to be essentially @class Default a where def :: a@,
class HasDefaultExt a where
defExt :: a
instance HasDefaultExt (Maybe a) where defExt = Nothing
instance HasDefaultExt [a] where defExt = []
instance HasDefaultExt NoExtField where
defExt = noExtField
instance HasDefaultExt (Bag a) where
defExt = emptyBag
#if __GLASGOW_HASKELL__ >= 906
#if __GLASGOW_HASKELL__ < 910
instance HasDefaultExt (LayoutInfo GhcPs) where
defExt = NoLayoutInfo
#endif
instance HasDefaultExt SourceText where
defExt = NoSourceText
#elif __GLASGOW_HASKELL__ >= 900
instance HasDefaultExt LayoutInfo where
defExt = NoLayoutInfo
#endif
#if __GLASGOW_HASKELL__ >= 910
instance HasDefaultExt GHC.Types.Basic.Origin where
defExt = Generated OtherExpansion DoPmc
#elif __GLASGOW_HASKELL__ >= 908
instance HasDefaultExt GHC.Types.Basic.Origin where
defExt = Generated DoPmc
#elif __GLASGOW_HASKELL__ >= 906
instance HasDefaultExt GHC.Types.Basic.Origin where
defExt = Generated
#endif
instance (HasDefaultExt a, HasDefaultExt b) => HasDefaultExt (a, b) where
defExt = (defExt, defExt)
instance (HasDefaultExt a, HasDefaultExt b, HasDefaultExt c) => HasDefaultExt (a, b, c) where
defExt = (defExt, defExt, defExt)
#if __GLASGOW_HASKELL__ >= 910
instance NoAnn ann => HasDefaultExt (EpAnn ann) where
defExt = noAnn
instance HasDefaultExt EpAnnComments where
defExt = epAnnComments (noAnn @(EpAnn [()]))
#elif __GLASGOW_HASKELL__ >= 902
instance HasDefaultExt (EpAnn ann) where
defExt = noAnn
instance HasDefaultExt AnnSortKey where
defExt = NoAnnSortKey
instance HasDefaultExt EpAnnComments where
defExt = epAnnComments noAnn
#endif
#if __GLASGOW_HASKELL__ >= 910
instance HasDefaultExt NoEpAnns where defExt = NoEpAnns
instance HasDefaultExt AnnListItem where defExt = noAnn
instance HasDefaultExt AnnPragma where defExt = noAnn
instance HasDefaultExt AnnContext where defExt = noAnn
instance HasDefaultExt AnnSig where defExt = noAnn
instance HasDefaultExt AnnParen where defExt = noAnn
instance HasDefaultExt EpAnnHsCase where defExt = noAnn
instance HasDefaultExt NameAnn where defExt = noAnn
instance HasDefaultExt (AnnSortKey tag) where defExt = NoAnnSortKey
instance HasDefaultExt EpLayout where defExt = EpNoLayout
instance HasDefaultExt (EpToken t) where defExt = noAnn
#if __GLASGOW_HASKELL__ >= 912
instance NoAnn a => HasDefaultExt (AnnList a) where defExt = noAnn
#else
instance HasDefaultExt AnnList where defExt = noAnn
#endif
#endif
#if __GLASGOW_HASKELL__ >= 912
instance HasDefaultExt EpAnnLam where defExt = noAnn
instance HasDefaultExt AnnConDeclH98 where defExt = noAnn
instance HasDefaultExt AnnClassDecl where defExt = noAnn
instance HasDefaultExt AnnFunRhs where defExt = noAnn
instance HasDefaultExt AnnClsInstDecl where defExt = noAnn
instance HasDefaultExt AnnDataDefn where defExt = noAnn
instance HasDefaultExt AnnTyVarBndr where defExt = noAnn
instance HasDefaultExt (EpUniToken tok utok) where defExt = NoEpUniTok
instance a ~ [LEpaComment] => HasDefaultExt (EpaLocation' a) where defExt = noAnn
#endif
{-------------------------------------------------------------------------------
Generalized @forall@ in 9.0
-------------------------------------------------------------------------------}
#if __GLASGOW_HASKELL__ >= 908
type HsTyVarBndr pass = GHC.HsTyVarBndr (HsBndrVis GhcPs) pass
type LHsTyVarBndr pass = GHC.LHsTyVarBndr (HsBndrVis GhcPs) pass
#elif __GLASGOW_HASKELL__ >= 900
type HsTyVarBndr pass = GHC.HsTyVarBndr () pass
type LHsTyVarBndr pass = GHC.LHsTyVarBndr () pass
#endif
hsFunTy :: XFunTy GhcPs -> LHsType GhcPs -> LHsType GhcPs -> HsType GhcPs
#if __GLASGOW_HASKELL__ < 900
hsFunTy = HsFunTy
#elif __GLASGOW_HASKELL__ < 904
hsFunTy ext = HsFunTy ext (HsUnrestrictedArrow NormalSyntax)
#elif __GLASGOW_HASKELL__ < 910
hsFunTy ext = HsFunTy ext (HsUnrestrictedArrow (L NoTokenLoc HsNormalTok))
#elif __GLASGOW_HASKELL__ < 914
hsFunTy ext = HsFunTy ext (HsUnrestrictedArrow NoEpUniTok)
#else
hsFunTy ext = HsFunTy ext (HsUnannotated (EpArrow defExt))
#endif
userTyVar :: LIdP GhcPs -> HsTyVarBndr GhcPs
#if __GLASGOW_HASKELL__ < 900
userTyVar = UserTyVar defExt
#elif __GLASGOW_HASKELL__ < 908
userTyVar = UserTyVar defExt ()
#elif __GLASGOW_HASKELL__ < 910
userTyVar = UserTyVar defExt HsBndrRequired
#elif __GLASGOW_HASKELL__ < 912
userTyVar = UserTyVar defExt (HsBndrRequired defExt)
#else
userTyVar n = HsTvb defExt (HsBndrRequired defExt) (HsBndrVar defExt n) (HsBndrNoKind defExt)
#endif
kindedTyVar :: LIdP GhcPs -> LHsKind GhcPs -> HsTyVarBndr GhcPs
#if __GLASGOW_HASKELL__ < 900
kindedTyVar = KindedTyVar defExt
#elif __GLASGOW_HASKELL__ < 908
kindedTyVar = KindedTyVar defExt ()
#elif __GLASGOW_HASKELL__ < 910
kindedTyVar = KindedTyVar defExt HsBndrRequired
#elif __GLASGOW_HASKELL__ < 912
kindedTyVar = KindedTyVar defExt (HsBndrRequired defExt)
#else
kindedTyVar n k = HsTvb defExt (HsBndrRequired defExt) (HsBndrVar defExt n) (HsBndrKind defExt k)
#endif
#if __GLASGOW_HASKELL__ < 912
-- | Like 'hsTyVarName', but don't throw away the location information
hsTyVarLName :: HsTyVarBndr GhcPs -> Maybe (LIdP GhcPs)
#if __GLASGOW_HASKELL__ < 900
hsTyVarLName (UserTyVar _ n ) = Just n
hsTyVarLName (KindedTyVar _ n _) = Just n
hsTyVarLName _ = Nothing
#else
hsTyVarLName (UserTyVar _ _ n ) = Just n
hsTyVarLName (KindedTyVar _ _ n _) = Just n
#endif
#endif
#if __GLASGOW_HASKELL__ < 900
setDefaultSpecificity :: LHsTyVarBndr pass -> GHC.LHsTyVarBndr pass
setDefaultSpecificity = id
#else
setDefaultSpecificity :: LHsTyVarBndr GhcPs -> GHC.LHsTyVarBndr Specificity GhcPs
#if __GLASGOW_HASKELL__ < 912
setDefaultSpecificity = mapXRec @GhcPs $ \case
UserTyVar ext _ name -> UserTyVar ext SpecifiedSpec name
KindedTyVar ext _ name kind -> KindedTyVar ext SpecifiedSpec name kind
#if __GLASGOW_HASKELL__ < 900
XTyVarBndr ext -> XTyVarBndr ext
#endif
#else
setDefaultSpecificity = mapXRec @GhcPs $ \(HsTvb ext _ name kind) -> HsTvb ext SpecifiedSpec name kind
#endif
#endif
{-------------------------------------------------------------------------------
New functionality
-------------------------------------------------------------------------------}
-- | Generic comparison for (parts of) the AST
--
-- NOTE: Not all abstract types are given special treatment here; in particular,
-- types only used in type-checked code ignored. To extend/audit this function,
-- grep the @ghc@ source for @abstractConstr@. Without further extensions,
-- all values of these types are considered equal.
--
-- NOTE: Although @ghc@ declares the constructor of @Bag@ as abstract as well,
-- we don't actually need a special case here: the constructors will be
-- considered equal, but 'gfoldl' will traverse the /elements/ of the @Bag@
-- nonetheless, which is precisely what we want.
compareHs' :: GenericQ (GenericQ Bool)
compareHs' x y
| (Just x', Just y') <- (cast x, cast y) = (==) @ConLike x' y'
| (Just x', Just y') <- (cast x, cast y) = (==) @PatSyn x' y'
| (Just x', Just y') <- (cast x, cast y) = (==) @Class x' y'
| (Just x', Just y') <- (cast x, cast y) = (==) @DataCon x' y'
| (Just x', Just y') <- (cast x, cast y) = (==) @FastString x' y'
| (Just x', Just y') <- (cast x, cast y) = (==) @Module x' y'
| (Just x', Just y') <- (cast x, cast y) = (==) @ModuleName x' y'
| (Just x', Just y') <- (cast x, cast y) = (==) @Name x' y'
| (Just x', Just y') <- (cast x, cast y) = (==) @OccName x' y'
| (Just x', Just y') <- (cast x, cast y) = (==) @TyCon x' y'
| (Just x', Just y') <- (cast x, cast y) = (==) @UnitId x' y'
| (Just x', Just y') <- (cast x, cast y) = (==) @Var x' y'
#if __GLASGOW_HASKELL__ >= 900
| (Just x', Just y') <- (cast x, cast y) = (==) @Unit x' y'
#endif
| (Just x', Just y') <- (cast x, cast y) = ignr @RealSrcSpan x' y'
| (Just x', Just y') <- (cast x, cast y) = ignr @SrcSpan x' y'
| otherwise = (toConstr x == toConstr y)
&& and (gzipWithQ compareHs' x y)
where
ignr :: a -> a -> Bool
ignr _ _ = True
-- | Compare two (parts) of a Haskell source tree for equality
--
-- The trees are compared for literal equality, but 'SrcSpan's are ignored.
compareHs :: Data a => a -> a -> Bool
compareHs x y = compareHs' x y
{-------------------------------------------------------------------------------
Working with locations
-------------------------------------------------------------------------------}
class ToSrcSpan a where
toSrcSpan :: a -> SrcSpan
instance ToSrcSpan SrcSpan where
toSrcSpan = id
#if 902 <= __GLASGOW_HASKELL__ && __GLASGOW_HASKELL__ < 910
instance ToSrcSpan (SrcSpanAnn' a) where
toSrcSpan = locA
#endif
instance ToSrcSpan l => ToSrcSpan (GenLocated l a) where
toSrcSpan (L l _) = toSrcSpan l
instance ToSrcSpan a => ToSrcSpan (NonEmpty a) where
toSrcSpan = toSrcSpan . NE.head
#if __GLASGOW_HASKELL__ >= 910
instance ToSrcSpan (EpAnn ann) where
toSrcSpan x = toSrcSpan (entry x)
instance ToSrcSpan EpaLocation where
toSrcSpan = getHasLoc
#endif
-- | The instance for @[]@ is not ideal: we use 'noLoc' if the list is empty
--
-- For the use cases in this library, this is acceptable: typically these are
-- lists with elements for the record fields, and having slightly poorer error
-- messages for highly unusual "empty large" records is fine.
instance ToSrcSpan a => ToSrcSpan [a] where
toSrcSpan (a:_) = toSrcSpan a
toSrcSpan [] = noSrcSpan
class FromSrcSpan a where
fromSrcSpan :: SrcSpan -> a
instance FromSrcSpan SrcSpan where
fromSrcSpan = id
#if 902 <= __GLASGOW_HASKELL__ && __GLASGOW_HASKELL__ < 910
instance FromSrcSpan (SrcAnn ann) where
fromSrcSpan = SrcSpanAnn defExt
#endif
#if __GLASGOW_HASKELL__ >= 910
instance HasDefaultExt ann => FromSrcSpan (EpAnn ann) where
fromSrcSpan s = EpAnn (spanAsAnchor s) defExt emptyComments
#endif
#if __GLASGOW_HASKELL__ >= 912
instance FromSrcSpan (EpaLocation' ann) where
fromSrcSpan = EpaSpan
#endif
class InheritLoc x a b | b -> a where
inheritLoc :: x -> a -> b
instance (ToSrcSpan x, FromSrcSpan y) => InheritLoc x a (GenLocated y a) where
inheritLoc = L . fromSrcSpan . toSrcSpan
instance InheritLoc x [a] [a] where inheritLoc _ = id
instance InheritLoc x Bool Bool where inheritLoc _ = id
instance InheritLoc x (HsTupArg p) (HsTupArg p) where inheritLoc _ = id
instance InheritLoc x (Pat p ) (Pat p) where inheritLoc _ = id
instance InheritLoc x (HsLocalBindsLR p q) (HsLocalBindsLR p q) where inheritLoc _ = id
withoutLoc :: InheritLoc SrcSpan a b => a -> b
withoutLoc = inheritLoc noSrcSpan
-- GHC-8.10 has weird unLoc definition.
unLoc :: GenLocated l a -> a
unLoc (L _ a) = a
{-------------------------------------------------------------------------------
Records
-------------------------------------------------------------------------------}
#if __GLASGOW_HASKELL__ >= 908
type RupdFlds = LHsRecUpdFields GhcPs
#elif __GLASGOW_HASKELL__ >= 902
type RupdFlds = Either [LHsRecUpdField GhcPs] [LHsRecUpdProj GhcPs]
#else
type RupdFlds = [LHsRecUpdField GhcPs]
#endif
#if __GLASGOW_HASKELL__ >= 912
mkAmbiguousFieldOcc :: LIdP GhcPs -> FieldOcc GhcPs
mkAmbiguousFieldOcc = mkFieldOcc
#endif
-- | Pattern match against the @rupd_flds@ of @RecordUpd@
simpleRecordUpdates :: RupdFlds -> Maybe [(LIdP GhcPs, LHsExpr GhcPs)]
#if __GLASGOW_HASKELL__ >= 904
simpleRecordUpdates =
\case
#if __GLASGOW_HASKELL__ >= 908
RegularRecUpdFields _ flds ->
mapM (aux (isUnambigous . unLoc)) flds
OverloadedRecUpdFields _ flds ->
mapM (aux (isSingleLabel . unLoc)) flds
#else
Left flds -> mapM (aux (isUnambigous . unLoc)) flds
Right flds -> mapM (aux (isSingleLabel . unLoc)) flds
#endif
where
aux :: forall lhs rhs.
(lhs -> Maybe (LIdP GhcPs))
-> LHsFieldBind GhcPs lhs rhs
-> Maybe (LIdP GhcPs, rhs)
aux f (L _ (HsFieldBind { hfbLHS = lbl
, hfbRHS = val
, hfbPun = pun
})) = do
guard $ not pun
(, val) <$> f lbl
#if __GLASGOW_HASKELL__ >= 912
isUnambigous :: FieldOcc GhcPs -> Maybe (LIdP GhcPs)
isUnambigous (FieldOcc _ name) = Just name
#else
isUnambigous :: AmbiguousFieldOcc GhcPs -> Maybe (LIdP GhcPs)
isUnambigous (Unambiguous _ name) = Just name
isUnambigous _ = Nothing
#endif
isSingleLabel :: FieldLabelStrings GhcPs -> Maybe (LIdP GhcPs)
isSingleLabel (FieldLabelStrings labels) =
case labels of
#if __GLASGOW_HASKELL__ >= 906
(matchSingleton -> Just (L _ (DotFieldOcc _ (L l (FieldLabelString label))))) ->
#else
[L _ (DotFieldOcc _ (L l label))] ->
#endif
Just $ L l (Unqual $ mkVarOccFS label)
_otherwise ->
Nothing
#elif __GLASGOW_HASKELL__ == 902
simpleRecordUpdates =
\case
Left flds -> mapM (aux isUnambigous) flds
Right flds -> mapM (aux isSingleLabel) flds
where
aux :: forall lhs rhs.
(lhs -> Maybe (LIdP GhcPs))
-> LHsRecField' GhcPs lhs rhs
-> Maybe (LIdP GhcPs, rhs)
aux f (L _ (HsRecField { hsRecFieldLbl = L _ lbl
, hsRecFieldArg = val
, hsRecPun = pun
})) = do
guard $ not pun
(, val) <$> f lbl
isUnambigous :: AmbiguousFieldOcc GhcPs -> Maybe (LIdP GhcPs)
isUnambigous (Unambiguous _ name) = Just name
isUnambigous _ = Nothing
isSingleLabel :: FieldLabelStrings GhcPs -> Maybe (LIdP GhcPs)
isSingleLabel (FieldLabelStrings labels) =
case labels of
[L _ (HsFieldLabel _ (L l label))] ->
Just $ inheritLoc l (Unqual $ mkVarOccFS label)
_otherwise ->
Nothing
#else
simpleRecordUpdates =
mapM (aux isUnambigous)
where
aux :: forall lhs rhs.
(lhs -> Maybe (LIdP GhcPs))
-> LHsRecField' lhs rhs
-> Maybe (LIdP GhcPs, rhs)
aux f (L _ (HsRecField { hsRecFieldLbl = L _ lbl
, hsRecFieldArg = val
, hsRecPun = pun
})) = do
guard $ not pun
(, val) <$> f lbl
isUnambigous :: AmbiguousFieldOcc GhcPs -> Maybe (LIdP GhcPs)
isUnambigous (Unambiguous _ name) = Just $ reLoc name
isUnambigous _ = Nothing
#endif
{-------------------------------------------------------------------------------
Diagnostics
-------------------------------------------------------------------------------}
issueError :: SrcSpan -> SDoc -> Hsc a
issueError l errMsg = do
#if __GLASGOW_HASKELL__ == 902
throwOneError $
mkErr l neverQualify (mkDecorated [errMsg])
#elif __GLASGOW_HASKELL__ >= 908
throwOneError $
mkErrorMsgEnvelope
l
neverQualify
(GhcUnknownMessage $ mkSimpleUnknownDiagnostic $ mkPlainError [] errMsg)
#elif __GLASGOW_HASKELL__ >= 906
throwOneError $
mkErrorMsgEnvelope
l
neverQualify
(GhcUnknownMessage $ UnknownDiagnostic $ mkPlainError [] errMsg)
#elif __GLASGOW_HASKELL__ >= 904
throwOneError $
mkErrorMsgEnvelope
l
neverQualify
(GhcUnknownMessage $ mkPlainError [] errMsg)
#else
dynFlags <- getDynFlags
throwOneError $
mkErrMsg dynFlags l neverQualify errMsg
#endif
issueWarning :: SrcSpan -> SDoc -> Hsc ()
issueWarning l errMsg = do
dynFlags <- getDynFlags
#if __GLASGOW_HASKELL__ == 902
logger <- getLogger
liftIO $ printOrThrowWarnings logger dynFlags . bag $
mkWarnMsg l neverQualify errMsg
#elif __GLASGOW_HASKELL__ >= 906
logger <- getLogger
dflags <- getDynFlags
let print_config = initPrintConfig dflags
liftIO $ printOrThrowDiagnostics logger print_config (initDiagOpts dynFlags) . mkMessages . bag $
mkMsgEnvelope
(initDiagOpts dynFlags)
l
neverQualify
#if __GLASGOW_HASKELL__ >= 908
(GhcUnknownMessage $ mkSimpleUnknownDiagnostic $ mkPlainDiagnostic WarningWithoutFlag [] errMsg)
#else
(GhcUnknownMessage $ UnknownDiagnostic $ mkPlainDiagnostic WarningWithoutFlag [] errMsg)
#endif
#elif __GLASGOW_HASKELL__ >= 904
logger <- getLogger
liftIO $ printOrThrowDiagnostics logger (initDiagOpts dynFlags) . mkMessages . bag $
mkMsgEnvelope
(initDiagOpts dynFlags)
l
neverQualify
(GhcUnknownMessage $ mkPlainDiagnostic WarningWithoutFlag [] errMsg)
#else
liftIO $ printOrThrowWarnings dynFlags . bag $
mkWarnMsg dynFlags l neverQualify errMsg
#endif
where
bag :: a -> Bag a
bag = listToBag . (:[])
{-------------------------------------------------------------------------------
Strictness
-------------------------------------------------------------------------------}
#if __GLASGOW_HASKELL__ >= 914
getBangType :: LHsType GhcPs -> LHsType GhcPs
getBangType (L _ (XHsType (HsBangTy _ _ lty))) = lty
--getBangType (L _ (HsDocTy x (L _ (HsBangTy _ _ lty)) lds)) =
-- addCLocA lty lds (HsDocTy x lty lds)
getBangType lty = lty
getBangStrictness :: LHsType GhcPs -> HsSrcBang
getBangStrictness (L _ (XHsType (HsBangTy _ s _ty))) = s
-- getBangStrictness (L _ (HsDocTy _ (L _ (HsBangTy (_, s) b _)) _)) = HsSrcBang s b
getBangStrictness _ = HsSrcBang NoSourceText NoSrcUnpack NoSrcStrict
#endif
{-------------------------------------------------------------------------------
Singleton
-------------------------------------------------------------------------------}
class Singleton f where
singleton :: a -> f a
matchSingleton :: f a -> Maybe a
instance Singleton [] where
singleton x = [x]
matchSingleton [x] = Just x
matchSingleton _ = Nothing
instance Singleton NonEmpty where
singleton x = x :| []
matchSingleton (x :| []) = Just x
matchSingleton _ = Nothing
{-------------------------------------------------------------------------------
Compat
-------------------------------------------------------------------------------}
#if __GLASGOW_HASKELL__ >= 914
wrapBangTy :: HsTypeGhcPsExt -> HsType GhcPs
wrapBangTy = XHsType
#else
wrapBangTy :: HsType GhcPs -> HsType GhcPs
wrapBangTy = id
#endif
#if __GLASGOW_HASKELL__ >= 910
pattern LambdaExpr :: HsMatchContext fn
pattern LambdaExpr = LamAlt LamSingle
#endif