liquidhaskell-0.9.0.2.1: src-ghc/Liquid/GHC/Types.hs
{-# LANGUAGE DeriveGeneric #-}
module Liquid.GHC.Types where
import Data.HashSet (HashSet, fromList)
import Data.Hashable
import GHC.Generics hiding (moduleName)
import Liquid.GHC.API
-- | A 'StableName' is virtually isomorphic to a GHC's 'Name' but crucially we don't use
-- the 'Eq' instance defined on a 'Name' because it's 'Unique'-based. In particular, GHC
-- doesn't guarantee that if we load an interface multiple times we would get the same 'Unique' for the
-- same 'Name', and this is a problem when we rely on 'Name's to be the same when we call 'isExportedVar',
-- which used to use a 'NameSet' derived from the '[AvailInfo]'. As the name implies, a 'NameSet' uses a
-- 'Name's 'Unique' for duplicate detection and indexing, and this would lead to 'Var's being resolved to
-- a 'Name' which is basically the same, but it has a /different/ 'Unique', and that would cause the lookup
-- inside the 'NameSet' to fail.
newtype StableName =
MkStableName { unStableName :: Name }
deriving Generic
instance Show StableName where
show (MkStableName n) = nameStableString n
instance Hashable StableName where
hashWithSalt s (MkStableName n) = hashWithSalt s (nameStableString n)
instance Eq StableName where
(MkStableName n1) == (MkStableName n2) = -- n1 `stableNameCmp` n2 == EQ
let sameOccName = occNameString (nameOccName n1) == occNameString (nameOccName n2)
sameModule = nameModule n1 == nameModule n2
sameSrcLoc = nameSrcLoc n1 == nameSrcLoc n2
sameSrcSpan = nameSrcSpan n1 == nameSrcSpan n2
in sameOccName && sameModule && sameSrcLoc && sameSrcSpan
-- | Creates a new 'StableName' out of a 'Name'.
mkStableName :: Name -> StableName
mkStableName = MkStableName
-- | Converts a list of 'AvailInfo' into a \"StableNameSet\", similarly to what 'availsToNameSet' would do.
availsToStableNameSet :: [AvailInfo] -> HashSet StableName
availsToStableNameSet avails = foldr add mempty avails
where add av acc = acc <> fromList (map mkStableName (availNames av))
--------------------------------------------------------------------------------
-- | Datatype For Holding GHC ModGuts ------------------------------------------
--------------------------------------------------------------------------------
data MGIModGuts = MI
{ mgi_binds :: !CoreProgram
, mgi_module :: !Module
, mgi_deps :: !Dependencies
, mgi_dir_imps :: ![ModuleName]
, mgi_rdr_env :: !GlobalRdrEnv
, mgi_tcs :: ![TyCon]
, mgi_fam_insts :: ![FamInst]
, mgi_exports :: !(HashSet StableName)
, mgi_cls_inst :: !(Maybe [ClsInst])
}
miModGuts :: Maybe [ClsInst] -> ModGuts -> MGIModGuts
miModGuts cls mg = MI
{ mgi_binds = mg_binds mg
, mgi_module = mg_module mg
, mgi_deps = mg_deps mg
, mgi_dir_imps = mgDirImps mg
, mgi_rdr_env = mg_rdr_env mg
, mgi_tcs = mg_tcs mg
, mgi_fam_insts = mg_fam_insts mg
, mgi_exports = availsToStableNameSet $ mg_exports mg
, mgi_cls_inst = cls
}
nameSetToStableNameSet :: NameSet -> HashSet StableName
nameSetToStableNameSet = fromList . map mkStableName . nameSetElemsStable
mgDirImps :: ModGuts -> [ModuleName]
mgDirImps = map gwib_mod . getDependenciesModuleNames . mg_deps
mgiNamestring :: MGIModGuts -> String
mgiNamestring = moduleNameString . moduleName . mgi_module