summaryrefslogtreecommitdiff
path: root/compiler/iface
diff options
context:
space:
mode:
authorSylvain Henry <sylvain@haskus.fr>2020-01-02 19:13:44 +0100
committerMarge Bot <ben+marge-bot@smart-cactus.org>2020-01-06 18:39:22 -0500
commit99a9f51bf8207c79241fc0b685fadeb222a61292 (patch)
tree63daf74031c47b7a680477a21bba505bf2d32701 /compiler/iface
parent5ffea0c6c6a2670fd6819540f3ea61ce6620caaa (diff)
downloadhaskell-99a9f51bf8207c79241fc0b685fadeb222a61292.tar.gz
Module hierarchy: Iface (cf #13009)
Diffstat (limited to 'compiler/iface')
-rw-r--r--compiler/iface/BinIface.hs435
-rw-r--r--compiler/iface/BuildTyCl.hs6
-rw-r--r--compiler/iface/IfaceEnv.hs298
-rw-r--r--compiler/iface/IfaceEnv.hs-boot9
-rw-r--r--compiler/iface/IfaceSyn.hs2593
-rw-r--r--compiler/iface/IfaceType.hs2060
-rw-r--r--compiler/iface/IfaceType.hs-boot15
-rw-r--r--compiler/iface/LoadIface.hs1289
-rw-r--r--compiler/iface/LoadIface.hs-boot7
-rw-r--r--compiler/iface/MkIface.hs2078
-rw-r--r--compiler/iface/TcIface.hs1825
-rw-r--r--compiler/iface/TcIface.hs-boot19
-rw-r--r--compiler/iface/ToIface.hs684
-rw-r--r--compiler/iface/ToIface.hs-boot18
14 files changed, 3 insertions, 11333 deletions
diff --git a/compiler/iface/BinIface.hs b/compiler/iface/BinIface.hs
deleted file mode 100644
index faee723bd2..0000000000
--- a/compiler/iface/BinIface.hs
+++ /dev/null
@@ -1,435 +0,0 @@
-{-# LANGUAGE BinaryLiterals, CPP, ScopedTypeVariables, BangPatterns #-}
-
---
--- (c) The University of Glasgow 2002-2006
---
-
-{-# OPTIONS_GHC -O2 #-}
--- We always optimise this, otherwise performance of a non-optimised
--- compiler is severely affected
-
--- | Binary interface file support.
-module BinIface (
- -- * Public API for interface file serialisation
- writeBinIface,
- readBinIface,
- getSymtabName,
- getDictFastString,
- CheckHiWay(..),
- TraceBinIFaceReading(..),
- getWithUserData,
- putWithUserData,
-
- -- * Internal serialisation functions
- getSymbolTable,
- putName,
- putDictionary,
- putFastString,
- putSymbolTable,
- BinSymbolTable(..),
- BinDictionary(..)
-
- ) where
-
-#include "HsVersions.h"
-
-import GhcPrelude
-
-import TcRnMonad
-import PrelInfo ( isKnownKeyName, lookupKnownKeyName )
-import IfaceEnv
-import HscTypes
-import Module
-import Name
-import DynFlags
-import UniqFM
-import UniqSupply
-import Panic
-import Binary
-import SrcLoc
-import ErrUtils
-import FastMutInt
-import Unique
-import Outputable
-import NameCache
-import GHC.Platform
-import FastString
-import Constants
-import Util
-
-import Data.Array
-import Data.Array.ST
-import Data.Array.Unsafe
-import Data.Bits
-import Data.Char
-import Data.Word
-import Data.IORef
-import Data.Foldable
-import Control.Monad
-import Control.Monad.ST
-import Control.Monad.Trans.Class
-import qualified Control.Monad.Trans.State.Strict as State
-
--- ---------------------------------------------------------------------------
--- Reading and writing binary interface files
---
-
-data CheckHiWay = CheckHiWay | IgnoreHiWay
- deriving Eq
-
-data TraceBinIFaceReading = TraceBinIFaceReading | QuietBinIFaceReading
- deriving Eq
-
--- | Read an interface file
-readBinIface :: CheckHiWay -> TraceBinIFaceReading -> FilePath
- -> TcRnIf a b ModIface
-readBinIface checkHiWay traceBinIFaceReading hi_path = do
- ncu <- mkNameCacheUpdater
- dflags <- getDynFlags
- liftIO $ readBinIface_ dflags checkHiWay traceBinIFaceReading hi_path ncu
-
-readBinIface_ :: DynFlags -> CheckHiWay -> TraceBinIFaceReading -> FilePath
- -> NameCacheUpdater
- -> IO ModIface
-readBinIface_ dflags checkHiWay traceBinIFaceReading hi_path ncu = do
- let printer :: SDoc -> IO ()
- printer = case traceBinIFaceReading of
- TraceBinIFaceReading -> \sd ->
- putLogMsg dflags
- NoReason
- SevOutput
- noSrcSpan
- (defaultDumpStyle dflags)
- sd
- QuietBinIFaceReading -> \_ -> return ()
-
- wantedGot :: String -> a -> a -> (a -> SDoc) -> IO ()
- wantedGot what wanted got ppr' =
- printer (text what <> text ": " <>
- vcat [text "Wanted " <> ppr' wanted <> text ",",
- text "got " <> ppr' got])
-
- errorOnMismatch :: (Eq a, Show a) => String -> a -> a -> IO ()
- errorOnMismatch what wanted got =
- -- This will be caught by readIface which will emit an error
- -- msg containing the iface module name.
- when (wanted /= got) $ throwGhcExceptionIO $ ProgramError
- (what ++ " (wanted " ++ show wanted
- ++ ", got " ++ show got ++ ")")
- bh <- Binary.readBinMem hi_path
-
- -- Read the magic number to check that this really is a GHC .hi file
- -- (This magic number does not change when we change
- -- GHC interface file format)
- magic <- get bh
- wantedGot "Magic" (binaryInterfaceMagic dflags) magic ppr
- errorOnMismatch "magic number mismatch: old/corrupt interface file?"
- (binaryInterfaceMagic dflags) magic
-
- -- Note [dummy iface field]
- -- read a dummy 32/64 bit value. This field used to hold the
- -- dictionary pointer in old interface file formats, but now
- -- the dictionary pointer is after the version (where it
- -- should be). Also, the serialisation of value of type "Bin
- -- a" used to depend on the word size of the machine, now they
- -- are always 32 bits.
- if wORD_SIZE dflags == 4
- then do _ <- Binary.get bh :: IO Word32; return ()
- else do _ <- Binary.get bh :: IO Word64; return ()
-
- -- Check the interface file version and ways.
- check_ver <- get bh
- let our_ver = show hiVersion
- wantedGot "Version" our_ver check_ver text
- errorOnMismatch "mismatched interface file versions" our_ver check_ver
-
- check_way <- get bh
- let way_descr = getWayDescr dflags
- wantedGot "Way" way_descr check_way ppr
- when (checkHiWay == CheckHiWay) $
- errorOnMismatch "mismatched interface file ways" way_descr check_way
- getWithUserData ncu bh
-
-
--- | This performs a get action after reading the dictionary and symbol
--- table. It is necessary to run this before trying to deserialise any
--- Names or FastStrings.
-getWithUserData :: Binary a => NameCacheUpdater -> BinHandle -> IO a
-getWithUserData ncu bh = do
- -- Read the dictionary
- -- The next word in the file is a pointer to where the dictionary is
- -- (probably at the end of the file)
- dict_p <- Binary.get bh
- data_p <- tellBin bh -- Remember where we are now
- seekBin bh dict_p
- dict <- getDictionary bh
- seekBin bh data_p -- Back to where we were before
-
- -- Initialise the user-data field of bh
- bh <- do
- bh <- return $ setUserData bh $ newReadState (error "getSymtabName")
- (getDictFastString dict)
- symtab_p <- Binary.get bh -- Get the symtab ptr
- data_p <- tellBin bh -- Remember where we are now
- seekBin bh symtab_p
- symtab <- getSymbolTable bh ncu
- seekBin bh data_p -- Back to where we were before
-
- -- It is only now that we know how to get a Name
- return $ setUserData bh $ newReadState (getSymtabName ncu dict symtab)
- (getDictFastString dict)
-
- -- Read the interface file
- get bh
-
--- | Write an interface file
-writeBinIface :: DynFlags -> FilePath -> ModIface -> IO ()
-writeBinIface dflags hi_path mod_iface = do
- bh <- openBinMem initBinMemSize
- put_ bh (binaryInterfaceMagic dflags)
-
- -- dummy 32/64-bit field before the version/way for
- -- compatibility with older interface file formats.
- -- See Note [dummy iface field] above.
- if wORD_SIZE dflags == 4
- then Binary.put_ bh (0 :: Word32)
- else Binary.put_ bh (0 :: Word64)
-
- -- The version and way descriptor go next
- put_ bh (show hiVersion)
- let way_descr = getWayDescr dflags
- put_ bh way_descr
-
-
- putWithUserData (debugTraceMsg dflags 3) bh mod_iface
- -- And send the result to the file
- writeBinMem bh hi_path
-
--- | Put a piece of data with an initialised `UserData` field. This
--- is necessary if you want to serialise Names or FastStrings.
--- It also writes a symbol table and the dictionary.
--- This segment should be read using `getWithUserData`.
-putWithUserData :: Binary a => (SDoc -> IO ()) -> BinHandle -> a -> IO ()
-putWithUserData log_action bh payload = do
- -- Remember where the dictionary pointer will go
- dict_p_p <- tellBin bh
- -- Placeholder for ptr to dictionary
- put_ bh dict_p_p
-
- -- Remember where the symbol table pointer will go
- symtab_p_p <- tellBin bh
- put_ bh symtab_p_p
- -- Make some initial state
- symtab_next <- newFastMutInt
- writeFastMutInt symtab_next 0
- symtab_map <- newIORef emptyUFM
- let bin_symtab = BinSymbolTable {
- bin_symtab_next = symtab_next,
- bin_symtab_map = symtab_map }
- dict_next_ref <- newFastMutInt
- writeFastMutInt dict_next_ref 0
- dict_map_ref <- newIORef emptyUFM
- let bin_dict = BinDictionary {
- bin_dict_next = dict_next_ref,
- bin_dict_map = dict_map_ref }
-
- -- Put the main thing,
- bh <- return $ setUserData bh $ newWriteState (putName bin_dict bin_symtab)
- (putName bin_dict bin_symtab)
- (putFastString bin_dict)
- put_ bh payload
-
- -- Write the symtab pointer at the front of the file
- symtab_p <- tellBin bh -- This is where the symtab will start
- putAt bh symtab_p_p symtab_p -- Fill in the placeholder
- seekBin bh symtab_p -- Seek back to the end of the file
-
- -- Write the symbol table itself
- symtab_next <- readFastMutInt symtab_next
- symtab_map <- readIORef symtab_map
- putSymbolTable bh symtab_next symtab_map
- log_action (text "writeBinIface:" <+> int symtab_next
- <+> text "Names")
-
- -- NB. write the dictionary after the symbol table, because
- -- writing the symbol table may create more dictionary entries.
-
- -- Write the dictionary pointer at the front of the file
- dict_p <- tellBin bh -- This is where the dictionary will start
- putAt bh dict_p_p dict_p -- Fill in the placeholder
- seekBin bh dict_p -- Seek back to the end of the file
-
- -- Write the dictionary itself
- dict_next <- readFastMutInt dict_next_ref
- dict_map <- readIORef dict_map_ref
- putDictionary bh dict_next dict_map
- log_action (text "writeBinIface:" <+> int dict_next
- <+> text "dict entries")
-
-
-
--- | Initial ram buffer to allocate for writing interface files
-initBinMemSize :: Int
-initBinMemSize = 1024 * 1024
-
-binaryInterfaceMagic :: DynFlags -> Word32
-binaryInterfaceMagic dflags
- | target32Bit (targetPlatform dflags) = 0x1face
- | otherwise = 0x1face64
-
-
--- -----------------------------------------------------------------------------
--- The symbol table
---
-
-putSymbolTable :: BinHandle -> Int -> UniqFM (Int,Name) -> IO ()
-putSymbolTable bh next_off symtab = do
- put_ bh next_off
- let names = elems (array (0,next_off-1) (nonDetEltsUFM symtab))
- -- It's OK to use nonDetEltsUFM here because the elements have
- -- indices that array uses to create order
- mapM_ (\n -> serialiseName bh n symtab) names
-
-getSymbolTable :: BinHandle -> NameCacheUpdater -> IO SymbolTable
-getSymbolTable bh ncu = do
- sz <- get bh
- od_names <- sequence (replicate sz (get bh))
- updateNameCache ncu $ \namecache ->
- runST $ flip State.evalStateT namecache $ do
- mut_arr <- lift $ newSTArray_ (0, sz-1)
- for_ (zip [0..] od_names) $ \(i, odn) -> do
- (nc, !n) <- State.gets $ \nc -> fromOnDiskName nc odn
- lift $ writeArray mut_arr i n
- State.put nc
- arr <- lift $ unsafeFreeze mut_arr
- namecache' <- State.get
- return (namecache', arr)
- where
- -- This binding is required because the type of newArray_ cannot be inferred
- newSTArray_ :: forall s. (Int, Int) -> ST s (STArray s Int Name)
- newSTArray_ = newArray_
-
-type OnDiskName = (UnitId, ModuleName, OccName)
-
-fromOnDiskName :: NameCache -> OnDiskName -> (NameCache, Name)
-fromOnDiskName nc (pid, mod_name, occ) =
- let mod = mkModule pid mod_name
- cache = nsNames nc
- in case lookupOrigNameCache cache mod occ of
- Just name -> (nc, name)
- Nothing ->
- let (uniq, us) = takeUniqFromSupply (nsUniqs nc)
- name = mkExternalName uniq mod occ noSrcSpan
- new_cache = extendNameCache cache mod occ name
- in ( nc{ nsUniqs = us, nsNames = new_cache }, name )
-
-serialiseName :: BinHandle -> Name -> UniqFM (Int,Name) -> IO ()
-serialiseName bh name _ = do
- let mod = ASSERT2( isExternalName name, ppr name ) nameModule name
- put_ bh (moduleUnitId mod, moduleName mod, nameOccName name)
-
-
--- Note [Symbol table representation of names]
--- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
---
--- An occurrence of a name in an interface file is serialized as a single 32-bit
--- word. The format of this word is:
--- 00xxxxxx xxxxxxxx xxxxxxxx xxxxxxxx
--- A normal name. x is an index into the symbol table
--- 10xxxxxx xxyyyyyy yyyyyyyy yyyyyyyy
--- A known-key name. x is the Unique's Char, y is the int part. We assume that
--- all known-key uniques fit in this space. This is asserted by
--- PrelInfo.knownKeyNamesOkay.
---
--- During serialization we check for known-key things using isKnownKeyName.
--- During deserialization we use lookupKnownKeyName to get from the unique back
--- to its corresponding Name.
-
-
--- See Note [Symbol table representation of names]
-putName :: BinDictionary -> BinSymbolTable -> BinHandle -> Name -> IO ()
-putName _dict BinSymbolTable{
- bin_symtab_map = symtab_map_ref,
- bin_symtab_next = symtab_next }
- bh name
- | isKnownKeyName name
- , let (c, u) = unpkUnique (nameUnique name) -- INVARIANT: (ord c) fits in 8 bits
- = -- ASSERT(u < 2^(22 :: Int))
- put_ bh (0x80000000
- .|. (fromIntegral (ord c) `shiftL` 22)
- .|. (fromIntegral u :: Word32))
-
- | otherwise
- = do symtab_map <- readIORef symtab_map_ref
- case lookupUFM symtab_map name of
- Just (off,_) -> put_ bh (fromIntegral off :: Word32)
- Nothing -> do
- off <- readFastMutInt symtab_next
- -- MASSERT(off < 2^(30 :: Int))
- writeFastMutInt symtab_next (off+1)
- writeIORef symtab_map_ref
- $! addToUFM symtab_map name (off,name)
- put_ bh (fromIntegral off :: Word32)
-
--- See Note [Symbol table representation of names]
-getSymtabName :: NameCacheUpdater
- -> Dictionary -> SymbolTable
- -> BinHandle -> IO Name
-getSymtabName _ncu _dict symtab bh = do
- i :: Word32 <- get bh
- case i .&. 0xC0000000 of
- 0x00000000 -> return $! symtab ! fromIntegral i
-
- 0x80000000 ->
- let
- tag = chr (fromIntegral ((i .&. 0x3FC00000) `shiftR` 22))
- ix = fromIntegral i .&. 0x003FFFFF
- u = mkUnique tag ix
- in
- return $! case lookupKnownKeyName u of
- Nothing -> pprPanic "getSymtabName:unknown known-key unique"
- (ppr i $$ ppr (unpkUnique u))
- Just n -> n
-
- _ -> pprPanic "getSymtabName:unknown name tag" (ppr i)
-
-data BinSymbolTable = BinSymbolTable {
- bin_symtab_next :: !FastMutInt, -- The next index to use
- bin_symtab_map :: !(IORef (UniqFM (Int,Name)))
- -- indexed by Name
- }
-
-putFastString :: BinDictionary -> BinHandle -> FastString -> IO ()
-putFastString dict bh fs = allocateFastString dict fs >>= put_ bh
-
-allocateFastString :: BinDictionary -> FastString -> IO Word32
-allocateFastString BinDictionary { bin_dict_next = j_r,
- bin_dict_map = out_r} f = do
- out <- readIORef out_r
- let uniq = getUnique f
- case lookupUFM out uniq of
- Just (j, _) -> return (fromIntegral j :: Word32)
- Nothing -> do
- j <- readFastMutInt j_r
- writeFastMutInt j_r (j + 1)
- writeIORef out_r $! addToUFM out uniq (j, f)
- return (fromIntegral j :: Word32)
-
-getDictFastString :: Dictionary -> BinHandle -> IO FastString
-getDictFastString dict bh = do
- j <- get bh
- return $! (dict ! fromIntegral (j :: Word32))
-
-data BinDictionary = BinDictionary {
- bin_dict_next :: !FastMutInt, -- The next index to use
- bin_dict_map :: !(IORef (UniqFM (Int,FastString)))
- -- indexed by FastString
- }
-
-getWayDescr :: DynFlags -> String
-getWayDescr dflags
- | platformUnregisterised (targetPlatform dflags) = 'u':tag
- | otherwise = tag
- where tag = buildTag dflags
- -- if this is an unregisterised build, make sure our interfaces
- -- can't be used by a registerised build.
diff --git a/compiler/iface/BuildTyCl.hs b/compiler/iface/BuildTyCl.hs
index 827b89983f..1ea61cf0c5 100644
--- a/compiler/iface/BuildTyCl.hs
+++ b/compiler/iface/BuildTyCl.hs
@@ -17,7 +17,7 @@ module BuildTyCl (
import GhcPrelude
-import IfaceEnv
+import GHC.Iface.Env
import FamInstEnv( FamInstEnvs, mkNewTypeCoAxiom )
import TysWiredIn( isCTupleTyConName )
import TysPrim ( voidPrimTy )
@@ -78,7 +78,7 @@ mkNewTyConRhs tycon_name tycon con
etad_tvs :: [TyVar] -- Matched lazily, so that mkNewTypeCo can
etad_roles :: [Role] -- return a TyCon without pulling on rhs_ty
- etad_rhs :: Type -- See Note [Tricky iface loop] in LoadIface
+ etad_rhs :: Type -- See Note [Tricky iface loop] in GHC.Iface.Load
(etad_tvs, etad_roles, etad_rhs) = eta_reduce (reverse tvs) (reverse roles) rhs_ty
eta_reduce :: [TyVar] -- Reversed
@@ -386,7 +386,7 @@ newImplicitBinder :: Name -- Base name
-> TcRnIf m n Name -- Implicit name
-- Called in BuildTyCl to allocate the implicit binders of type/class decls
-- For source type/class decls, this is the first occurrence
--- For iface ones, the LoadIface has already allocated a suitable name in the cache
+-- For iface ones, GHC.Iface.Load has already allocated a suitable name in the cache
newImplicitBinder base_name mk_sys_occ
= newImplicitBinderLoc base_name mk_sys_occ (nameSrcSpan base_name)
diff --git a/compiler/iface/IfaceEnv.hs b/compiler/iface/IfaceEnv.hs
deleted file mode 100644
index 2bcfa82c96..0000000000
--- a/compiler/iface/IfaceEnv.hs
+++ /dev/null
@@ -1,298 +0,0 @@
--- (c) The University of Glasgow 2002-2006
-
-{-# LANGUAGE CPP, RankNTypes, BangPatterns #-}
-
-module IfaceEnv (
- newGlobalBinder, newInteractiveBinder,
- externaliseName,
- lookupIfaceTop,
- lookupOrig, lookupOrigIO, lookupOrigNameCache, extendNameCache,
- newIfaceName, newIfaceNames,
- extendIfaceIdEnv, extendIfaceTyVarEnv,
- tcIfaceLclId, tcIfaceTyVar, lookupIfaceVar,
- lookupIfaceTyVar, extendIfaceEnvs,
- setNameModule,
-
- ifaceExportNames,
-
- -- Name-cache stuff
- allocateGlobalBinder, updNameCacheTc,
- mkNameCacheUpdater, NameCacheUpdater(..),
- ) where
-
-#include "HsVersions.h"
-
-import GhcPrelude
-
-import TcRnMonad
-import HscTypes
-import Type
-import Var
-import Name
-import Avail
-import Module
-import FastString
-import FastStringEnv
-import IfaceType
-import NameCache
-import UniqSupply
-import SrcLoc
-
-import Outputable
-import Data.List ( partition )
-
-{-
-*********************************************************
-* *
- Allocating new Names in the Name Cache
-* *
-*********************************************************
-
-See Also: Note [The Name Cache] in NameCache
--}
-
-newGlobalBinder :: Module -> OccName -> SrcSpan -> TcRnIf a b Name
--- Used for source code and interface files, to make the
--- Name for a thing, given its Module and OccName
--- See Note [The Name Cache]
---
--- The cache may already already have a binding for this thing,
--- because we may have seen an occurrence before, but now is the
--- moment when we know its Module and SrcLoc in their full glory
-
-newGlobalBinder mod occ loc
- = do { name <- updNameCacheTc mod occ $ \name_cache ->
- allocateGlobalBinder name_cache mod occ loc
- ; traceIf (text "newGlobalBinder" <+>
- (vcat [ ppr mod <+> ppr occ <+> ppr loc, ppr name]))
- ; return name }
-
-newInteractiveBinder :: HscEnv -> OccName -> SrcSpan -> IO Name
--- Works in the IO monad, and gets the Module
--- from the interactive context
-newInteractiveBinder hsc_env occ loc
- = do { let mod = icInteractiveModule (hsc_IC hsc_env)
- ; updNameCacheIO hsc_env mod occ $ \name_cache ->
- allocateGlobalBinder name_cache mod occ loc }
-
-allocateGlobalBinder
- :: NameCache
- -> Module -> OccName -> SrcSpan
- -> (NameCache, Name)
--- See Note [The Name Cache]
-allocateGlobalBinder name_supply mod occ loc
- = case lookupOrigNameCache (nsNames name_supply) mod occ of
- -- A hit in the cache! We are at the binding site of the name.
- -- This is the moment when we know the SrcLoc
- -- of the Name, so we set this field in the Name we return.
- --
- -- Then (bogus) multiple bindings of the same Name
- -- get different SrcLocs can be reported as such.
- --
- -- Possible other reason: it might be in the cache because we
- -- encountered an occurrence before the binding site for an
- -- implicitly-imported Name. Perhaps the current SrcLoc is
- -- better... but not really: it'll still just say 'imported'
- --
- -- IMPORTANT: Don't mess with wired-in names.
- -- Their wired-in-ness is in their NameSort
- -- and their Module is correct.
-
- Just name | isWiredInName name
- -> (name_supply, name)
- | otherwise
- -> (new_name_supply, name')
- where
- uniq = nameUnique name
- name' = mkExternalName uniq mod occ loc
- -- name' is like name, but with the right SrcSpan
- new_cache = extendNameCache (nsNames name_supply) mod occ name'
- new_name_supply = name_supply {nsNames = new_cache}
-
- -- Miss in the cache!
- -- Build a completely new Name, and put it in the cache
- _ -> (new_name_supply, name)
- where
- (uniq, us') = takeUniqFromSupply (nsUniqs name_supply)
- name = mkExternalName uniq mod occ loc
- new_cache = extendNameCache (nsNames name_supply) mod occ name
- new_name_supply = name_supply {nsUniqs = us', nsNames = new_cache}
-
-ifaceExportNames :: [IfaceExport] -> TcRnIf gbl lcl [AvailInfo]
-ifaceExportNames exports = return exports
-
--- | A function that atomically updates the name cache given a modifier
--- function. The second result of the modifier function will be the result
--- of the IO action.
-newtype NameCacheUpdater
- = NCU { updateNameCache :: forall c. (NameCache -> (NameCache, c)) -> IO c }
-
-mkNameCacheUpdater :: TcRnIf a b NameCacheUpdater
-mkNameCacheUpdater = do { hsc_env <- getTopEnv
- ; let !ncRef = hsc_NC hsc_env
- ; return (NCU (updNameCache ncRef)) }
-
-updNameCacheTc :: Module -> OccName -> (NameCache -> (NameCache, c))
- -> TcRnIf a b c
-updNameCacheTc mod occ upd_fn = do {
- hsc_env <- getTopEnv
- ; liftIO $ updNameCacheIO hsc_env mod occ upd_fn }
-
-
-updNameCacheIO :: HscEnv -> Module -> OccName
- -> (NameCache -> (NameCache, c))
- -> IO c
-updNameCacheIO hsc_env mod occ upd_fn = do {
-
- -- First ensure that mod and occ are evaluated
- -- If not, chaos can ensue:
- -- we read the name-cache
- -- then pull on mod (say)
- -- which does some stuff that modifies the name cache
- -- This did happen, with tycon_mod in TcIface.tcIfaceAlt (DataAlt..)
-
- mod `seq` occ `seq` return ()
- ; updNameCache (hsc_NC hsc_env) upd_fn }
-
-
-{-
-************************************************************************
-* *
- Name cache access
-* *
-************************************************************************
--}
-
--- | Look up the 'Name' for a given 'Module' and 'OccName'.
--- Consider alternatively using 'lookupIfaceTop' if you're in the 'IfL' monad
--- and 'Module' is simply that of the 'ModIface' you are typechecking.
-lookupOrig :: Module -> OccName -> TcRnIf a b Name
-lookupOrig mod occ
- = do { traceIf (text "lookup_orig" <+> ppr mod <+> ppr occ)
-
- ; updNameCacheTc mod occ $ lookupNameCache mod occ }
-
-lookupOrigIO :: HscEnv -> Module -> OccName -> IO Name
-lookupOrigIO hsc_env mod occ
- = updNameCacheIO hsc_env mod occ $ lookupNameCache mod occ
-
-lookupNameCache :: Module -> OccName -> NameCache -> (NameCache, Name)
--- Lookup up the (Module,OccName) in the NameCache
--- If you find it, return it; if not, allocate a fresh original name and extend
--- the NameCache.
--- Reason: this may the first occurrence of (say) Foo.bar we have encountered.
--- If we need to explore its value we will load Foo.hi; but meanwhile all we
--- need is a Name for it.
-lookupNameCache mod occ name_cache =
- case lookupOrigNameCache (nsNames name_cache) mod occ of {
- Just name -> (name_cache, name);
- Nothing ->
- case takeUniqFromSupply (nsUniqs name_cache) of {
- (uniq, us) ->
- let
- name = mkExternalName uniq mod occ noSrcSpan
- new_cache = extendNameCache (nsNames name_cache) mod occ name
- in (name_cache{ nsUniqs = us, nsNames = new_cache }, name) }}
-
-externaliseName :: Module -> Name -> TcRnIf m n Name
--- Take an Internal Name and make it an External one,
--- with the same unique
-externaliseName mod name
- = do { let occ = nameOccName name
- loc = nameSrcSpan name
- uniq = nameUnique name
- ; occ `seq` return () -- c.f. seq in newGlobalBinder
- ; updNameCacheTc mod occ $ \ ns ->
- let name' = mkExternalName uniq mod occ loc
- ns' = ns { nsNames = extendNameCache (nsNames ns) mod occ name' }
- in (ns', name') }
-
--- | Set the 'Module' of a 'Name'.
-setNameModule :: Maybe Module -> Name -> TcRnIf m n Name
-setNameModule Nothing n = return n
-setNameModule (Just m) n =
- newGlobalBinder m (nameOccName n) (nameSrcSpan n)
-
-{-
-************************************************************************
-* *
- Type variables and local Ids
-* *
-************************************************************************
--}
-
-tcIfaceLclId :: FastString -> IfL Id
-tcIfaceLclId occ
- = do { lcl <- getLclEnv
- ; case (lookupFsEnv (if_id_env lcl) occ) of
- Just ty_var -> return ty_var
- Nothing -> failIfM (text "Iface id out of scope: " <+> ppr occ)
- }
-
-extendIfaceIdEnv :: [Id] -> IfL a -> IfL a
-extendIfaceIdEnv ids thing_inside
- = do { env <- getLclEnv
- ; let { id_env' = extendFsEnvList (if_id_env env) pairs
- ; pairs = [(occNameFS (getOccName id), id) | id <- ids] }
- ; setLclEnv (env { if_id_env = id_env' }) thing_inside }
-
-
-tcIfaceTyVar :: FastString -> IfL TyVar
-tcIfaceTyVar occ
- = do { lcl <- getLclEnv
- ; case (lookupFsEnv (if_tv_env lcl) occ) of
- Just ty_var -> return ty_var
- Nothing -> failIfM (text "Iface type variable out of scope: " <+> ppr occ)
- }
-
-lookupIfaceTyVar :: IfaceTvBndr -> IfL (Maybe TyVar)
-lookupIfaceTyVar (occ, _)
- = do { lcl <- getLclEnv
- ; return (lookupFsEnv (if_tv_env lcl) occ) }
-
-lookupIfaceVar :: IfaceBndr -> IfL (Maybe TyCoVar)
-lookupIfaceVar (IfaceIdBndr (occ, _))
- = do { lcl <- getLclEnv
- ; return (lookupFsEnv (if_id_env lcl) occ) }
-lookupIfaceVar (IfaceTvBndr (occ, _))
- = do { lcl <- getLclEnv
- ; return (lookupFsEnv (if_tv_env lcl) occ) }
-
-extendIfaceTyVarEnv :: [TyVar] -> IfL a -> IfL a
-extendIfaceTyVarEnv tyvars thing_inside
- = do { env <- getLclEnv
- ; let { tv_env' = extendFsEnvList (if_tv_env env) pairs
- ; pairs = [(occNameFS (getOccName tv), tv) | tv <- tyvars] }
- ; setLclEnv (env { if_tv_env = tv_env' }) thing_inside }
-
-extendIfaceEnvs :: [TyCoVar] -> IfL a -> IfL a
-extendIfaceEnvs tcvs thing_inside
- = extendIfaceTyVarEnv tvs $
- extendIfaceIdEnv cvs $
- thing_inside
- where
- (tvs, cvs) = partition isTyVar tcvs
-
-{-
-************************************************************************
-* *
- Getting from RdrNames to Names
-* *
-************************************************************************
--}
-
--- | Look up a top-level name from the current Iface module
-lookupIfaceTop :: OccName -> IfL Name
-lookupIfaceTop occ
- = do { env <- getLclEnv; lookupOrig (if_mod env) occ }
-
-newIfaceName :: OccName -> IfL Name
-newIfaceName occ
- = do { uniq <- newUnique
- ; return $! mkInternalName uniq occ noSrcSpan }
-
-newIfaceNames :: [OccName] -> IfL [Name]
-newIfaceNames occs
- = do { uniqs <- newUniqueSupply
- ; return [ mkInternalName uniq occ noSrcSpan
- | (occ,uniq) <- occs `zip` uniqsFromSupply uniqs] }
diff --git a/compiler/iface/IfaceEnv.hs-boot b/compiler/iface/IfaceEnv.hs-boot
deleted file mode 100644
index 025c3711a0..0000000000
--- a/compiler/iface/IfaceEnv.hs-boot
+++ /dev/null
@@ -1,9 +0,0 @@
-module IfaceEnv where
-
-import Module
-import OccName
-import TcRnMonad
-import Name
-import SrcLoc
-
-newGlobalBinder :: Module -> OccName -> SrcSpan -> TcRnIf a b Name
diff --git a/compiler/iface/IfaceSyn.hs b/compiler/iface/IfaceSyn.hs
deleted file mode 100644
index 78eb3ea271..0000000000
--- a/compiler/iface/IfaceSyn.hs
+++ /dev/null
@@ -1,2593 +0,0 @@
-{-
-(c) The University of Glasgow 2006
-(c) The GRASP/AQUA Project, Glasgow University, 1993-1998
--}
-
-{-# LANGUAGE CPP #-}
-{-# LANGUAGE LambdaCase #-}
-
-module IfaceSyn (
- module IfaceType,
-
- IfaceDecl(..), IfaceFamTyConFlav(..), IfaceClassOp(..), IfaceAT(..),
- IfaceConDecl(..), IfaceConDecls(..), IfaceEqSpec,
- IfaceExpr(..), IfaceAlt, IfaceLetBndr(..), IfaceJoinInfo(..),
- IfaceBinding(..), IfaceConAlt(..),
- IfaceIdInfo(..), IfaceIdDetails(..), IfaceUnfolding(..),
- IfaceInfoItem(..), IfaceRule(..), IfaceAnnotation(..), IfaceAnnTarget,
- IfaceClsInst(..), IfaceFamInst(..), IfaceTickish(..),
- IfaceClassBody(..),
- IfaceBang(..),
- IfaceSrcBang(..), SrcUnpackedness(..), SrcStrictness(..),
- IfaceAxBranch(..),
- IfaceTyConParent(..),
- IfaceCompleteMatch(..),
-
- -- * Binding names
- IfaceTopBndr,
- putIfaceTopBndr, getIfaceTopBndr,
-
- -- Misc
- ifaceDeclImplicitBndrs, visibleIfConDecls,
- ifaceDeclFingerprints,
-
- -- Free Names
- freeNamesIfDecl, freeNamesIfRule, freeNamesIfFamInst,
-
- -- Pretty printing
- pprIfaceExpr,
- pprIfaceDecl,
- AltPpr(..), ShowSub(..), ShowHowMuch(..), showToIface, showToHeader
- ) where
-
-#include "HsVersions.h"
-
-import GhcPrelude
-
-import IfaceType
-import BinFingerprint
-import CoreSyn( IsOrphan, isOrphan )
-import DynFlags( gopt, GeneralFlag (Opt_PrintAxiomIncomps) )
-import Demand
-import Class
-import FieldLabel
-import NameSet
-import CoAxiom ( BranchIndex )
-import Name
-import CostCentre
-import Literal
-import ForeignCall
-import Annotations( AnnPayload, AnnTarget )
-import BasicTypes
-import Outputable
-import Module
-import SrcLoc
-import Fingerprint
-import Binary
-import BooleanFormula ( BooleanFormula, pprBooleanFormula, isTrue )
-import Var( VarBndr(..), binderVar )
-import TyCon ( Role (..), Injectivity(..), tyConBndrVisArgFlag )
-import Util( dropList, filterByList, notNull, unzipWith, debugIsOn )
-import DataCon (SrcStrictness(..), SrcUnpackedness(..))
-import Lexeme (isLexSym)
-import TysWiredIn ( constraintKindTyConName )
-import Util (seqList)
-
-import Control.Monad
-import System.IO.Unsafe
-import Control.DeepSeq
-
-infixl 3 &&&
-
-{-
-************************************************************************
-* *
- Declarations
-* *
-************************************************************************
--}
-
--- | A binding top-level 'Name' in an interface file (e.g. the name of an
--- 'IfaceDecl').
-type IfaceTopBndr = Name
- -- It's convenient to have a Name in the IfaceSyn, although in each
- -- case the namespace is implied by the context. However, having an
- -- Name makes things like ifaceDeclImplicitBndrs and ifaceDeclFingerprints
- -- very convenient. Moreover, having the key of the binder means that
- -- we can encode known-key things cleverly in the symbol table. See Note
- -- [Symbol table representation of Names]
- --
- -- We don't serialise the namespace onto the disk though; rather we
- -- drop it when serialising and add it back in when deserialising.
-
-getIfaceTopBndr :: BinHandle -> IO IfaceTopBndr
-getIfaceTopBndr bh = get bh
-
-putIfaceTopBndr :: BinHandle -> IfaceTopBndr -> IO ()
-putIfaceTopBndr bh name =
- case getUserData bh of
- UserData{ ud_put_binding_name = put_binding_name } ->
- --pprTrace "putIfaceTopBndr" (ppr name) $
- put_binding_name bh name
-
-data IfaceDecl
- = IfaceId { ifName :: IfaceTopBndr,
- ifType :: IfaceType,
- ifIdDetails :: IfaceIdDetails,
- ifIdInfo :: IfaceIdInfo }
-
- | IfaceData { ifName :: IfaceTopBndr, -- Type constructor
- ifBinders :: [IfaceTyConBinder],
- ifResKind :: IfaceType, -- Result kind of type constructor
- ifCType :: Maybe CType, -- C type for CAPI FFI
- ifRoles :: [Role], -- Roles
- ifCtxt :: IfaceContext, -- The "stupid theta"
- ifCons :: IfaceConDecls, -- Includes new/data/data family info
- ifGadtSyntax :: Bool, -- True <=> declared using
- -- GADT syntax
- ifParent :: IfaceTyConParent -- The axiom, for a newtype,
- -- or data/newtype family instance
- }
-
- | IfaceSynonym { ifName :: IfaceTopBndr, -- Type constructor
- ifRoles :: [Role], -- Roles
- ifBinders :: [IfaceTyConBinder],
- ifResKind :: IfaceKind, -- Kind of the *result*
- ifSynRhs :: IfaceType }
-
- | IfaceFamily { ifName :: IfaceTopBndr, -- Type constructor
- ifResVar :: Maybe IfLclName, -- Result variable name, used
- -- only for pretty-printing
- -- with --show-iface
- ifBinders :: [IfaceTyConBinder],
- ifResKind :: IfaceKind, -- Kind of the *tycon*
- ifFamFlav :: IfaceFamTyConFlav,
- ifFamInj :: Injectivity } -- injectivity information
-
- | IfaceClass { ifName :: IfaceTopBndr, -- Name of the class TyCon
- ifRoles :: [Role], -- Roles
- ifBinders :: [IfaceTyConBinder],
- ifFDs :: [FunDep IfLclName], -- Functional dependencies
- ifBody :: IfaceClassBody -- Methods, superclasses, ATs
- }
-
- | IfaceAxiom { ifName :: IfaceTopBndr, -- Axiom name
- ifTyCon :: IfaceTyCon, -- LHS TyCon
- ifRole :: Role, -- Role of axiom
- ifAxBranches :: [IfaceAxBranch] -- Branches
- }
-
- | IfacePatSyn { ifName :: IfaceTopBndr, -- Name of the pattern synonym
- ifPatIsInfix :: Bool,
- ifPatMatcher :: (IfExtName, Bool),
- ifPatBuilder :: Maybe (IfExtName, Bool),
- -- Everything below is redundant,
- -- but needed to implement pprIfaceDecl
- ifPatUnivBndrs :: [IfaceForAllBndr],
- ifPatExBndrs :: [IfaceForAllBndr],
- ifPatProvCtxt :: IfaceContext,
- ifPatReqCtxt :: IfaceContext,
- ifPatArgs :: [IfaceType],
- ifPatTy :: IfaceType,
- ifFieldLabels :: [FieldLabel] }
-
--- See also 'ClassBody'
-data IfaceClassBody
- -- Abstract classes don't specify their body; they only occur in @hs-boot@ and
- -- @hsig@ files.
- = IfAbstractClass
- | IfConcreteClass {
- ifClassCtxt :: IfaceContext, -- Super classes
- ifATs :: [IfaceAT], -- Associated type families
- ifSigs :: [IfaceClassOp], -- Method signatures
- ifMinDef :: BooleanFormula IfLclName -- Minimal complete definition
- }
-
-data IfaceTyConParent
- = IfNoParent
- | IfDataInstance
- IfExtName -- Axiom name
- IfaceTyCon -- Family TyCon (pretty-printing only, not used in TcIface)
- -- see Note [Pretty printing via IfaceSyn] in PprTyThing
- IfaceAppArgs -- Arguments of the family TyCon
-
-data IfaceFamTyConFlav
- = IfaceDataFamilyTyCon -- Data family
- | IfaceOpenSynFamilyTyCon
- | IfaceClosedSynFamilyTyCon (Maybe (IfExtName, [IfaceAxBranch]))
- -- ^ Name of associated axiom and branches for pretty printing purposes,
- -- or 'Nothing' for an empty closed family without an axiom
- -- See Note [Pretty printing via IfaceSyn] in PprTyThing
- | IfaceAbstractClosedSynFamilyTyCon
- | IfaceBuiltInSynFamTyCon -- for pretty printing purposes only
-
-data IfaceClassOp
- = IfaceClassOp IfaceTopBndr
- IfaceType -- Class op type
- (Maybe (DefMethSpec IfaceType)) -- Default method
- -- The types of both the class op itself,
- -- and the default method, are *not* quantified
- -- over the class variables
-
-data IfaceAT = IfaceAT -- See Class.ClassATItem
- IfaceDecl -- The associated type declaration
- (Maybe IfaceType) -- Default associated type instance, if any
-
-
--- This is just like CoAxBranch
-data IfaceAxBranch = IfaceAxBranch { ifaxbTyVars :: [IfaceTvBndr]
- , ifaxbEtaTyVars :: [IfaceTvBndr]
- , ifaxbCoVars :: [IfaceIdBndr]
- , ifaxbLHS :: IfaceAppArgs
- , ifaxbRoles :: [Role]
- , ifaxbRHS :: IfaceType
- , ifaxbIncomps :: [BranchIndex] }
- -- See Note [Storing compatibility] in CoAxiom
-
-data IfaceConDecls
- = IfAbstractTyCon -- c.f TyCon.AbstractTyCon
- | IfDataTyCon [IfaceConDecl] -- Data type decls
- | IfNewTyCon IfaceConDecl -- Newtype decls
-
--- For IfDataTyCon and IfNewTyCon we store:
--- * the data constructor(s);
--- The field labels are stored individually in the IfaceConDecl
--- (there is some redundancy here, because a field label may occur
--- in multiple IfaceConDecls and represent the same field label)
-
-data IfaceConDecl
- = IfCon {
- ifConName :: IfaceTopBndr, -- Constructor name
- ifConWrapper :: Bool, -- True <=> has a wrapper
- ifConInfix :: Bool, -- True <=> declared infix
-
- -- The universal type variables are precisely those
- -- of the type constructor of this data constructor
- -- This is *easy* to guarantee when creating the IfCon
- -- but it's not so easy for the original TyCon/DataCon
- -- So this guarantee holds for IfaceConDecl, but *not* for DataCon
-
- ifConExTCvs :: [IfaceBndr], -- Existential ty/covars
- ifConUserTvBinders :: [IfaceForAllBndr],
- -- The tyvars, in the order the user wrote them
- -- INVARIANT: the set of tyvars in ifConUserTvBinders is exactly the
- -- set of tyvars (*not* covars) of ifConExTCvs, unioned
- -- with the set of ifBinders (from the parent IfaceDecl)
- -- whose tyvars do not appear in ifConEqSpec
- -- See Note [DataCon user type variable binders] in DataCon
- ifConEqSpec :: IfaceEqSpec, -- Equality constraints
- ifConCtxt :: IfaceContext, -- Non-stupid context
- ifConArgTys :: [IfaceType], -- Arg types
- ifConFields :: [FieldLabel], -- ...ditto... (field labels)
- ifConStricts :: [IfaceBang],
- -- Empty (meaning all lazy),
- -- or 1-1 corresp with arg tys
- -- See Note [Bangs on imported data constructors] in MkId
- ifConSrcStricts :: [IfaceSrcBang] } -- empty meaning no src stricts
-
-type IfaceEqSpec = [(IfLclName,IfaceType)]
-
--- | This corresponds to an HsImplBang; that is, the final
--- implementation decision about the data constructor arg
-data IfaceBang
- = IfNoBang | IfStrict | IfUnpack | IfUnpackCo IfaceCoercion
-
--- | This corresponds to HsSrcBang
-data IfaceSrcBang
- = IfSrcBang SrcUnpackedness SrcStrictness
-
-data IfaceClsInst
- = IfaceClsInst { ifInstCls :: IfExtName, -- See comments with
- ifInstTys :: [Maybe IfaceTyCon], -- the defn of ClsInst
- ifDFun :: IfExtName, -- The dfun
- ifOFlag :: OverlapFlag, -- Overlap flag
- ifInstOrph :: IsOrphan } -- See Note [Orphans] in InstEnv
- -- There's always a separate IfaceDecl for the DFun, which gives
- -- its IdInfo with its full type and version number.
- -- The instance declarations taken together have a version number,
- -- and we don't want that to wobble gratuitously
- -- If this instance decl is *used*, we'll record a usage on the dfun;
- -- and if the head does not change it won't be used if it wasn't before
-
--- The ifFamInstTys field of IfaceFamInst contains a list of the rough
--- match types
-data IfaceFamInst
- = IfaceFamInst { ifFamInstFam :: IfExtName -- Family name
- , ifFamInstTys :: [Maybe IfaceTyCon] -- See above
- , ifFamInstAxiom :: IfExtName -- The axiom
- , ifFamInstOrph :: IsOrphan -- Just like IfaceClsInst
- }
-
-data IfaceRule
- = IfaceRule {
- ifRuleName :: RuleName,
- ifActivation :: Activation,
- ifRuleBndrs :: [IfaceBndr], -- Tyvars and term vars
- ifRuleHead :: IfExtName, -- Head of lhs
- ifRuleArgs :: [IfaceExpr], -- Args of LHS
- ifRuleRhs :: IfaceExpr,
- ifRuleAuto :: Bool,
- ifRuleOrph :: IsOrphan -- Just like IfaceClsInst
- }
-
-data IfaceAnnotation
- = IfaceAnnotation {
- ifAnnotatedTarget :: IfaceAnnTarget,
- ifAnnotatedValue :: AnnPayload
- }
-
-type IfaceAnnTarget = AnnTarget OccName
-
-data IfaceCompleteMatch = IfaceCompleteMatch [IfExtName] IfExtName
-
-instance Outputable IfaceCompleteMatch where
- ppr (IfaceCompleteMatch cls ty) = text "COMPLETE" <> colon <+> ppr cls
- <+> dcolon <+> ppr ty
-
-
-
-
--- Here's a tricky case:
--- * Compile with -O module A, and B which imports A.f
--- * Change function f in A, and recompile without -O
--- * When we read in old A.hi we read in its IdInfo (as a thunk)
--- (In earlier GHCs we used to drop IdInfo immediately on reading,
--- but we do not do that now. Instead it's discarded when the
--- ModIface is read into the various decl pools.)
--- * The version comparison sees that new (=NoInfo) differs from old (=HasInfo *)
--- and so gives a new version.
-
-data IfaceIdInfo
- = NoInfo -- When writing interface file without -O
- | HasInfo [IfaceInfoItem] -- Has info, and here it is
-
-data IfaceInfoItem
- = HsArity Arity
- | HsStrictness StrictSig
- | HsInline InlinePragma
- | HsUnfold Bool -- True <=> isStrongLoopBreaker is true
- IfaceUnfolding -- See Note [Expose recursive functions]
- | HsNoCafRefs
- | HsLevity -- Present <=> never levity polymorphic
-
--- NB: Specialisations and rules come in separately and are
--- only later attached to the Id. Partial reason: some are orphans.
-
-data IfaceUnfolding
- = IfCoreUnfold Bool IfaceExpr -- True <=> INLINABLE, False <=> regular unfolding
- -- Possibly could eliminate the Bool here, the information
- -- is also in the InlinePragma.
-
- | IfCompulsory IfaceExpr -- Only used for default methods, in fact
-
- | IfInlineRule Arity -- INLINE pragmas
- Bool -- OK to inline even if *un*-saturated
- Bool -- OK to inline even if context is boring
- IfaceExpr
-
- | IfDFunUnfold [IfaceBndr] [IfaceExpr]
-
-
--- We only serialise the IdDetails of top-level Ids, and even then
--- we only need a very limited selection. Notably, none of the
--- implicit ones are needed here, because they are not put it
--- interface files
-
-data IfaceIdDetails
- = IfVanillaId
- | IfRecSelId (Either IfaceTyCon IfaceDecl) Bool
- | IfDFunId
-
-{-
-Note [Versioning of instances]
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-See [https://gitlab.haskell.org/ghc/ghc/wikis/commentary/compiler/recompilation-avoidance#instances]
-
-
-************************************************************************
-* *
- Functions over declarations
-* *
-************************************************************************
--}
-
-visibleIfConDecls :: IfaceConDecls -> [IfaceConDecl]
-visibleIfConDecls IfAbstractTyCon = []
-visibleIfConDecls (IfDataTyCon cs) = cs
-visibleIfConDecls (IfNewTyCon c) = [c]
-
-ifaceDeclImplicitBndrs :: IfaceDecl -> [OccName]
--- *Excludes* the 'main' name, but *includes* the implicitly-bound names
--- Deeply revolting, because it has to predict what gets bound,
--- especially the question of whether there's a wrapper for a datacon
--- See Note [Implicit TyThings] in HscTypes
-
--- N.B. the set of names returned here *must* match the set of
--- TyThings returned by HscTypes.implicitTyThings, in the sense that
--- TyThing.getOccName should define a bijection between the two lists.
--- This invariant is used in LoadIface.loadDecl (see note [Tricky iface loop])
--- The order of the list does not matter.
-
-ifaceDeclImplicitBndrs (IfaceData {ifName = tc_name, ifCons = cons })
- = case cons of
- IfAbstractTyCon -> []
- IfNewTyCon cd -> mkNewTyCoOcc (occName tc_name) : ifaceConDeclImplicitBndrs cd
- IfDataTyCon cds -> concatMap ifaceConDeclImplicitBndrs cds
-
-ifaceDeclImplicitBndrs (IfaceClass { ifBody = IfAbstractClass })
- = []
-
-ifaceDeclImplicitBndrs (IfaceClass { ifName = cls_tc_name
- , ifBody = IfConcreteClass {
- ifClassCtxt = sc_ctxt,
- ifSigs = sigs,
- ifATs = ats
- }})
- = -- (possibly) newtype coercion
- co_occs ++
- -- data constructor (DataCon namespace)
- -- data worker (Id namespace)
- -- no wrapper (class dictionaries never have a wrapper)
- [dc_occ, dcww_occ] ++
- -- associated types
- [occName (ifName at) | IfaceAT at _ <- ats ] ++
- -- superclass selectors
- [mkSuperDictSelOcc n cls_tc_occ | n <- [1..n_ctxt]] ++
- -- operation selectors
- [occName op | IfaceClassOp op _ _ <- sigs]
- where
- cls_tc_occ = occName cls_tc_name
- n_ctxt = length sc_ctxt
- n_sigs = length sigs
- co_occs | is_newtype = [mkNewTyCoOcc cls_tc_occ]
- | otherwise = []
- dcww_occ = mkDataConWorkerOcc dc_occ
- dc_occ = mkClassDataConOcc cls_tc_occ
- is_newtype = n_sigs + n_ctxt == 1 -- Sigh (keep this synced with buildClass)
-
-ifaceDeclImplicitBndrs _ = []
-
-ifaceConDeclImplicitBndrs :: IfaceConDecl -> [OccName]
-ifaceConDeclImplicitBndrs (IfCon {
- ifConWrapper = has_wrapper, ifConName = con_name })
- = [occName con_name, work_occ] ++ wrap_occs
- where
- con_occ = occName con_name
- work_occ = mkDataConWorkerOcc con_occ -- Id namespace
- wrap_occs | has_wrapper = [mkDataConWrapperOcc con_occ] -- Id namespace
- | otherwise = []
-
--- -----------------------------------------------------------------------------
--- The fingerprints of an IfaceDecl
-
- -- We better give each name bound by the declaration a
- -- different fingerprint! So we calculate the fingerprint of
- -- each binder by combining the fingerprint of the whole
- -- declaration with the name of the binder. (#5614, #7215)
-ifaceDeclFingerprints :: Fingerprint -> IfaceDecl -> [(OccName,Fingerprint)]
-ifaceDeclFingerprints hash decl
- = (getOccName decl, hash) :
- [ (occ, computeFingerprint' (hash,occ))
- | occ <- ifaceDeclImplicitBndrs decl ]
- where
- computeFingerprint' =
- unsafeDupablePerformIO
- . computeFingerprint (panic "ifaceDeclFingerprints")
-
-{-
-************************************************************************
-* *
- Expressions
-* *
-************************************************************************
--}
-
-data IfaceExpr
- = IfaceLcl IfLclName
- | IfaceExt IfExtName
- | IfaceType IfaceType
- | IfaceCo IfaceCoercion
- | IfaceTuple TupleSort [IfaceExpr] -- Saturated; type arguments omitted
- | IfaceLam IfaceLamBndr IfaceExpr
- | IfaceApp IfaceExpr IfaceExpr
- | IfaceCase IfaceExpr IfLclName [IfaceAlt]
- | IfaceECase IfaceExpr IfaceType -- See Note [Empty case alternatives]
- | IfaceLet IfaceBinding IfaceExpr
- | IfaceCast IfaceExpr IfaceCoercion
- | IfaceLit Literal
- | IfaceFCall ForeignCall IfaceType
- | IfaceTick IfaceTickish IfaceExpr -- from Tick tickish E
-
-data IfaceTickish
- = IfaceHpcTick Module Int -- from HpcTick x
- | IfaceSCC CostCentre Bool Bool -- from ProfNote
- | IfaceSource RealSrcSpan String -- from SourceNote
- -- no breakpoints: we never export these into interface files
-
-type IfaceAlt = (IfaceConAlt, [IfLclName], IfaceExpr)
- -- Note: IfLclName, not IfaceBndr (and same with the case binder)
- -- We reconstruct the kind/type of the thing from the context
- -- thus saving bulk in interface files
-
-data IfaceConAlt = IfaceDefault
- | IfaceDataAlt IfExtName
- | IfaceLitAlt Literal
-
-data IfaceBinding
- = IfaceNonRec IfaceLetBndr IfaceExpr
- | IfaceRec [(IfaceLetBndr, IfaceExpr)]
-
--- IfaceLetBndr is like IfaceIdBndr, but has IdInfo too
--- It's used for *non-top-level* let/rec binders
--- See Note [IdInfo on nested let-bindings]
-data IfaceLetBndr = IfLetBndr IfLclName IfaceType IfaceIdInfo IfaceJoinInfo
-
-data IfaceJoinInfo = IfaceNotJoinPoint
- | IfaceJoinPoint JoinArity
-
-{-
-Note [Empty case alternatives]
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-In IfaceSyn an IfaceCase does not record the types of the alternatives,
-unlike CorSyn Case. But we need this type if the alternatives are empty.
-Hence IfaceECase. See Note [Empty case alternatives] in CoreSyn.
-
-Note [Expose recursive functions]
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-For supercompilation we want to put *all* unfoldings in the interface
-file, even for functions that are recursive (or big). So we need to
-know when an unfolding belongs to a loop-breaker so that we can refrain
-from inlining it (except during supercompilation).
-
-Note [IdInfo on nested let-bindings]
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-Occasionally we want to preserve IdInfo on nested let bindings. The one
-that came up was a NOINLINE pragma on a let-binding inside an INLINE
-function. The user (Duncan Coutts) really wanted the NOINLINE control
-to cross the separate compilation boundary.
-
-In general we retain all info that is left by CoreTidy.tidyLetBndr, since
-that is what is seen by importing module with --make
-
-Note [Displaying axiom incompatibilities]
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-With -fprint-axiom-incomps we display which closed type family equations
-are incompatible with which. This information is sometimes necessary
-because GHC doesn't try equations in order: any equation can be used when
-all preceding equations that are incompatible with it do not apply.
-
-For example, the last "a && a = a" equation in Data.Type.Bool.&& is
-actually compatible with all previous equations, and can reduce at any
-time.
-
-This is displayed as:
-Prelude> :i Data.Type.Equality.==
-type family (==) (a :: k) (b :: k) :: Bool
- where
- {- #0 -} (==) (f a) (g b) = (f == g) && (a == b)
- {- #1 -} (==) a a = 'True
- -- incompatible with: #0
- {- #2 -} (==) _1 _2 = 'False
- -- incompatible with: #1, #0
-The comment after an equation refers to all previous equations (0-indexed)
-that are incompatible with it.
-
-************************************************************************
-* *
- Printing IfaceDecl
-* *
-************************************************************************
--}
-
-pprAxBranch :: SDoc -> BranchIndex -> IfaceAxBranch -> SDoc
--- The TyCon might be local (just an OccName), or this might
--- be a branch for an imported TyCon, so it would be an ExtName
--- So it's easier to take an SDoc here
---
--- This function is used
--- to print interface files,
--- in debug messages
--- in :info F for GHCi, which goes via toConToIfaceDecl on the family tycon
--- For user error messages we use Coercion.pprCoAxiom and friends
-pprAxBranch pp_tc idx (IfaceAxBranch { ifaxbTyVars = tvs
- , ifaxbCoVars = _cvs
- , ifaxbLHS = pat_tys
- , ifaxbRHS = rhs
- , ifaxbIncomps = incomps })
- = ASSERT2( null _cvs, pp_tc $$ ppr _cvs )
- hang ppr_binders 2 (hang pp_lhs 2 (equals <+> ppr rhs))
- $+$
- nest 4 maybe_incomps
- where
- -- See Note [Printing foralls in type family instances] in IfaceType
- ppr_binders = maybe_index <+>
- pprUserIfaceForAll (map (mkIfaceForAllTvBndr Specified) tvs)
- pp_lhs = hang pp_tc 2 (pprParendIfaceAppArgs pat_tys)
-
- -- See Note [Displaying axiom incompatibilities]
- maybe_index
- = sdocWithDynFlags $ \dflags ->
- ppWhen (gopt Opt_PrintAxiomIncomps dflags) $
- text "{-" <+> (text "#" <> ppr idx) <+> text "-}"
- maybe_incomps
- = sdocWithDynFlags $ \dflags ->
- ppWhen (gopt Opt_PrintAxiomIncomps dflags && notNull incomps) $
- text "--" <+> text "incompatible with:"
- <+> pprWithCommas (\incomp -> text "#" <> ppr incomp) incomps
-
-instance Outputable IfaceAnnotation where
- ppr (IfaceAnnotation target value) = ppr target <+> colon <+> ppr value
-
-instance NamedThing IfaceClassOp where
- getName (IfaceClassOp n _ _) = n
-
-instance HasOccName IfaceClassOp where
- occName = getOccName
-
-instance NamedThing IfaceConDecl where
- getName = ifConName
-
-instance HasOccName IfaceConDecl where
- occName = getOccName
-
-instance NamedThing IfaceDecl where
- getName = ifName
-
-instance HasOccName IfaceDecl where
- occName = getOccName
-
-instance Outputable IfaceDecl where
- ppr = pprIfaceDecl showToIface
-
-{-
-Note [Minimal complete definition] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-The minimal complete definition should only be included if a complete
-class definition is shown. Since the minimal complete definition is
-anonymous we can't reuse the same mechanism that is used for the
-filtering of method signatures. Instead we just check if anything at all is
-filtered and hide it in that case.
--}
-
-data ShowSub
- = ShowSub
- { ss_how_much :: ShowHowMuch
- , ss_forall :: ShowForAllFlag }
-
--- See Note [Printing IfaceDecl binders]
--- The alternative pretty printer referred to in the note.
-newtype AltPpr = AltPpr (Maybe (OccName -> SDoc))
-
-data ShowHowMuch
- = ShowHeader AltPpr -- ^Header information only, not rhs
- | ShowSome [OccName] AltPpr
- -- ^ Show only some sub-components. Specifically,
- --
- -- [@[]@] Print all sub-components.
- -- [@(n:ns)@] Print sub-component @n@ with @ShowSub = ns@;
- -- elide other sub-components to @...@
- -- May 14: the list is max 1 element long at the moment
- | ShowIface
- -- ^Everything including GHC-internal information (used in --show-iface)
-
-{-
-Note [Printing IfaceDecl binders]
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-The binders in an IfaceDecl are just OccNames, so we don't know what module they
-come from. But when we pretty-print a TyThing by converting to an IfaceDecl
-(see PprTyThing), the TyThing may come from some other module so we really need
-the module qualifier. We solve this by passing in a pretty-printer for the
-binders.
-
-When printing an interface file (--show-iface), we want to print
-everything unqualified, so we can just print the OccName directly.
--}
-
-instance Outputable ShowHowMuch where
- ppr (ShowHeader _) = text "ShowHeader"
- ppr ShowIface = text "ShowIface"
- ppr (ShowSome occs _) = text "ShowSome" <+> ppr occs
-
-showToHeader :: ShowSub
-showToHeader = ShowSub { ss_how_much = ShowHeader $ AltPpr Nothing
- , ss_forall = ShowForAllWhen }
-
-showToIface :: ShowSub
-showToIface = ShowSub { ss_how_much = ShowIface
- , ss_forall = ShowForAllWhen }
-
-ppShowIface :: ShowSub -> SDoc -> SDoc
-ppShowIface (ShowSub { ss_how_much = ShowIface }) doc = doc
-ppShowIface _ _ = Outputable.empty
-
--- show if all sub-components or the complete interface is shown
-ppShowAllSubs :: ShowSub -> SDoc -> SDoc -- Note [Minimal complete definition]
-ppShowAllSubs (ShowSub { ss_how_much = ShowSome [] _ }) doc = doc
-ppShowAllSubs (ShowSub { ss_how_much = ShowIface }) doc = doc
-ppShowAllSubs _ _ = Outputable.empty
-
-ppShowRhs :: ShowSub -> SDoc -> SDoc
-ppShowRhs (ShowSub { ss_how_much = ShowHeader _ }) _ = Outputable.empty
-ppShowRhs _ doc = doc
-
-showSub :: HasOccName n => ShowSub -> n -> Bool
-showSub (ShowSub { ss_how_much = ShowHeader _ }) _ = False
-showSub (ShowSub { ss_how_much = ShowSome (n:_) _ }) thing = n == occName thing
-showSub (ShowSub { ss_how_much = _ }) _ = True
-
-ppr_trim :: [Maybe SDoc] -> [SDoc]
--- Collapse a group of Nothings to a single "..."
-ppr_trim xs
- = snd (foldr go (False, []) xs)
- where
- go (Just doc) (_, so_far) = (False, doc : so_far)
- go Nothing (True, so_far) = (True, so_far)
- go Nothing (False, so_far) = (True, text "..." : so_far)
-
-isIfaceDataInstance :: IfaceTyConParent -> Bool
-isIfaceDataInstance IfNoParent = False
-isIfaceDataInstance _ = True
-
-pprClassRoles :: ShowSub -> IfaceTopBndr -> [IfaceTyConBinder] -> [Role] -> SDoc
-pprClassRoles ss clas binders roles =
- pprRoles (== Nominal)
- (pprPrefixIfDeclBndr (ss_how_much ss) (occName clas))
- binders
- roles
-
-pprClassStandaloneKindSig :: ShowSub -> IfaceTopBndr -> IfaceKind -> SDoc
-pprClassStandaloneKindSig ss clas =
- pprStandaloneKindSig (pprPrefixIfDeclBndr (ss_how_much ss) (occName clas))
-
-constraintIfaceKind :: IfaceKind
-constraintIfaceKind =
- IfaceTyConApp (IfaceTyCon constraintKindTyConName (IfaceTyConInfo NotPromoted IfaceNormalTyCon)) IA_Nil
-
-pprIfaceDecl :: ShowSub -> IfaceDecl -> SDoc
--- NB: pprIfaceDecl is also used for pretty-printing TyThings in GHCi
--- See Note [Pretty-printing TyThings] in PprTyThing
-pprIfaceDecl ss (IfaceData { ifName = tycon, ifCType = ctype,
- ifCtxt = context, ifResKind = kind,
- ifRoles = roles, ifCons = condecls,
- ifParent = parent,
- ifGadtSyntax = gadt,
- ifBinders = binders })
-
- | gadt = vcat [ pp_roles
- , pp_ki_sig
- , pp_nd <+> pp_lhs <+> pp_kind <+> pp_where
- , nest 2 (vcat pp_cons)
- , nest 2 $ ppShowIface ss pp_extra ]
- | otherwise = vcat [ pp_roles
- , pp_ki_sig
- , hang (pp_nd <+> pp_lhs) 2 (add_bars pp_cons)
- , nest 2 $ ppShowIface ss pp_extra ]
- where
- is_data_instance = isIfaceDataInstance parent
- -- See Note [Printing foralls in type family instances] in IfaceType
- pp_data_inst_forall :: SDoc
- pp_data_inst_forall = pprUserIfaceForAll forall_bndrs
-
- forall_bndrs :: [IfaceForAllBndr]
- forall_bndrs = [Bndr (binderVar tc_bndr) Specified | tc_bndr <- binders]
-
- cons = visibleIfConDecls condecls
- pp_where = ppWhen (gadt && not (null cons)) $ text "where"
- pp_cons = ppr_trim (map show_con cons) :: [SDoc]
- pp_kind = ppUnless (if ki_sig_printable
- then isIfaceTauType kind
- -- Even in the presence of a standalone kind signature, a non-tau
- -- result kind annotation cannot be discarded as it determines the arity.
- -- See Note [Arity inference in kcDeclHeader_sig] in TcHsType
- else isIfaceLiftedTypeKind kind)
- (dcolon <+> ppr kind)
-
- pp_lhs = case parent of
- IfNoParent -> pprIfaceDeclHead suppress_bndr_sig context ss tycon binders
- IfDataInstance{}
- -> text "instance" <+> pp_data_inst_forall
- <+> pprIfaceTyConParent parent
-
- pp_roles
- | is_data_instance = empty
- | otherwise = pprRoles (== Representational) name_doc binders roles
- -- Don't display roles for data family instances (yet)
- -- See discussion on #8672.
-
- ki_sig_printable =
- -- If we print a standalone kind signature for a data instance, we leak
- -- the internal constructor name:
- --
- -- type T15827.R:Dka :: forall k. k -> *
- -- data instance forall k (a :: k). D a = MkD (Proxy a)
- --
- -- This T15827.R:Dka is a compiler-generated type constructor for the
- -- data instance.
- not is_data_instance
-
- pp_ki_sig = ppWhen ki_sig_printable $
- pprStandaloneKindSig name_doc (mkIfaceTyConKind binders kind)
-
- -- See Note [Suppressing binder signatures] in IfaceType
- suppress_bndr_sig = SuppressBndrSig ki_sig_printable
-
- name_doc = pprPrefixIfDeclBndr (ss_how_much ss) (occName tycon)
-
- add_bars [] = Outputable.empty
- add_bars (c:cs) = sep ((equals <+> c) : map (vbar <+>) cs)
-
- ok_con dc = showSub ss dc || any (showSub ss . flSelector) (ifConFields dc)
-
- show_con dc
- | ok_con dc = Just $ pprIfaceConDecl ss gadt tycon binders parent dc
- | otherwise = Nothing
-
- pp_nd = case condecls of
- IfAbstractTyCon{} -> text "data"
- IfDataTyCon{} -> text "data"
- IfNewTyCon{} -> text "newtype"
-
- pp_extra = vcat [pprCType ctype]
-
-pprIfaceDecl ss (IfaceClass { ifName = clas
- , ifRoles = roles
- , ifFDs = fds
- , ifBinders = binders
- , ifBody = IfAbstractClass })
- = vcat [ pprClassRoles ss clas binders roles
- , pprClassStandaloneKindSig ss clas (mkIfaceTyConKind binders constraintIfaceKind)
- , text "class" <+> pprIfaceDeclHead suppress_bndr_sig [] ss clas binders <+> pprFundeps fds ]
- where
- -- See Note [Suppressing binder signatures] in IfaceType
- suppress_bndr_sig = SuppressBndrSig True
-
-pprIfaceDecl ss (IfaceClass { ifName = clas
- , ifRoles = roles
- , ifFDs = fds
- , ifBinders = binders
- , ifBody = IfConcreteClass {
- ifATs = ats,
- ifSigs = sigs,
- ifClassCtxt = context,
- ifMinDef = minDef
- }})
- = vcat [ pprClassRoles ss clas binders roles
- , pprClassStandaloneKindSig ss clas (mkIfaceTyConKind binders constraintIfaceKind)
- , text "class" <+> pprIfaceDeclHead suppress_bndr_sig context ss clas binders <+> pprFundeps fds <+> pp_where
- , nest 2 (vcat [ vcat asocs, vcat dsigs
- , ppShowAllSubs ss (pprMinDef minDef)])]
- where
- pp_where = ppShowRhs ss $ ppUnless (null sigs && null ats) (text "where")
-
- asocs = ppr_trim $ map maybeShowAssoc ats
- dsigs = ppr_trim $ map maybeShowSig sigs
-
- maybeShowAssoc :: IfaceAT -> Maybe SDoc
- maybeShowAssoc asc@(IfaceAT d _)
- | showSub ss d = Just $ pprIfaceAT ss asc
- | otherwise = Nothing
-
- maybeShowSig :: IfaceClassOp -> Maybe SDoc
- maybeShowSig sg
- | showSub ss sg = Just $ pprIfaceClassOp ss sg
- | otherwise = Nothing
-
- pprMinDef :: BooleanFormula IfLclName -> SDoc
- pprMinDef minDef = ppUnless (isTrue minDef) $ -- hide empty definitions
- text "{-# MINIMAL" <+>
- pprBooleanFormula
- (\_ def -> cparen (isLexSym def) (ppr def)) 0 minDef <+>
- text "#-}"
-
- -- See Note [Suppressing binder signatures] in IfaceType
- suppress_bndr_sig = SuppressBndrSig True
-
-pprIfaceDecl ss (IfaceSynonym { ifName = tc
- , ifBinders = binders
- , ifSynRhs = mono_ty
- , ifResKind = res_kind})
- = vcat [ pprStandaloneKindSig name_doc (mkIfaceTyConKind binders res_kind)
- , hang (text "type" <+> pprIfaceDeclHead suppress_bndr_sig [] ss tc binders <+> equals)
- 2 (sep [ pprIfaceForAll tvs, pprIfaceContextArr theta, ppr tau
- , ppUnless (isIfaceLiftedTypeKind res_kind) (dcolon <+> ppr res_kind) ])
- ]
- where
- (tvs, theta, tau) = splitIfaceSigmaTy mono_ty
- name_doc = pprPrefixIfDeclBndr (ss_how_much ss) (occName tc)
-
- -- See Note [Suppressing binder signatures] in IfaceType
- suppress_bndr_sig = SuppressBndrSig True
-
-pprIfaceDecl ss (IfaceFamily { ifName = tycon
- , ifFamFlav = rhs, ifBinders = binders
- , ifResKind = res_kind
- , ifResVar = res_var, ifFamInj = inj })
- | IfaceDataFamilyTyCon <- rhs
- = vcat [ pprStandaloneKindSig name_doc (mkIfaceTyConKind binders res_kind)
- , text "data family" <+> pprIfaceDeclHead suppress_bndr_sig [] ss tycon binders
- ]
-
- | otherwise
- = vcat [ pprStandaloneKindSig name_doc (mkIfaceTyConKind binders res_kind)
- , hang (text "type family"
- <+> pprIfaceDeclHead suppress_bndr_sig [] ss tycon binders
- <+> ppShowRhs ss (pp_where rhs))
- 2 (pp_inj res_var inj <+> ppShowRhs ss (pp_rhs rhs))
- $$
- nest 2 (ppShowRhs ss (pp_branches rhs))
- ]
- where
- name_doc = pprPrefixIfDeclBndr (ss_how_much ss) (occName tycon)
-
- pp_where (IfaceClosedSynFamilyTyCon {}) = text "where"
- pp_where _ = empty
-
- pp_inj Nothing _ = empty
- pp_inj (Just res) inj
- | Injective injectivity <- inj = hsep [ equals, ppr res
- , pp_inj_cond res injectivity]
- | otherwise = hsep [ equals, ppr res ]
-
- pp_inj_cond res inj = case filterByList inj binders of
- [] -> empty
- tvs -> hsep [vbar, ppr res, text "->", interppSP (map ifTyConBinderName tvs)]
-
- pp_rhs IfaceDataFamilyTyCon
- = ppShowIface ss (text "data")
- pp_rhs IfaceOpenSynFamilyTyCon
- = ppShowIface ss (text "open")
- pp_rhs IfaceAbstractClosedSynFamilyTyCon
- = ppShowIface ss (text "closed, abstract")
- pp_rhs (IfaceClosedSynFamilyTyCon {})
- = empty -- see pp_branches
- pp_rhs IfaceBuiltInSynFamTyCon
- = ppShowIface ss (text "built-in")
-
- pp_branches (IfaceClosedSynFamilyTyCon (Just (ax, brs)))
- = vcat (unzipWith (pprAxBranch
- (pprPrefixIfDeclBndr
- (ss_how_much ss)
- (occName tycon))
- ) $ zip [0..] brs)
- $$ ppShowIface ss (text "axiom" <+> ppr ax)
- pp_branches _ = Outputable.empty
-
- -- See Note [Suppressing binder signatures] in IfaceType
- suppress_bndr_sig = SuppressBndrSig True
-
-pprIfaceDecl _ (IfacePatSyn { ifName = name,
- ifPatUnivBndrs = univ_bndrs, ifPatExBndrs = ex_bndrs,
- ifPatProvCtxt = prov_ctxt, ifPatReqCtxt = req_ctxt,
- ifPatArgs = arg_tys,
- ifPatTy = pat_ty} )
- = sdocWithDynFlags mk_msg
- where
- mk_msg dflags
- = hang (text "pattern" <+> pprPrefixOcc name)
- 2 (dcolon <+> sep [univ_msg
- , pprIfaceContextArr req_ctxt
- , ppWhen insert_empty_ctxt $ parens empty <+> darrow
- , ex_msg
- , pprIfaceContextArr prov_ctxt
- , pprIfaceType $ foldr (IfaceFunTy VisArg) pat_ty arg_tys ])
- where
- univ_msg = pprUserIfaceForAll univ_bndrs
- ex_msg = pprUserIfaceForAll ex_bndrs
-
- insert_empty_ctxt = null req_ctxt
- && not (null prov_ctxt && isEmpty dflags ex_msg)
-
-pprIfaceDecl ss (IfaceId { ifName = var, ifType = ty,
- ifIdDetails = details, ifIdInfo = info })
- = vcat [ hang (pprPrefixIfDeclBndr (ss_how_much ss) (occName var) <+> dcolon)
- 2 (pprIfaceSigmaType (ss_forall ss) ty)
- , ppShowIface ss (ppr details)
- , ppShowIface ss (ppr info) ]
-
-pprIfaceDecl _ (IfaceAxiom { ifName = name, ifTyCon = tycon
- , ifAxBranches = branches })
- = hang (text "axiom" <+> ppr name <+> dcolon)
- 2 (vcat $ unzipWith (pprAxBranch (ppr tycon)) $ zip [0..] branches)
-
-pprCType :: Maybe CType -> SDoc
-pprCType Nothing = Outputable.empty
-pprCType (Just cType) = text "C type:" <+> ppr cType
-
--- if, for each role, suppress_if role is True, then suppress the role
--- output
-pprRoles :: (Role -> Bool) -> SDoc -> [IfaceTyConBinder]
- -> [Role] -> SDoc
-pprRoles suppress_if tyCon bndrs roles
- = sdocWithDynFlags $ \dflags ->
- let froles = suppressIfaceInvisibles dflags bndrs roles
- in ppUnless (all suppress_if froles || null froles) $
- text "type role" <+> tyCon <+> hsep (map ppr froles)
-
-pprStandaloneKindSig :: SDoc -> IfaceType -> SDoc
-pprStandaloneKindSig tyCon ty = text "type" <+> tyCon <+> text "::" <+> ppr ty
-
-pprInfixIfDeclBndr :: ShowHowMuch -> OccName -> SDoc
-pprInfixIfDeclBndr (ShowSome _ (AltPpr (Just ppr_bndr))) name
- = pprInfixVar (isSymOcc name) (ppr_bndr name)
-pprInfixIfDeclBndr _ name
- = pprInfixVar (isSymOcc name) (ppr name)
-
-pprPrefixIfDeclBndr :: ShowHowMuch -> OccName -> SDoc
-pprPrefixIfDeclBndr (ShowHeader (AltPpr (Just ppr_bndr))) name
- = parenSymOcc name (ppr_bndr name)
-pprPrefixIfDeclBndr (ShowSome _ (AltPpr (Just ppr_bndr))) name
- = parenSymOcc name (ppr_bndr name)
-pprPrefixIfDeclBndr _ name
- = parenSymOcc name (ppr name)
-
-instance Outputable IfaceClassOp where
- ppr = pprIfaceClassOp showToIface
-
-pprIfaceClassOp :: ShowSub -> IfaceClassOp -> SDoc
-pprIfaceClassOp ss (IfaceClassOp n ty dm)
- = pp_sig n ty $$ generic_dm
- where
- generic_dm | Just (GenericDM dm_ty) <- dm
- = text "default" <+> pp_sig n dm_ty
- | otherwise
- = empty
- pp_sig n ty
- = pprPrefixIfDeclBndr (ss_how_much ss) (occName n)
- <+> dcolon
- <+> pprIfaceSigmaType ShowForAllWhen ty
-
-instance Outputable IfaceAT where
- ppr = pprIfaceAT showToIface
-
-pprIfaceAT :: ShowSub -> IfaceAT -> SDoc
-pprIfaceAT ss (IfaceAT d mb_def)
- = vcat [ pprIfaceDecl ss d
- , case mb_def of
- Nothing -> Outputable.empty
- Just rhs -> nest 2 $
- text "Default:" <+> ppr rhs ]
-
-instance Outputable IfaceTyConParent where
- ppr p = pprIfaceTyConParent p
-
-pprIfaceTyConParent :: IfaceTyConParent -> SDoc
-pprIfaceTyConParent IfNoParent
- = Outputable.empty
-pprIfaceTyConParent (IfDataInstance _ tc tys)
- = pprIfaceTypeApp topPrec tc tys
-
-pprIfaceDeclHead :: SuppressBndrSig
- -> IfaceContext -> ShowSub -> Name
- -> [IfaceTyConBinder] -- of the tycon, for invisible-suppression
- -> SDoc
-pprIfaceDeclHead suppress_sig context ss tc_occ bndrs
- = sdocWithDynFlags $ \ dflags ->
- sep [ pprIfaceContextArr context
- , pprPrefixIfDeclBndr (ss_how_much ss) (occName tc_occ)
- <+> pprIfaceTyConBinders suppress_sig
- (suppressIfaceInvisibles dflags bndrs bndrs) ]
-
-pprIfaceConDecl :: ShowSub -> Bool
- -> IfaceTopBndr
- -> [IfaceTyConBinder]
- -> IfaceTyConParent
- -> IfaceConDecl -> SDoc
-pprIfaceConDecl ss gadt_style tycon tc_binders parent
- (IfCon { ifConName = name, ifConInfix = is_infix,
- ifConUserTvBinders = user_tvbs,
- ifConEqSpec = eq_spec, ifConCtxt = ctxt, ifConArgTys = arg_tys,
- ifConStricts = stricts, ifConFields = fields })
- | gadt_style = pp_prefix_con <+> dcolon <+> ppr_gadt_ty
- | otherwise = ppr_ex_quant pp_h98_con
- where
- pp_h98_con
- | not (null fields) = pp_prefix_con <+> pp_field_args
- | is_infix
- , [ty1, ty2] <- pp_args
- = sep [ ty1
- , pprInfixIfDeclBndr how_much (occName name)
- , ty2]
- | otherwise = pp_prefix_con <+> sep pp_args
-
- how_much = ss_how_much ss
- tys_w_strs :: [(IfaceBang, IfaceType)]
- tys_w_strs = zip stricts arg_tys
- pp_prefix_con = pprPrefixIfDeclBndr how_much (occName name)
-
- -- If we're pretty-printing a H98-style declaration with existential
- -- quantification, then user_tvbs will always consist of the universal
- -- tyvar binders followed by the existential tyvar binders. So to recover
- -- the visibilities of the existential tyvar binders, we can simply drop
- -- the universal tyvar binders from user_tvbs.
- ex_tvbs = dropList tc_binders user_tvbs
- ppr_ex_quant = pprIfaceForAllPartMust ex_tvbs ctxt
- pp_gadt_res_ty = mk_user_con_res_ty eq_spec
- ppr_gadt_ty = pprIfaceForAllPart user_tvbs ctxt pp_tau
-
- -- A bit gruesome this, but we can't form the full con_tau, and ppr it,
- -- because we don't have a Name for the tycon, only an OccName
- pp_tau | null fields
- = case pp_args ++ [pp_gadt_res_ty] of
- (t:ts) -> fsep (t : map (arrow <+>) ts)
- [] -> panic "pp_con_taus"
- | otherwise
- = sep [pp_field_args, arrow <+> pp_gadt_res_ty]
-
- ppr_bang IfNoBang = whenPprDebug $ char '_'
- ppr_bang IfStrict = char '!'
- ppr_bang IfUnpack = text "{-# UNPACK #-}"
- ppr_bang (IfUnpackCo co) = text "! {-# UNPACK #-}" <>
- pprParendIfaceCoercion co
-
- pprFieldArgTy, pprArgTy :: (IfaceBang, IfaceType) -> SDoc
- -- If using record syntax, the only reason one would need to parenthesize
- -- a compound field type is if it's preceded by a bang pattern.
- pprFieldArgTy (bang, ty) = ppr_arg_ty (bang_prec bang) bang ty
- -- If not using record syntax, a compound field type might need to be
- -- parenthesized if one of the following holds:
- --
- -- 1. We're using Haskell98 syntax.
- -- 2. The field type is preceded with a bang pattern.
- pprArgTy (bang, ty) = ppr_arg_ty (max gadt_prec (bang_prec bang)) bang ty
-
- ppr_arg_ty :: PprPrec -> IfaceBang -> IfaceType -> SDoc
- ppr_arg_ty prec bang ty = ppr_bang bang <> pprPrecIfaceType prec ty
-
- -- If we're displaying the fields GADT-style, e.g.,
- --
- -- data Foo a where
- -- MkFoo :: (Int -> Int) -> Maybe a -> Foo
- --
- -- Then we use `funPrec`, since that will ensure `Int -> Int` gets the
- -- parentheses that it requires, but simple compound types like `Maybe a`
- -- (which don't require parentheses in a function argument position) won't
- -- get them, assuming that there are no bang patterns (see bang_prec).
- --
- -- If we're displaying the fields Haskell98-style, e.g.,
- --
- -- data Foo a = MkFoo (Int -> Int) (Maybe a)
- --
- -- Then not only must we parenthesize `Int -> Int`, we must also
- -- parenthesize compound fields like (Maybe a). Therefore, we pick
- -- `appPrec`, which has higher precedence than `funPrec`.
- gadt_prec :: PprPrec
- gadt_prec
- | gadt_style = funPrec
- | otherwise = appPrec
-
- -- The presence of bang patterns or UNPACK annotations requires
- -- surrounding the type with parentheses, if needed (#13699)
- bang_prec :: IfaceBang -> PprPrec
- bang_prec IfNoBang = topPrec
- bang_prec IfStrict = appPrec
- bang_prec IfUnpack = appPrec
- bang_prec IfUnpackCo{} = appPrec
-
- pp_args :: [SDoc] -- No records, e.g., ` Maybe a -> Int -> ...` or
- -- `!(Maybe a) -> !Int -> ...`
- pp_args = map pprArgTy tys_w_strs
-
- pp_field_args :: SDoc -- Records, e.g., { x :: Maybe a, y :: Int } or
- -- { x :: !(Maybe a), y :: !Int }
- pp_field_args = braces $ sep $ punctuate comma $ ppr_trim $
- zipWith maybe_show_label fields tys_w_strs
-
- maybe_show_label :: FieldLabel -> (IfaceBang, IfaceType) -> Maybe SDoc
- maybe_show_label lbl bty
- | showSub ss sel = Just (pprPrefixIfDeclBndr how_much occ
- <+> dcolon <+> pprFieldArgTy bty)
- | otherwise = Nothing
- where
- sel = flSelector lbl
- occ = mkVarOccFS (flLabel lbl)
-
- mk_user_con_res_ty :: IfaceEqSpec -> SDoc
- -- See Note [Result type of a data family GADT]
- mk_user_con_res_ty eq_spec
- | IfDataInstance _ tc tys <- parent
- = pprIfaceType (IfaceTyConApp tc (substIfaceAppArgs gadt_subst tys))
- | otherwise
- = ppr_tc_app gadt_subst
- where
- gadt_subst = mkIfaceTySubst eq_spec
-
- -- When pretty-printing a GADT return type, we:
- --
- -- 1. Take the data tycon binders, extract their variable names and
- -- visibilities, and construct suitable arguments from them. (This is
- -- the role of mk_tc_app_args.)
- -- 2. Apply the GADT substitution constructed from the eq_spec.
- -- (See Note [Result type of a data family GADT].)
- -- 3. Pretty-print the data type constructor applied to its arguments.
- -- This process will omit any invisible arguments, such as coercion
- -- variables, if necessary. (See Note
- -- [VarBndrs, TyCoVarBinders, TyConBinders, and visibility] in TyCoRep.)
- ppr_tc_app gadt_subst =
- pprPrefixIfDeclBndr how_much (occName tycon)
- <+> pprParendIfaceAppArgs
- (substIfaceAppArgs gadt_subst (mk_tc_app_args tc_binders))
-
- mk_tc_app_args :: [IfaceTyConBinder] -> IfaceAppArgs
- mk_tc_app_args [] = IA_Nil
- mk_tc_app_args (Bndr bndr vis:tc_bndrs) =
- IA_Arg (IfaceTyVar (ifaceBndrName bndr)) (tyConBndrVisArgFlag vis)
- (mk_tc_app_args tc_bndrs)
-
-instance Outputable IfaceRule where
- ppr (IfaceRule { ifRuleName = name, ifActivation = act, ifRuleBndrs = bndrs,
- ifRuleHead = fn, ifRuleArgs = args, ifRuleRhs = rhs,
- ifRuleOrph = orph })
- = sep [ hsep [ pprRuleName name
- , if isOrphan orph then text "[orphan]" else Outputable.empty
- , ppr act
- , pp_foralls ]
- , nest 2 (sep [ppr fn <+> sep (map pprParendIfaceExpr args),
- text "=" <+> ppr rhs]) ]
- where
- pp_foralls = ppUnless (null bndrs) $ forAllLit <+> pprIfaceBndrs bndrs <> dot
-
-instance Outputable IfaceClsInst where
- ppr (IfaceClsInst { ifDFun = dfun_id, ifOFlag = flag
- , ifInstCls = cls, ifInstTys = mb_tcs
- , ifInstOrph = orph })
- = hang (text "instance" <+> ppr flag
- <+> (if isOrphan orph then text "[orphan]" else Outputable.empty)
- <+> ppr cls <+> brackets (pprWithCommas ppr_rough mb_tcs))
- 2 (equals <+> ppr dfun_id)
-
-instance Outputable IfaceFamInst where
- ppr (IfaceFamInst { ifFamInstFam = fam, ifFamInstTys = mb_tcs
- , ifFamInstAxiom = tycon_ax, ifFamInstOrph = orph })
- = hang (text "family instance"
- <+> (if isOrphan orph then text "[orphan]" else Outputable.empty)
- <+> ppr fam <+> pprWithCommas (brackets . ppr_rough) mb_tcs)
- 2 (equals <+> ppr tycon_ax)
-
-ppr_rough :: Maybe IfaceTyCon -> SDoc
-ppr_rough Nothing = dot
-ppr_rough (Just tc) = ppr tc
-
-{-
-Note [Result type of a data family GADT]
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-Consider
- data family T a
- data instance T (p,q) where
- T1 :: T (Int, Maybe c)
- T2 :: T (Bool, q)
-
-The IfaceDecl actually looks like
-
- data TPr p q where
- T1 :: forall p q. forall c. (p~Int,q~Maybe c) => TPr p q
- T2 :: forall p q. (p~Bool) => TPr p q
-
-To reconstruct the result types for T1 and T2 that we
-want to pretty print, we substitute the eq-spec
-[p->Int, q->Maybe c] in the arg pattern (p,q) to give
- T (Int, Maybe c)
-Remember that in IfaceSyn, the TyCon and DataCon share the same
-universal type variables.
-
------------------------------ Printing IfaceExpr ------------------------------------
--}
-
-instance Outputable IfaceExpr where
- ppr e = pprIfaceExpr noParens e
-
-noParens :: SDoc -> SDoc
-noParens pp = pp
-
-pprParendIfaceExpr :: IfaceExpr -> SDoc
-pprParendIfaceExpr = pprIfaceExpr parens
-
--- | Pretty Print an IfaceExpre
---
--- The first argument should be a function that adds parens in context that need
--- an atomic value (e.g. function args)
-pprIfaceExpr :: (SDoc -> SDoc) -> IfaceExpr -> SDoc
-
-pprIfaceExpr _ (IfaceLcl v) = ppr v
-pprIfaceExpr _ (IfaceExt v) = ppr v
-pprIfaceExpr _ (IfaceLit l) = ppr l
-pprIfaceExpr _ (IfaceFCall cc ty) = braces (ppr cc <+> ppr ty)
-pprIfaceExpr _ (IfaceType ty) = char '@' <+> pprParendIfaceType ty
-pprIfaceExpr _ (IfaceCo co) = text "@~" <+> pprParendIfaceCoercion co
-
-pprIfaceExpr add_par app@(IfaceApp _ _) = add_par (pprIfaceApp app [])
-pprIfaceExpr _ (IfaceTuple c as) = tupleParens c (pprWithCommas ppr as)
-
-pprIfaceExpr add_par i@(IfaceLam _ _)
- = add_par (sep [char '\\' <+> sep (map pprIfaceLamBndr bndrs) <+> arrow,
- pprIfaceExpr noParens body])
- where
- (bndrs,body) = collect [] i
- collect bs (IfaceLam b e) = collect (b:bs) e
- collect bs e = (reverse bs, e)
-
-pprIfaceExpr add_par (IfaceECase scrut ty)
- = add_par (sep [ text "case" <+> pprIfaceExpr noParens scrut
- , text "ret_ty" <+> pprParendIfaceType ty
- , text "of {}" ])
-
-pprIfaceExpr add_par (IfaceCase scrut bndr [(con, bs, rhs)])
- = add_par (sep [text "case"
- <+> pprIfaceExpr noParens scrut <+> text "of"
- <+> ppr bndr <+> char '{' <+> ppr_con_bs con bs <+> arrow,
- pprIfaceExpr noParens rhs <+> char '}'])
-
-pprIfaceExpr add_par (IfaceCase scrut bndr alts)
- = add_par (sep [text "case"
- <+> pprIfaceExpr noParens scrut <+> text "of"
- <+> ppr bndr <+> char '{',
- nest 2 (sep (map ppr_alt alts)) <+> char '}'])
-
-pprIfaceExpr _ (IfaceCast expr co)
- = sep [pprParendIfaceExpr expr,
- nest 2 (text "`cast`"),
- pprParendIfaceCoercion co]
-
-pprIfaceExpr add_par (IfaceLet (IfaceNonRec b rhs) body)
- = add_par (sep [text "let {",
- nest 2 (ppr_bind (b, rhs)),
- text "} in",
- pprIfaceExpr noParens body])
-
-pprIfaceExpr add_par (IfaceLet (IfaceRec pairs) body)
- = add_par (sep [text "letrec {",
- nest 2 (sep (map ppr_bind pairs)),
- text "} in",
- pprIfaceExpr noParens body])
-
-pprIfaceExpr add_par (IfaceTick tickish e)
- = add_par (pprIfaceTickish tickish <+> pprIfaceExpr noParens e)
-
-ppr_alt :: (IfaceConAlt, [IfLclName], IfaceExpr) -> SDoc
-ppr_alt (con, bs, rhs) = sep [ppr_con_bs con bs,
- arrow <+> pprIfaceExpr noParens rhs]
-
-ppr_con_bs :: IfaceConAlt -> [IfLclName] -> SDoc
-ppr_con_bs con bs = ppr con <+> hsep (map ppr bs)
-
-ppr_bind :: (IfaceLetBndr, IfaceExpr) -> SDoc
-ppr_bind (IfLetBndr b ty info ji, rhs)
- = sep [hang (ppr b <+> dcolon <+> ppr ty) 2 (ppr ji <+> ppr info),
- equals <+> pprIfaceExpr noParens rhs]
-
-------------------
-pprIfaceTickish :: IfaceTickish -> SDoc
-pprIfaceTickish (IfaceHpcTick m ix)
- = braces (text "tick" <+> ppr m <+> ppr ix)
-pprIfaceTickish (IfaceSCC cc tick scope)
- = braces (pprCostCentreCore cc <+> ppr tick <+> ppr scope)
-pprIfaceTickish (IfaceSource src _names)
- = braces (pprUserRealSpan True src)
-
-------------------
-pprIfaceApp :: IfaceExpr -> [SDoc] -> SDoc
-pprIfaceApp (IfaceApp fun arg) args = pprIfaceApp fun $
- nest 2 (pprParendIfaceExpr arg) : args
-pprIfaceApp fun args = sep (pprParendIfaceExpr fun : args)
-
-------------------
-instance Outputable IfaceConAlt where
- ppr IfaceDefault = text "DEFAULT"
- ppr (IfaceLitAlt l) = ppr l
- ppr (IfaceDataAlt d) = ppr d
-
-------------------
-instance Outputable IfaceIdDetails where
- ppr IfVanillaId = Outputable.empty
- ppr (IfRecSelId tc b) = text "RecSel" <+> ppr tc
- <+> if b
- then text "<naughty>"
- else Outputable.empty
- ppr IfDFunId = text "DFunId"
-
-instance Outputable IfaceIdInfo where
- ppr NoInfo = Outputable.empty
- ppr (HasInfo is) = text "{-" <+> pprWithCommas ppr is
- <+> text "-}"
-
-instance Outputable IfaceInfoItem where
- ppr (HsUnfold lb unf) = text "Unfolding"
- <> ppWhen lb (text "(loop-breaker)")
- <> colon <+> ppr unf
- ppr (HsInline prag) = text "Inline:" <+> ppr prag
- ppr (HsArity arity) = text "Arity:" <+> int arity
- ppr (HsStrictness str) = text "Strictness:" <+> pprIfaceStrictSig str
- ppr HsNoCafRefs = text "HasNoCafRefs"
- ppr HsLevity = text "Never levity-polymorphic"
-
-instance Outputable IfaceJoinInfo where
- ppr IfaceNotJoinPoint = empty
- ppr (IfaceJoinPoint ar) = angleBrackets (text "join" <+> ppr ar)
-
-instance Outputable IfaceUnfolding where
- ppr (IfCompulsory e) = text "<compulsory>" <+> parens (ppr e)
- ppr (IfCoreUnfold s e) = (if s
- then text "<stable>"
- else Outputable.empty)
- <+> parens (ppr e)
- ppr (IfInlineRule a uok bok e) = sep [text "InlineRule"
- <+> ppr (a,uok,bok),
- pprParendIfaceExpr e]
- ppr (IfDFunUnfold bs es) = hang (text "DFun:" <+> sep (map ppr bs) <> dot)
- 2 (sep (map pprParendIfaceExpr es))
-
-{-
-************************************************************************
-* *
- Finding the Names in IfaceSyn
-* *
-************************************************************************
-
-This is used for dependency analysis in MkIface, so that we
-fingerprint a declaration before the things that depend on it. It
-is specific to interface-file fingerprinting in the sense that we
-don't collect *all* Names: for example, the DFun of an instance is
-recorded textually rather than by its fingerprint when
-fingerprinting the instance, so DFuns are not dependencies.
--}
-
-freeNamesIfDecl :: IfaceDecl -> NameSet
-freeNamesIfDecl (IfaceId { ifType = t, ifIdDetails = d, ifIdInfo = i})
- = freeNamesIfType t &&&
- freeNamesIfIdInfo i &&&
- freeNamesIfIdDetails d
-
-freeNamesIfDecl (IfaceData { ifBinders = bndrs, ifResKind = res_k
- , ifParent = p, ifCtxt = ctxt, ifCons = cons })
- = freeNamesIfVarBndrs bndrs &&&
- freeNamesIfType res_k &&&
- freeNamesIfaceTyConParent p &&&
- freeNamesIfContext ctxt &&&
- freeNamesIfConDecls cons
-
-freeNamesIfDecl (IfaceSynonym { ifBinders = bndrs, ifResKind = res_k
- , ifSynRhs = rhs })
- = freeNamesIfVarBndrs bndrs &&&
- freeNamesIfKind res_k &&&
- freeNamesIfType rhs
-
-freeNamesIfDecl (IfaceFamily { ifBinders = bndrs, ifResKind = res_k
- , ifFamFlav = flav })
- = freeNamesIfVarBndrs bndrs &&&
- freeNamesIfKind res_k &&&
- freeNamesIfFamFlav flav
-
-freeNamesIfDecl (IfaceClass{ ifBinders = bndrs, ifBody = cls_body })
- = freeNamesIfVarBndrs bndrs &&&
- freeNamesIfClassBody cls_body
-
-freeNamesIfDecl (IfaceAxiom { ifTyCon = tc, ifAxBranches = branches })
- = freeNamesIfTc tc &&&
- fnList freeNamesIfAxBranch branches
-
-freeNamesIfDecl (IfacePatSyn { ifPatMatcher = (matcher, _)
- , ifPatBuilder = mb_builder
- , ifPatUnivBndrs = univ_bndrs
- , ifPatExBndrs = ex_bndrs
- , ifPatProvCtxt = prov_ctxt
- , ifPatReqCtxt = req_ctxt
- , ifPatArgs = args
- , ifPatTy = pat_ty
- , ifFieldLabels = lbls })
- = unitNameSet matcher &&&
- maybe emptyNameSet (unitNameSet . fst) mb_builder &&&
- freeNamesIfVarBndrs univ_bndrs &&&
- freeNamesIfVarBndrs ex_bndrs &&&
- freeNamesIfContext prov_ctxt &&&
- freeNamesIfContext req_ctxt &&&
- fnList freeNamesIfType args &&&
- freeNamesIfType pat_ty &&&
- mkNameSet (map flSelector lbls)
-
-freeNamesIfClassBody :: IfaceClassBody -> NameSet
-freeNamesIfClassBody IfAbstractClass
- = emptyNameSet
-freeNamesIfClassBody (IfConcreteClass{ ifClassCtxt = ctxt, ifATs = ats, ifSigs = sigs })
- = freeNamesIfContext ctxt &&&
- fnList freeNamesIfAT ats &&&
- fnList freeNamesIfClsSig sigs
-
-freeNamesIfAxBranch :: IfaceAxBranch -> NameSet
-freeNamesIfAxBranch (IfaceAxBranch { ifaxbTyVars = tyvars
- , ifaxbCoVars = covars
- , ifaxbLHS = lhs
- , ifaxbRHS = rhs })
- = fnList freeNamesIfTvBndr tyvars &&&
- fnList freeNamesIfIdBndr covars &&&
- freeNamesIfAppArgs lhs &&&
- freeNamesIfType rhs
-
-freeNamesIfIdDetails :: IfaceIdDetails -> NameSet
-freeNamesIfIdDetails (IfRecSelId tc _) =
- either freeNamesIfTc freeNamesIfDecl tc
-freeNamesIfIdDetails _ = emptyNameSet
-
--- All other changes are handled via the version info on the tycon
-freeNamesIfFamFlav :: IfaceFamTyConFlav -> NameSet
-freeNamesIfFamFlav IfaceOpenSynFamilyTyCon = emptyNameSet
-freeNamesIfFamFlav IfaceDataFamilyTyCon = emptyNameSet
-freeNamesIfFamFlav (IfaceClosedSynFamilyTyCon (Just (ax, br)))
- = unitNameSet ax &&& fnList freeNamesIfAxBranch br
-freeNamesIfFamFlav (IfaceClosedSynFamilyTyCon Nothing) = emptyNameSet
-freeNamesIfFamFlav IfaceAbstractClosedSynFamilyTyCon = emptyNameSet
-freeNamesIfFamFlav IfaceBuiltInSynFamTyCon = emptyNameSet
-
-freeNamesIfContext :: IfaceContext -> NameSet
-freeNamesIfContext = fnList freeNamesIfType
-
-freeNamesIfAT :: IfaceAT -> NameSet
-freeNamesIfAT (IfaceAT decl mb_def)
- = freeNamesIfDecl decl &&&
- case mb_def of
- Nothing -> emptyNameSet
- Just rhs -> freeNamesIfType rhs
-
-freeNamesIfClsSig :: IfaceClassOp -> NameSet
-freeNamesIfClsSig (IfaceClassOp _n ty dm) = freeNamesIfType ty &&& freeNamesDM dm
-
-freeNamesDM :: Maybe (DefMethSpec IfaceType) -> NameSet
-freeNamesDM (Just (GenericDM ty)) = freeNamesIfType ty
-freeNamesDM _ = emptyNameSet
-
-freeNamesIfConDecls :: IfaceConDecls -> NameSet
-freeNamesIfConDecls (IfDataTyCon c) = fnList freeNamesIfConDecl c
-freeNamesIfConDecls (IfNewTyCon c) = freeNamesIfConDecl c
-freeNamesIfConDecls _ = emptyNameSet
-
-freeNamesIfConDecl :: IfaceConDecl -> NameSet
-freeNamesIfConDecl (IfCon { ifConExTCvs = ex_tvs, ifConCtxt = ctxt
- , ifConArgTys = arg_tys
- , ifConFields = flds
- , ifConEqSpec = eq_spec
- , ifConStricts = bangs })
- = fnList freeNamesIfBndr ex_tvs &&&
- freeNamesIfContext ctxt &&&
- fnList freeNamesIfType arg_tys &&&
- mkNameSet (map flSelector flds) &&&
- fnList freeNamesIfType (map snd eq_spec) &&& -- equality constraints
- fnList freeNamesIfBang bangs
-
-freeNamesIfBang :: IfaceBang -> NameSet
-freeNamesIfBang (IfUnpackCo co) = freeNamesIfCoercion co
-freeNamesIfBang _ = emptyNameSet
-
-freeNamesIfKind :: IfaceType -> NameSet
-freeNamesIfKind = freeNamesIfType
-
-freeNamesIfAppArgs :: IfaceAppArgs -> NameSet
-freeNamesIfAppArgs (IA_Arg t _ ts) = freeNamesIfType t &&& freeNamesIfAppArgs ts
-freeNamesIfAppArgs IA_Nil = emptyNameSet
-
-freeNamesIfType :: IfaceType -> NameSet
-freeNamesIfType (IfaceFreeTyVar _) = emptyNameSet
-freeNamesIfType (IfaceTyVar _) = emptyNameSet
-freeNamesIfType (IfaceAppTy s t) = freeNamesIfType s &&& freeNamesIfAppArgs t
-freeNamesIfType (IfaceTyConApp tc ts) = freeNamesIfTc tc &&& freeNamesIfAppArgs ts
-freeNamesIfType (IfaceTupleTy _ _ ts) = freeNamesIfAppArgs ts
-freeNamesIfType (IfaceLitTy _) = emptyNameSet
-freeNamesIfType (IfaceForAllTy tv t) = freeNamesIfVarBndr tv &&& freeNamesIfType t
-freeNamesIfType (IfaceFunTy _ s t) = freeNamesIfType s &&& freeNamesIfType t
-freeNamesIfType (IfaceCastTy t c) = freeNamesIfType t &&& freeNamesIfCoercion c
-freeNamesIfType (IfaceCoercionTy c) = freeNamesIfCoercion c
-
-freeNamesIfMCoercion :: IfaceMCoercion -> NameSet
-freeNamesIfMCoercion IfaceMRefl = emptyNameSet
-freeNamesIfMCoercion (IfaceMCo co) = freeNamesIfCoercion co
-
-freeNamesIfCoercion :: IfaceCoercion -> NameSet
-freeNamesIfCoercion (IfaceReflCo t) = freeNamesIfType t
-freeNamesIfCoercion (IfaceGReflCo _ t mco)
- = freeNamesIfType t &&& freeNamesIfMCoercion mco
-freeNamesIfCoercion (IfaceFunCo _ c1 c2)
- = freeNamesIfCoercion c1 &&& freeNamesIfCoercion c2
-freeNamesIfCoercion (IfaceTyConAppCo _ tc cos)
- = freeNamesIfTc tc &&& fnList freeNamesIfCoercion cos
-freeNamesIfCoercion (IfaceAppCo c1 c2)
- = freeNamesIfCoercion c1 &&& freeNamesIfCoercion c2
-freeNamesIfCoercion (IfaceForAllCo _ kind_co co)
- = freeNamesIfCoercion kind_co &&& freeNamesIfCoercion co
-freeNamesIfCoercion (IfaceFreeCoVar _) = emptyNameSet
-freeNamesIfCoercion (IfaceCoVarCo _) = emptyNameSet
-freeNamesIfCoercion (IfaceHoleCo _) = emptyNameSet
-freeNamesIfCoercion (IfaceAxiomInstCo ax _ cos)
- = unitNameSet ax &&& fnList freeNamesIfCoercion cos
-freeNamesIfCoercion (IfaceUnivCo p _ t1 t2)
- = freeNamesIfProv p &&& freeNamesIfType t1 &&& freeNamesIfType t2
-freeNamesIfCoercion (IfaceSymCo c)
- = freeNamesIfCoercion c
-freeNamesIfCoercion (IfaceTransCo c1 c2)
- = freeNamesIfCoercion c1 &&& freeNamesIfCoercion c2
-freeNamesIfCoercion (IfaceNthCo _ co)
- = freeNamesIfCoercion co
-freeNamesIfCoercion (IfaceLRCo _ co)
- = freeNamesIfCoercion co
-freeNamesIfCoercion (IfaceInstCo co co2)
- = freeNamesIfCoercion co &&& freeNamesIfCoercion co2
-freeNamesIfCoercion (IfaceKindCo c)
- = freeNamesIfCoercion c
-freeNamesIfCoercion (IfaceSubCo co)
- = freeNamesIfCoercion co
-freeNamesIfCoercion (IfaceAxiomRuleCo _ax cos)
- -- the axiom is just a string, so we don't count it as a name.
- = fnList freeNamesIfCoercion cos
-
-freeNamesIfProv :: IfaceUnivCoProv -> NameSet
-freeNamesIfProv IfaceUnsafeCoerceProv = emptyNameSet
-freeNamesIfProv (IfacePhantomProv co) = freeNamesIfCoercion co
-freeNamesIfProv (IfaceProofIrrelProv co) = freeNamesIfCoercion co
-freeNamesIfProv (IfacePluginProv _) = emptyNameSet
-
-freeNamesIfVarBndr :: VarBndr IfaceBndr vis -> NameSet
-freeNamesIfVarBndr (Bndr bndr _) = freeNamesIfBndr bndr
-
-freeNamesIfVarBndrs :: [VarBndr IfaceBndr vis] -> NameSet
-freeNamesIfVarBndrs = fnList freeNamesIfVarBndr
-
-freeNamesIfBndr :: IfaceBndr -> NameSet
-freeNamesIfBndr (IfaceIdBndr b) = freeNamesIfIdBndr b
-freeNamesIfBndr (IfaceTvBndr b) = freeNamesIfTvBndr b
-
-freeNamesIfBndrs :: [IfaceBndr] -> NameSet
-freeNamesIfBndrs = fnList freeNamesIfBndr
-
-freeNamesIfLetBndr :: IfaceLetBndr -> NameSet
--- Remember IfaceLetBndr is used only for *nested* bindings
--- The IdInfo can contain an unfolding (in the case of
--- local INLINE pragmas), so look there too
-freeNamesIfLetBndr (IfLetBndr _name ty info _ji) = freeNamesIfType ty
- &&& freeNamesIfIdInfo info
-
-freeNamesIfTvBndr :: IfaceTvBndr -> NameSet
-freeNamesIfTvBndr (_fs,k) = freeNamesIfKind k
- -- kinds can have Names inside, because of promotion
-
-freeNamesIfIdBndr :: IfaceIdBndr -> NameSet
-freeNamesIfIdBndr (_fs,k) = freeNamesIfKind k
-
-freeNamesIfIdInfo :: IfaceIdInfo -> NameSet
-freeNamesIfIdInfo NoInfo = emptyNameSet
-freeNamesIfIdInfo (HasInfo i) = fnList freeNamesItem i
-
-freeNamesItem :: IfaceInfoItem -> NameSet
-freeNamesItem (HsUnfold _ u) = freeNamesIfUnfold u
-freeNamesItem _ = emptyNameSet
-
-freeNamesIfUnfold :: IfaceUnfolding -> NameSet
-freeNamesIfUnfold (IfCoreUnfold _ e) = freeNamesIfExpr e
-freeNamesIfUnfold (IfCompulsory e) = freeNamesIfExpr e
-freeNamesIfUnfold (IfInlineRule _ _ _ e) = freeNamesIfExpr e
-freeNamesIfUnfold (IfDFunUnfold bs es) = freeNamesIfBndrs bs &&& fnList freeNamesIfExpr es
-
-freeNamesIfExpr :: IfaceExpr -> NameSet
-freeNamesIfExpr (IfaceExt v) = unitNameSet v
-freeNamesIfExpr (IfaceFCall _ ty) = freeNamesIfType ty
-freeNamesIfExpr (IfaceType ty) = freeNamesIfType ty
-freeNamesIfExpr (IfaceCo co) = freeNamesIfCoercion co
-freeNamesIfExpr (IfaceTuple _ as) = fnList freeNamesIfExpr as
-freeNamesIfExpr (IfaceLam (b,_) body) = freeNamesIfBndr b &&& freeNamesIfExpr body
-freeNamesIfExpr (IfaceApp f a) = freeNamesIfExpr f &&& freeNamesIfExpr a
-freeNamesIfExpr (IfaceCast e co) = freeNamesIfExpr e &&& freeNamesIfCoercion co
-freeNamesIfExpr (IfaceTick _ e) = freeNamesIfExpr e
-freeNamesIfExpr (IfaceECase e ty) = freeNamesIfExpr e &&& freeNamesIfType ty
-freeNamesIfExpr (IfaceCase s _ alts)
- = freeNamesIfExpr s &&& fnList fn_alt alts &&& fn_cons alts
- where
- fn_alt (_con,_bs,r) = freeNamesIfExpr r
-
- -- Depend on the data constructors. Just one will do!
- -- Note [Tracking data constructors]
- fn_cons [] = emptyNameSet
- fn_cons ((IfaceDefault ,_,_) : xs) = fn_cons xs
- fn_cons ((IfaceDataAlt con,_,_) : _ ) = unitNameSet con
- fn_cons (_ : _ ) = emptyNameSet
-
-freeNamesIfExpr (IfaceLet (IfaceNonRec bndr rhs) body)
- = freeNamesIfLetBndr bndr &&& freeNamesIfExpr rhs &&& freeNamesIfExpr body
-
-freeNamesIfExpr (IfaceLet (IfaceRec as) x)
- = fnList fn_pair as &&& freeNamesIfExpr x
- where
- fn_pair (bndr, rhs) = freeNamesIfLetBndr bndr &&& freeNamesIfExpr rhs
-
-freeNamesIfExpr _ = emptyNameSet
-
-freeNamesIfTc :: IfaceTyCon -> NameSet
-freeNamesIfTc tc = unitNameSet (ifaceTyConName tc)
--- ToDo: shouldn't we include IfaceIntTc & co.?
-
-freeNamesIfRule :: IfaceRule -> NameSet
-freeNamesIfRule (IfaceRule { ifRuleBndrs = bs, ifRuleHead = f
- , ifRuleArgs = es, ifRuleRhs = rhs })
- = unitNameSet f &&&
- fnList freeNamesIfBndr bs &&&
- fnList freeNamesIfExpr es &&&
- freeNamesIfExpr rhs
-
-freeNamesIfFamInst :: IfaceFamInst -> NameSet
-freeNamesIfFamInst (IfaceFamInst { ifFamInstFam = famName
- , ifFamInstAxiom = axName })
- = unitNameSet famName &&&
- unitNameSet axName
-
-freeNamesIfaceTyConParent :: IfaceTyConParent -> NameSet
-freeNamesIfaceTyConParent IfNoParent = emptyNameSet
-freeNamesIfaceTyConParent (IfDataInstance ax tc tys)
- = unitNameSet ax &&& freeNamesIfTc tc &&& freeNamesIfAppArgs tys
-
--- helpers
-(&&&) :: NameSet -> NameSet -> NameSet
-(&&&) = unionNameSet
-
-fnList :: (a -> NameSet) -> [a] -> NameSet
-fnList f = foldr (&&&) emptyNameSet . map f
-
-{-
-Note [Tracking data constructors]
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-In a case expression
- case e of { C a -> ...; ... }
-You might think that we don't need to include the datacon C
-in the free names, because its type will probably show up in
-the free names of 'e'. But in rare circumstances this may
-not happen. Here's the one that bit me:
-
- module DynFlags where
- import {-# SOURCE #-} Packages( PackageState )
- data DynFlags = DF ... PackageState ...
-
- module Packages where
- import DynFlags
- data PackageState = PS ...
- lookupModule (df :: DynFlags)
- = case df of
- DF ...p... -> case p of
- PS ... -> ...
-
-Now, lookupModule depends on DynFlags, but the transitive dependency
-on the *locally-defined* type PackageState is not visible. We need
-to take account of the use of the data constructor PS in the pattern match.
-
-
-************************************************************************
-* *
- Binary instances
-* *
-************************************************************************
-
-Note that there is a bit of subtlety here when we encode names. While
-IfaceTopBndrs is really just a synonym for Name, we need to take care to
-encode them with {get,put}IfaceTopBndr. The difference becomes important when
-we go to fingerprint an IfaceDecl. See Note [Fingerprinting IfaceDecls] for
-details.
-
--}
-
-instance Binary IfaceDecl where
- put_ bh (IfaceId name ty details idinfo) = do
- putByte bh 0
- putIfaceTopBndr bh name
- lazyPut bh (ty, details, idinfo)
- -- See Note [Lazy deserialization of IfaceId]
-
- put_ bh (IfaceData a1 a2 a3 a4 a5 a6 a7 a8 a9) = do
- putByte bh 2
- putIfaceTopBndr bh a1
- put_ bh a2
- put_ bh a3
- put_ bh a4
- put_ bh a5
- put_ bh a6
- put_ bh a7
- put_ bh a8
- put_ bh a9
-
- put_ bh (IfaceSynonym a1 a2 a3 a4 a5) = do
- putByte bh 3
- putIfaceTopBndr bh a1
- put_ bh a2
- put_ bh a3
- put_ bh a4
- put_ bh a5
-
- put_ bh (IfaceFamily a1 a2 a3 a4 a5 a6) = do
- putByte bh 4
- putIfaceTopBndr bh a1
- put_ bh a2
- put_ bh a3
- put_ bh a4
- put_ bh a5
- put_ bh a6
-
- -- NB: Written in a funny way to avoid an interface change
- put_ bh (IfaceClass {
- ifName = a2,
- ifRoles = a3,
- ifBinders = a4,
- ifFDs = a5,
- ifBody = IfConcreteClass {
- ifClassCtxt = a1,
- ifATs = a6,
- ifSigs = a7,
- ifMinDef = a8
- }}) = do
- putByte bh 5
- put_ bh a1
- putIfaceTopBndr bh a2
- put_ bh a3
- put_ bh a4
- put_ bh a5
- put_ bh a6
- put_ bh a7
- put_ bh a8
-
- put_ bh (IfaceAxiom a1 a2 a3 a4) = do
- putByte bh 6
- putIfaceTopBndr bh a1
- put_ bh a2
- put_ bh a3
- put_ bh a4
-
- put_ bh (IfacePatSyn a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 a11) = do
- putByte bh 7
- putIfaceTopBndr bh a1
- put_ bh a2
- put_ bh a3
- put_ bh a4
- put_ bh a5
- put_ bh a6
- put_ bh a7
- put_ bh a8
- put_ bh a9
- put_ bh a10
- put_ bh a11
-
- put_ bh (IfaceClass {
- ifName = a1,
- ifRoles = a2,
- ifBinders = a3,
- ifFDs = a4,
- ifBody = IfAbstractClass }) = do
- putByte bh 8
- putIfaceTopBndr bh a1
- put_ bh a2
- put_ bh a3
- put_ bh a4
-
- get bh = do
- h <- getByte bh
- case h of
- 0 -> do name <- get bh
- ~(ty, details, idinfo) <- lazyGet bh
- -- See Note [Lazy deserialization of IfaceId]
- return (IfaceId name ty details idinfo)
- 1 -> error "Binary.get(TyClDecl): ForeignType"
- 2 -> do a1 <- getIfaceTopBndr bh
- a2 <- get bh
- a3 <- get bh
- a4 <- get bh
- a5 <- get bh
- a6 <- get bh
- a7 <- get bh
- a8 <- get bh
- a9 <- get bh
- return (IfaceData a1 a2 a3 a4 a5 a6 a7 a8 a9)
- 3 -> do a1 <- getIfaceTopBndr bh
- a2 <- get bh
- a3 <- get bh
- a4 <- get bh
- a5 <- get bh
- return (IfaceSynonym a1 a2 a3 a4 a5)
- 4 -> do a1 <- getIfaceTopBndr bh
- a2 <- get bh
- a3 <- get bh
- a4 <- get bh
- a5 <- get bh
- a6 <- get bh
- return (IfaceFamily a1 a2 a3 a4 a5 a6)
- 5 -> do a1 <- get bh
- a2 <- getIfaceTopBndr bh
- a3 <- get bh
- a4 <- get bh
- a5 <- get bh
- a6 <- get bh
- a7 <- get bh
- a8 <- get bh
- return (IfaceClass {
- ifName = a2,
- ifRoles = a3,
- ifBinders = a4,
- ifFDs = a5,
- ifBody = IfConcreteClass {
- ifClassCtxt = a1,
- ifATs = a6,
- ifSigs = a7,
- ifMinDef = a8
- }})
- 6 -> do a1 <- getIfaceTopBndr bh
- a2 <- get bh
- a3 <- get bh
- a4 <- get bh
- return (IfaceAxiom a1 a2 a3 a4)
- 7 -> do a1 <- getIfaceTopBndr bh
- a2 <- get bh
- a3 <- get bh
- a4 <- get bh
- a5 <- get bh
- a6 <- get bh
- a7 <- get bh
- a8 <- get bh
- a9 <- get bh
- a10 <- get bh
- a11 <- get bh
- return (IfacePatSyn a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 a11)
- 8 -> do a1 <- getIfaceTopBndr bh
- a2 <- get bh
- a3 <- get bh
- a4 <- get bh
- return (IfaceClass {
- ifName = a1,
- ifRoles = a2,
- ifBinders = a3,
- ifFDs = a4,
- ifBody = IfAbstractClass })
- _ -> panic (unwords ["Unknown IfaceDecl tag:", show h])
-
-{- Note [Lazy deserialization of IfaceId]
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-The use of lazyPut and lazyGet in the IfaceId Binary instance is
-purely for performance reasons, to avoid deserializing details about
-identifiers that will never be used. It's not involved in tying the
-knot in the type checker. It saved ~1% of the total build time of GHC.
-
-When we read an interface file, we extend the PTE, a mapping of Names
-to TyThings, with the declarations we have read. The extension of the
-PTE is strict in the Names, but not in the TyThings themselves.
-LoadIface.loadDecl calculates the list of (Name, TyThing) bindings to
-add to the PTE. For an IfaceId, there's just one binding to add; and
-the ty, details, and idinfo fields of an IfaceId are used only in the
-TyThing. So by reading those fields lazily we may be able to save the
-work of ever having to deserialize them (into IfaceType, etc.).
-
-For IfaceData and IfaceClass, loadDecl creates extra implicit bindings
-(the constructors and field selectors of the data declaration, or the
-methods of the class), whose Names depend on more than just the Name
-of the type constructor or class itself. So deserializing them lazily
-would be more involved. Similar comments apply to the other
-constructors of IfaceDecl with the additional point that they probably
-represent a small proportion of all declarations.
--}
-
-instance Binary IfaceFamTyConFlav where
- put_ bh IfaceDataFamilyTyCon = putByte bh 0
- put_ bh IfaceOpenSynFamilyTyCon = putByte bh 1
- put_ bh (IfaceClosedSynFamilyTyCon mb) = putByte bh 2 >> put_ bh mb
- put_ bh IfaceAbstractClosedSynFamilyTyCon = putByte bh 3
- put_ _ IfaceBuiltInSynFamTyCon
- = pprPanic "Cannot serialize IfaceBuiltInSynFamTyCon, used for pretty-printing only" Outputable.empty
-
- get bh = do { h <- getByte bh
- ; case h of
- 0 -> return IfaceDataFamilyTyCon
- 1 -> return IfaceOpenSynFamilyTyCon
- 2 -> do { mb <- get bh
- ; return (IfaceClosedSynFamilyTyCon mb) }
- 3 -> return IfaceAbstractClosedSynFamilyTyCon
- _ -> pprPanic "Binary.get(IfaceFamTyConFlav): Invalid tag"
- (ppr (fromIntegral h :: Int)) }
-
-instance Binary IfaceClassOp where
- put_ bh (IfaceClassOp n ty def) = do
- putIfaceTopBndr bh n
- put_ bh ty
- put_ bh def
- get bh = do
- n <- getIfaceTopBndr bh
- ty <- get bh
- def <- get bh
- return (IfaceClassOp n ty def)
-
-instance Binary IfaceAT where
- put_ bh (IfaceAT dec defs) = do
- put_ bh dec
- put_ bh defs
- get bh = do
- dec <- get bh
- defs <- get bh
- return (IfaceAT dec defs)
-
-instance Binary IfaceAxBranch where
- put_ bh (IfaceAxBranch a1 a2 a3 a4 a5 a6 a7) = do
- put_ bh a1
- put_ bh a2
- put_ bh a3
- put_ bh a4
- put_ bh a5
- put_ bh a6
- put_ bh a7
- get bh = do
- a1 <- get bh
- a2 <- get bh
- a3 <- get bh
- a4 <- get bh
- a5 <- get bh
- a6 <- get bh
- a7 <- get bh
- return (IfaceAxBranch a1 a2 a3 a4 a5 a6 a7)
-
-instance Binary IfaceConDecls where
- put_ bh IfAbstractTyCon = putByte bh 0
- put_ bh (IfDataTyCon cs) = putByte bh 1 >> put_ bh cs
- put_ bh (IfNewTyCon c) = putByte bh 2 >> put_ bh c
- get bh = do
- h <- getByte bh
- case h of
- 0 -> return IfAbstractTyCon
- 1 -> liftM IfDataTyCon (get bh)
- 2 -> liftM IfNewTyCon (get bh)
- _ -> error "Binary(IfaceConDecls).get: Invalid IfaceConDecls"
-
-instance Binary IfaceConDecl where
- put_ bh (IfCon a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 a11) = do
- putIfaceTopBndr bh a1
- put_ bh a2
- put_ bh a3
- put_ bh a4
- put_ bh a5
- put_ bh a6
- put_ bh a7
- put_ bh a8
- put_ bh (length a9)
- mapM_ (put_ bh) a9
- put_ bh a10
- put_ bh a11
- get bh = do
- a1 <- getIfaceTopBndr bh
- a2 <- get bh
- a3 <- get bh
- a4 <- get bh
- a5 <- get bh
- a6 <- get bh
- a7 <- get bh
- a8 <- get bh
- n_fields <- get bh
- a9 <- replicateM n_fields (get bh)
- a10 <- get bh
- a11 <- get bh
- return (IfCon a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 a11)
-
-instance Binary IfaceBang where
- put_ bh IfNoBang = putByte bh 0
- put_ bh IfStrict = putByte bh 1
- put_ bh IfUnpack = putByte bh 2
- put_ bh (IfUnpackCo co) = putByte bh 3 >> put_ bh co
-
- get bh = do
- h <- getByte bh
- case h of
- 0 -> do return IfNoBang
- 1 -> do return IfStrict
- 2 -> do return IfUnpack
- _ -> do { a <- get bh; return (IfUnpackCo a) }
-
-instance Binary IfaceSrcBang where
- put_ bh (IfSrcBang a1 a2) =
- do put_ bh a1
- put_ bh a2
-
- get bh =
- do a1 <- get bh
- a2 <- get bh
- return (IfSrcBang a1 a2)
-
-instance Binary IfaceClsInst where
- put_ bh (IfaceClsInst cls tys dfun flag orph) = do
- put_ bh cls
- put_ bh tys
- put_ bh dfun
- put_ bh flag
- put_ bh orph
- get bh = do
- cls <- get bh
- tys <- get bh
- dfun <- get bh
- flag <- get bh
- orph <- get bh
- return (IfaceClsInst cls tys dfun flag orph)
-
-instance Binary IfaceFamInst where
- put_ bh (IfaceFamInst fam tys name orph) = do
- put_ bh fam
- put_ bh tys
- put_ bh name
- put_ bh orph
- get bh = do
- fam <- get bh
- tys <- get bh
- name <- get bh
- orph <- get bh
- return (IfaceFamInst fam tys name orph)
-
-instance Binary IfaceRule where
- put_ bh (IfaceRule a1 a2 a3 a4 a5 a6 a7 a8) = do
- put_ bh a1
- put_ bh a2
- put_ bh a3
- put_ bh a4
- put_ bh a5
- put_ bh a6
- put_ bh a7
- put_ bh a8
- get bh = do
- a1 <- get bh
- a2 <- get bh
- a3 <- get bh
- a4 <- get bh
- a5 <- get bh
- a6 <- get bh
- a7 <- get bh
- a8 <- get bh
- return (IfaceRule a1 a2 a3 a4 a5 a6 a7 a8)
-
-instance Binary IfaceAnnotation where
- put_ bh (IfaceAnnotation a1 a2) = do
- put_ bh a1
- put_ bh a2
- get bh = do
- a1 <- get bh
- a2 <- get bh
- return (IfaceAnnotation a1 a2)
-
-instance Binary IfaceIdDetails where
- put_ bh IfVanillaId = putByte bh 0
- put_ bh (IfRecSelId a b) = putByte bh 1 >> put_ bh a >> put_ bh b
- put_ bh IfDFunId = putByte bh 2
- get bh = do
- h <- getByte bh
- case h of
- 0 -> return IfVanillaId
- 1 -> do { a <- get bh; b <- get bh; return (IfRecSelId a b) }
- _ -> return IfDFunId
-
-instance Binary IfaceIdInfo where
- put_ bh NoInfo = putByte bh 0
- put_ bh (HasInfo i) = putByte bh 1 >> lazyPut bh i -- NB lazyPut
-
- get bh = do
- h <- getByte bh
- case h of
- 0 -> return NoInfo
- _ -> liftM HasInfo $ lazyGet bh -- NB lazyGet
-
-instance Binary IfaceInfoItem where
- put_ bh (HsArity aa) = putByte bh 0 >> put_ bh aa
- put_ bh (HsStrictness ab) = putByte bh 1 >> put_ bh ab
- put_ bh (HsUnfold lb ad) = putByte bh 2 >> put_ bh lb >> put_ bh ad
- put_ bh (HsInline ad) = putByte bh 3 >> put_ bh ad
- put_ bh HsNoCafRefs = putByte bh 4
- put_ bh HsLevity = putByte bh 5
- get bh = do
- h <- getByte bh
- case h of
- 0 -> liftM HsArity $ get bh
- 1 -> liftM HsStrictness $ get bh
- 2 -> do lb <- get bh
- ad <- get bh
- return (HsUnfold lb ad)
- 3 -> liftM HsInline $ get bh
- 4 -> return HsNoCafRefs
- _ -> return HsLevity
-
-instance Binary IfaceUnfolding where
- put_ bh (IfCoreUnfold s e) = do
- putByte bh 0
- put_ bh s
- put_ bh e
- put_ bh (IfInlineRule a b c d) = do
- putByte bh 1
- put_ bh a
- put_ bh b
- put_ bh c
- put_ bh d
- put_ bh (IfDFunUnfold as bs) = do
- putByte bh 2
- put_ bh as
- put_ bh bs
- put_ bh (IfCompulsory e) = do
- putByte bh 3
- put_ bh e
- get bh = do
- h <- getByte bh
- case h of
- 0 -> do s <- get bh
- e <- get bh
- return (IfCoreUnfold s e)
- 1 -> do a <- get bh
- b <- get bh
- c <- get bh
- d <- get bh
- return (IfInlineRule a b c d)
- 2 -> do as <- get bh
- bs <- get bh
- return (IfDFunUnfold as bs)
- _ -> do e <- get bh
- return (IfCompulsory e)
-
-
-instance Binary IfaceExpr where
- put_ bh (IfaceLcl aa) = do
- putByte bh 0
- put_ bh aa
- put_ bh (IfaceType ab) = do
- putByte bh 1
- put_ bh ab
- put_ bh (IfaceCo ab) = do
- putByte bh 2
- put_ bh ab
- put_ bh (IfaceTuple ac ad) = do
- putByte bh 3
- put_ bh ac
- put_ bh ad
- put_ bh (IfaceLam (ae, os) af) = do
- putByte bh 4
- put_ bh ae
- put_ bh os
- put_ bh af
- put_ bh (IfaceApp ag ah) = do
- putByte bh 5
- put_ bh ag
- put_ bh ah
- put_ bh (IfaceCase ai aj ak) = do
- putByte bh 6
- put_ bh ai
- put_ bh aj
- put_ bh ak
- put_ bh (IfaceLet al am) = do
- putByte bh 7
- put_ bh al
- put_ bh am
- put_ bh (IfaceTick an ao) = do
- putByte bh 8
- put_ bh an
- put_ bh ao
- put_ bh (IfaceLit ap) = do
- putByte bh 9
- put_ bh ap
- put_ bh (IfaceFCall as at) = do
- putByte bh 10
- put_ bh as
- put_ bh at
- put_ bh (IfaceExt aa) = do
- putByte bh 11
- put_ bh aa
- put_ bh (IfaceCast ie ico) = do
- putByte bh 12
- put_ bh ie
- put_ bh ico
- put_ bh (IfaceECase a b) = do
- putByte bh 13
- put_ bh a
- put_ bh b
- get bh = do
- h <- getByte bh
- case h of
- 0 -> do aa <- get bh
- return (IfaceLcl aa)
- 1 -> do ab <- get bh
- return (IfaceType ab)
- 2 -> do ab <- get bh
- return (IfaceCo ab)
- 3 -> do ac <- get bh
- ad <- get bh
- return (IfaceTuple ac ad)
- 4 -> do ae <- get bh
- os <- get bh
- af <- get bh
- return (IfaceLam (ae, os) af)
- 5 -> do ag <- get bh
- ah <- get bh
- return (IfaceApp ag ah)
- 6 -> do ai <- get bh
- aj <- get bh
- ak <- get bh
- return (IfaceCase ai aj ak)
- 7 -> do al <- get bh
- am <- get bh
- return (IfaceLet al am)
- 8 -> do an <- get bh
- ao <- get bh
- return (IfaceTick an ao)
- 9 -> do ap <- get bh
- return (IfaceLit ap)
- 10 -> do as <- get bh
- at <- get bh
- return (IfaceFCall as at)
- 11 -> do aa <- get bh
- return (IfaceExt aa)
- 12 -> do ie <- get bh
- ico <- get bh
- return (IfaceCast ie ico)
- 13 -> do a <- get bh
- b <- get bh
- return (IfaceECase a b)
- _ -> panic ("get IfaceExpr " ++ show h)
-
-instance Binary IfaceTickish where
- put_ bh (IfaceHpcTick m ix) = do
- putByte bh 0
- put_ bh m
- put_ bh ix
- put_ bh (IfaceSCC cc tick push) = do
- putByte bh 1
- put_ bh cc
- put_ bh tick
- put_ bh push
- put_ bh (IfaceSource src name) = do
- putByte bh 2
- put_ bh (srcSpanFile src)
- put_ bh (srcSpanStartLine src)
- put_ bh (srcSpanStartCol src)
- put_ bh (srcSpanEndLine src)
- put_ bh (srcSpanEndCol src)
- put_ bh name
-
- get bh = do
- h <- getByte bh
- case h of
- 0 -> do m <- get bh
- ix <- get bh
- return (IfaceHpcTick m ix)
- 1 -> do cc <- get bh
- tick <- get bh
- push <- get bh
- return (IfaceSCC cc tick push)
- 2 -> do file <- get bh
- sl <- get bh
- sc <- get bh
- el <- get bh
- ec <- get bh
- let start = mkRealSrcLoc file sl sc
- end = mkRealSrcLoc file el ec
- name <- get bh
- return (IfaceSource (mkRealSrcSpan start end) name)
- _ -> panic ("get IfaceTickish " ++ show h)
-
-instance Binary IfaceConAlt where
- put_ bh IfaceDefault = putByte bh 0
- put_ bh (IfaceDataAlt aa) = putByte bh 1 >> put_ bh aa
- put_ bh (IfaceLitAlt ac) = putByte bh 2 >> put_ bh ac
- get bh = do
- h <- getByte bh
- case h of
- 0 -> return IfaceDefault
- 1 -> liftM IfaceDataAlt $ get bh
- _ -> liftM IfaceLitAlt $ get bh
-
-instance Binary IfaceBinding where
- put_ bh (IfaceNonRec aa ab) = putByte bh 0 >> put_ bh aa >> put_ bh ab
- put_ bh (IfaceRec ac) = putByte bh 1 >> put_ bh ac
- get bh = do
- h <- getByte bh
- case h of
- 0 -> do { aa <- get bh; ab <- get bh; return (IfaceNonRec aa ab) }
- _ -> do { ac <- get bh; return (IfaceRec ac) }
-
-instance Binary IfaceLetBndr where
- put_ bh (IfLetBndr a b c d) = do
- put_ bh a
- put_ bh b
- put_ bh c
- put_ bh d
- get bh = do a <- get bh
- b <- get bh
- c <- get bh
- d <- get bh
- return (IfLetBndr a b c d)
-
-instance Binary IfaceJoinInfo where
- put_ bh IfaceNotJoinPoint = putByte bh 0
- put_ bh (IfaceJoinPoint ar) = do
- putByte bh 1
- put_ bh ar
- get bh = do
- h <- getByte bh
- case h of
- 0 -> return IfaceNotJoinPoint
- _ -> liftM IfaceJoinPoint $ get bh
-
-instance Binary IfaceTyConParent where
- put_ bh IfNoParent = putByte bh 0
- put_ bh (IfDataInstance ax pr ty) = do
- putByte bh 1
- put_ bh ax
- put_ bh pr
- put_ bh ty
- get bh = do
- h <- getByte bh
- case h of
- 0 -> return IfNoParent
- _ -> do
- ax <- get bh
- pr <- get bh
- ty <- get bh
- return $ IfDataInstance ax pr ty
-
-instance Binary IfaceCompleteMatch where
- put_ bh (IfaceCompleteMatch cs ts) = put_ bh cs >> put_ bh ts
- get bh = IfaceCompleteMatch <$> get bh <*> get bh
-
-
-{-
-************************************************************************
-* *
- NFData instances
- See Note [Avoiding space leaks in toIface*] in ToIface
-* *
-************************************************************************
--}
-
-instance NFData IfaceDecl where
- rnf = \case
- IfaceId f1 f2 f3 f4 ->
- rnf f1 `seq` rnf f2 `seq` rnf f3 `seq` rnf f4
-
- IfaceData f1 f2 f3 f4 f5 f6 f7 f8 f9 ->
- f1 `seq` seqList f2 `seq` f3 `seq` f4 `seq` f5 `seq`
- rnf f6 `seq` rnf f7 `seq` rnf f8 `seq` rnf f9
-
- IfaceSynonym f1 f2 f3 f4 f5 ->
- rnf f1 `seq` f2 `seq` seqList f3 `seq` rnf f4 `seq` rnf f5
-
- IfaceFamily f1 f2 f3 f4 f5 f6 ->
- rnf f1 `seq` rnf f2 `seq` seqList f3 `seq` rnf f4 `seq` rnf f5 `seq` f6 `seq` ()
-
- IfaceClass f1 f2 f3 f4 f5 ->
- rnf f1 `seq` f2 `seq` seqList f3 `seq` rnf f4 `seq` rnf f5
-
- IfaceAxiom nm tycon role ax ->
- rnf nm `seq`
- rnf tycon `seq`
- role `seq`
- rnf ax
-
- IfacePatSyn f1 f2 f3 f4 f5 f6 f7 f8 f9 f10 f11 ->
- rnf f1 `seq` rnf f2 `seq` rnf f3 `seq` rnf f4 `seq` f5 `seq` f6 `seq`
- rnf f7 `seq` rnf f8 `seq` rnf f9 `seq` rnf f10 `seq` f11 `seq` ()
-
-instance NFData IfaceAxBranch where
- rnf (IfaceAxBranch f1 f2 f3 f4 f5 f6 f7) =
- rnf f1 `seq` rnf f2 `seq` rnf f3 `seq` rnf f4 `seq` f5 `seq` rnf f6 `seq` rnf f7
-
-instance NFData IfaceClassBody where
- rnf = \case
- IfAbstractClass -> ()
- IfConcreteClass f1 f2 f3 f4 -> rnf f1 `seq` rnf f2 `seq` rnf f3 `seq` f4 `seq` ()
-
-instance NFData IfaceAT where
- rnf (IfaceAT f1 f2) = rnf f1 `seq` rnf f2
-
-instance NFData IfaceClassOp where
- rnf (IfaceClassOp f1 f2 f3) = rnf f1 `seq` rnf f2 `seq` f3 `seq` ()
-
-instance NFData IfaceTyConParent where
- rnf = \case
- IfNoParent -> ()
- IfDataInstance f1 f2 f3 -> rnf f1 `seq` rnf f2 `seq` rnf f3
-
-instance NFData IfaceConDecls where
- rnf = \case
- IfAbstractTyCon -> ()
- IfDataTyCon f1 -> rnf f1
- IfNewTyCon f1 -> rnf f1
-
-instance NFData IfaceConDecl where
- rnf (IfCon f1 f2 f3 f4 f5 f6 f7 f8 f9 f10 f11) =
- rnf f1 `seq` rnf f2 `seq` rnf f3 `seq` rnf f4 `seq` f5 `seq` rnf f6 `seq`
- rnf f7 `seq` rnf f8 `seq` f9 `seq` rnf f10 `seq` rnf f11
-
-instance NFData IfaceSrcBang where
- rnf (IfSrcBang f1 f2) = f1 `seq` f2 `seq` ()
-
-instance NFData IfaceBang where
- rnf x = x `seq` ()
-
-instance NFData IfaceIdDetails where
- rnf = \case
- IfVanillaId -> ()
- IfRecSelId (Left tycon) b -> rnf tycon `seq` rnf b
- IfRecSelId (Right decl) b -> rnf decl `seq` rnf b
- IfDFunId -> ()
-
-instance NFData IfaceIdInfo where
- rnf = \case
- NoInfo -> ()
- HasInfo f1 -> rnf f1
-
-instance NFData IfaceInfoItem where
- rnf = \case
- HsArity a -> rnf a
- HsStrictness str -> seqStrictSig str
- HsInline p -> p `seq` () -- TODO: seq further?
- HsUnfold b unf -> rnf b `seq` rnf unf
- HsNoCafRefs -> ()
- HsLevity -> ()
-
-instance NFData IfaceUnfolding where
- rnf = \case
- IfCoreUnfold inlinable expr ->
- rnf inlinable `seq` rnf expr
- IfCompulsory expr ->
- rnf expr
- IfInlineRule arity b1 b2 e ->
- rnf arity `seq` rnf b1 `seq` rnf b2 `seq` rnf e
- IfDFunUnfold bndrs exprs ->
- rnf bndrs `seq` rnf exprs
-
-instance NFData IfaceExpr where
- rnf = \case
- IfaceLcl nm -> rnf nm
- IfaceExt nm -> rnf nm
- IfaceType ty -> rnf ty
- IfaceCo co -> rnf co
- IfaceTuple sort exprs -> sort `seq` rnf exprs
- IfaceLam bndr expr -> rnf bndr `seq` rnf expr
- IfaceApp e1 e2 -> rnf e1 `seq` rnf e2
- IfaceCase e nm alts -> rnf e `seq` nm `seq` rnf alts
- IfaceECase e ty -> rnf e `seq` rnf ty
- IfaceLet bind e -> rnf bind `seq` rnf e
- IfaceCast e co -> rnf e `seq` rnf co
- IfaceLit l -> l `seq` () -- FIXME
- IfaceFCall fc ty -> fc `seq` rnf ty
- IfaceTick tick e -> rnf tick `seq` rnf e
-
-instance NFData IfaceBinding where
- rnf = \case
- IfaceNonRec bndr e -> rnf bndr `seq` rnf e
- IfaceRec binds -> rnf binds
-
-instance NFData IfaceLetBndr where
- rnf (IfLetBndr nm ty id_info join_info) =
- rnf nm `seq` rnf ty `seq` rnf id_info `seq` rnf join_info
-
-instance NFData IfaceFamTyConFlav where
- rnf = \case
- IfaceDataFamilyTyCon -> ()
- IfaceOpenSynFamilyTyCon -> ()
- IfaceClosedSynFamilyTyCon f1 -> rnf f1
- IfaceAbstractClosedSynFamilyTyCon -> ()
- IfaceBuiltInSynFamTyCon -> ()
-
-instance NFData IfaceJoinInfo where
- rnf x = x `seq` ()
-
-instance NFData IfaceTickish where
- rnf = \case
- IfaceHpcTick m i -> rnf m `seq` rnf i
- IfaceSCC cc b1 b2 -> cc `seq` rnf b1 `seq` rnf b2
- IfaceSource src str -> src `seq` rnf str
-
-instance NFData IfaceConAlt where
- rnf = \case
- IfaceDefault -> ()
- IfaceDataAlt nm -> rnf nm
- IfaceLitAlt lit -> lit `seq` ()
-
-instance NFData IfaceCompleteMatch where
- rnf (IfaceCompleteMatch f1 f2) = rnf f1 `seq` rnf f2
-
-instance NFData IfaceRule where
- rnf (IfaceRule f1 f2 f3 f4 f5 f6 f7 f8) =
- rnf f1 `seq` f2 `seq` rnf f3 `seq` rnf f4 `seq` rnf f5 `seq` rnf f6 `seq` rnf f7 `seq` f8 `seq` ()
-
-instance NFData IfaceFamInst where
- rnf (IfaceFamInst f1 f2 f3 f4) =
- rnf f1 `seq` rnf f2 `seq` rnf f3 `seq` f4 `seq` ()
-
-instance NFData IfaceClsInst where
- rnf (IfaceClsInst f1 f2 f3 f4 f5) =
- f1 `seq` rnf f2 `seq` rnf f3 `seq` f4 `seq` f5 `seq` ()
-
-instance NFData IfaceAnnotation where
- rnf (IfaceAnnotation f1 f2) = f1 `seq` f2 `seq` ()
diff --git a/compiler/iface/IfaceType.hs b/compiler/iface/IfaceType.hs
deleted file mode 100644
index 7a8c617bb7..0000000000
--- a/compiler/iface/IfaceType.hs
+++ /dev/null
@@ -1,2060 +0,0 @@
-{-
-(c) The University of Glasgow 2006
-(c) The GRASP/AQUA Project, Glasgow University, 1993-1998
-
-
-This module defines interface types and binders
--}
-
-{-# LANGUAGE CPP, FlexibleInstances, BangPatterns #-}
-{-# LANGUAGE MultiWayIf #-}
-{-# LANGUAGE TupleSections #-}
-{-# LANGUAGE LambdaCase #-}
- -- FlexibleInstances for Binary (DefMethSpec IfaceType)
-
-module IfaceType (
- IfExtName, IfLclName,
-
- IfaceType(..), IfacePredType, IfaceKind, IfaceCoercion(..),
- IfaceMCoercion(..),
- IfaceUnivCoProv(..),
- IfaceTyCon(..), IfaceTyConInfo(..), IfaceTyConSort(..),
- IfaceTyLit(..), IfaceAppArgs(..),
- IfaceContext, IfaceBndr(..), IfaceOneShot(..), IfaceLamBndr,
- IfaceTvBndr, IfaceIdBndr, IfaceTyConBinder,
- IfaceForAllBndr, ArgFlag(..), AnonArgFlag(..),
- ForallVisFlag(..), ShowForAllFlag(..),
- mkIfaceForAllTvBndr,
- mkIfaceTyConKind,
-
- ifForAllBndrVar, ifForAllBndrName, ifaceBndrName,
- ifTyConBinderVar, ifTyConBinderName,
-
- -- Equality testing
- isIfaceLiftedTypeKind,
-
- -- Conversion from IfaceAppArgs to IfaceTypes/ArgFlags
- appArgsIfaceTypes, appArgsIfaceTypesArgFlags,
-
- -- Printing
- SuppressBndrSig(..),
- UseBndrParens(..),
- pprIfaceType, pprParendIfaceType, pprPrecIfaceType,
- pprIfaceContext, pprIfaceContextArr,
- pprIfaceIdBndr, pprIfaceLamBndr, pprIfaceTvBndr, pprIfaceTyConBinders,
- pprIfaceBndrs, pprIfaceAppArgs, pprParendIfaceAppArgs,
- pprIfaceForAllPart, pprIfaceForAllPartMust, pprIfaceForAll,
- pprIfaceSigmaType, pprIfaceTyLit,
- pprIfaceCoercion, pprParendIfaceCoercion,
- splitIfaceSigmaTy, pprIfaceTypeApp, pprUserIfaceForAll,
- pprIfaceCoTcApp, pprTyTcApp, pprIfacePrefixApp,
- isIfaceTauType,
-
- suppressIfaceInvisibles,
- stripIfaceInvisVars,
- stripInvisArgs,
-
- mkIfaceTySubst, substIfaceTyVar, substIfaceAppArgs, inDomIfaceTySubst
- ) where
-
-#include "HsVersions.h"
-
-import GhcPrelude
-
-import {-# SOURCE #-} TysWiredIn ( coercibleTyCon, heqTyCon
- , liftedRepDataConTyCon, tupleTyConName )
-import {-# SOURCE #-} Type ( isRuntimeRepTy )
-
-import DynFlags
-import TyCon hiding ( pprPromotionQuote )
-import CoAxiom
-import Var
-import PrelNames
-import Name
-import BasicTypes
-import Binary
-import Outputable
-import FastString
-import FastStringEnv
-import Util
-
-import Data.Maybe( isJust )
-import qualified Data.Semigroup as Semi
-import Control.DeepSeq
-
-{-
-************************************************************************
-* *
- Local (nested) binders
-* *
-************************************************************************
--}
-
-type IfLclName = FastString -- A local name in iface syntax
-
-type IfExtName = Name -- An External or WiredIn Name can appear in IfaceSyn
- -- (However Internal or System Names never should)
-
-data IfaceBndr -- Local (non-top-level) binders
- = IfaceIdBndr {-# UNPACK #-} !IfaceIdBndr
- | IfaceTvBndr {-# UNPACK #-} !IfaceTvBndr
-
-type IfaceIdBndr = (IfLclName, IfaceType)
-type IfaceTvBndr = (IfLclName, IfaceKind)
-
-ifaceTvBndrName :: IfaceTvBndr -> IfLclName
-ifaceTvBndrName (n,_) = n
-
-ifaceIdBndrName :: IfaceIdBndr -> IfLclName
-ifaceIdBndrName (n,_) = n
-
-ifaceBndrName :: IfaceBndr -> IfLclName
-ifaceBndrName (IfaceTvBndr bndr) = ifaceTvBndrName bndr
-ifaceBndrName (IfaceIdBndr bndr) = ifaceIdBndrName bndr
-
-ifaceBndrType :: IfaceBndr -> IfaceType
-ifaceBndrType (IfaceIdBndr (_, t)) = t
-ifaceBndrType (IfaceTvBndr (_, t)) = t
-
-type IfaceLamBndr = (IfaceBndr, IfaceOneShot)
-
-data IfaceOneShot -- See Note [Preserve OneShotInfo] in CoreTicy
- = IfaceNoOneShot -- and Note [The oneShot function] in MkId
- | IfaceOneShot
-
-
-{-
-%************************************************************************
-%* *
- IfaceType
-%* *
-%************************************************************************
--}
-
--------------------------------
-type IfaceKind = IfaceType
-
--- | A kind of universal type, used for types and kinds.
---
--- Any time a 'Type' is pretty-printed, it is first converted to an 'IfaceType'
--- before being printed. See Note [Pretty printing via IfaceSyn] in PprTyThing
-data IfaceType
- = IfaceFreeTyVar TyVar -- See Note [Free tyvars in IfaceType]
- | IfaceTyVar IfLclName -- Type/coercion variable only, not tycon
- | IfaceLitTy IfaceTyLit
- | IfaceAppTy IfaceType IfaceAppArgs
- -- See Note [Suppressing invisible arguments] for
- -- an explanation of why the second field isn't
- -- IfaceType, analogous to AppTy.
- | IfaceFunTy AnonArgFlag IfaceType IfaceType
- | IfaceForAllTy IfaceForAllBndr IfaceType
- | IfaceTyConApp IfaceTyCon IfaceAppArgs -- Not necessarily saturated
- -- Includes newtypes, synonyms, tuples
- | IfaceCastTy IfaceType IfaceCoercion
- | IfaceCoercionTy IfaceCoercion
-
- | IfaceTupleTy -- Saturated tuples (unsaturated ones use IfaceTyConApp)
- TupleSort -- What sort of tuple?
- PromotionFlag -- A bit like IfaceTyCon
- IfaceAppArgs -- arity = length args
- -- For promoted data cons, the kind args are omitted
-
-type IfacePredType = IfaceType
-type IfaceContext = [IfacePredType]
-
-data IfaceTyLit
- = IfaceNumTyLit Integer
- | IfaceStrTyLit FastString
- deriving (Eq)
-
-type IfaceTyConBinder = VarBndr IfaceBndr TyConBndrVis
-type IfaceForAllBndr = VarBndr IfaceBndr ArgFlag
-
--- | Make an 'IfaceForAllBndr' from an 'IfaceTvBndr'.
-mkIfaceForAllTvBndr :: ArgFlag -> IfaceTvBndr -> IfaceForAllBndr
-mkIfaceForAllTvBndr vis var = Bndr (IfaceTvBndr var) vis
-
--- | Build the 'tyConKind' from the binders and the result kind.
--- Keep in sync with 'mkTyConKind' in types/TyCon.
-mkIfaceTyConKind :: [IfaceTyConBinder] -> IfaceKind -> IfaceKind
-mkIfaceTyConKind bndrs res_kind = foldr mk res_kind bndrs
- where
- mk :: IfaceTyConBinder -> IfaceKind -> IfaceKind
- mk (Bndr tv (AnonTCB af)) k = IfaceFunTy af (ifaceBndrType tv) k
- mk (Bndr tv (NamedTCB vis)) k = IfaceForAllTy (Bndr tv vis) k
-
--- | Stores the arguments in a type application as a list.
--- See @Note [Suppressing invisible arguments]@.
-data IfaceAppArgs
- = IA_Nil
- | IA_Arg IfaceType -- The type argument
-
- ArgFlag -- The argument's visibility. We store this here so
- -- that we can:
- --
- -- 1. Avoid pretty-printing invisible (i.e., specified
- -- or inferred) arguments when
- -- -fprint-explicit-kinds isn't enabled, or
- -- 2. When -fprint-explicit-kinds *is*, enabled, print
- -- specified arguments in @(...) and inferred
- -- arguments in @{...}.
-
- IfaceAppArgs -- The rest of the arguments
-
-instance Semi.Semigroup IfaceAppArgs where
- IA_Nil <> xs = xs
- IA_Arg ty argf rest <> xs = IA_Arg ty argf (rest Semi.<> xs)
-
-instance Monoid IfaceAppArgs where
- mempty = IA_Nil
- mappend = (Semi.<>)
-
--- Encodes type constructors, kind constructors,
--- coercion constructors, the lot.
--- We have to tag them in order to pretty print them
--- properly.
-data IfaceTyCon = IfaceTyCon { ifaceTyConName :: IfExtName
- , ifaceTyConInfo :: IfaceTyConInfo }
- deriving (Eq)
-
--- | The various types of TyCons which have special, built-in syntax.
-data IfaceTyConSort = IfaceNormalTyCon -- ^ a regular tycon
-
- | IfaceTupleTyCon !Arity !TupleSort
- -- ^ e.g. @(a, b, c)@ or @(#a, b, c#)@.
- -- The arity is the tuple width, not the tycon arity
- -- (which is twice the width in the case of unboxed
- -- tuples).
-
- | IfaceSumTyCon !Arity
- -- ^ e.g. @(a | b | c)@
-
- | IfaceEqualityTyCon
- -- ^ A heterogeneous equality TyCon
- -- (i.e. eqPrimTyCon, eqReprPrimTyCon, heqTyCon)
- -- that is actually being applied to two types
- -- of the same kind. This affects pretty-printing
- -- only: see Note [Equality predicates in IfaceType]
- deriving (Eq)
-
-{- Note [Free tyvars in IfaceType]
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-Nowadays (since Nov 16, 2016) we pretty-print a Type by converting to
-an IfaceType and pretty printing that. This eliminates a lot of
-pretty-print duplication, and it matches what we do with pretty-
-printing TyThings. See Note [Pretty printing via IfaceSyn] in PprTyThing.
-
-It works fine for closed types, but when printing debug traces (e.g.
-when using -ddump-tc-trace) we print a lot of /open/ types. These
-types are full of TcTyVars, and it's absolutely crucial to print them
-in their full glory, with their unique, TcTyVarDetails etc.
-
-So we simply embed a TyVar in IfaceType with the IfaceFreeTyVar constructor.
-Note that:
-
-* We never expect to serialise an IfaceFreeTyVar into an interface file, nor
- to deserialise one. IfaceFreeTyVar is used only in the "convert to IfaceType
- and then pretty-print" pipeline.
-
-We do the same for covars, naturally.
-
-Note [Equality predicates in IfaceType]
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-GHC has several varieties of type equality (see Note [The equality types story]
-in TysPrim for details). In an effort to avoid confusing users, we suppress
-the differences during pretty printing unless certain flags are enabled.
-Here is how each equality predicate* is printed in homogeneous and
-heterogeneous contexts, depending on which combination of the
--fprint-explicit-kinds and -fprint-equality-relations flags is used:
-
---------------------------------------------------------------------------------------------
-| Predicate | Neither flag | -fprint-explicit-kinds |
-|-------------------------------|----------------------------|-----------------------------|
-| a ~ b (homogeneous) | a ~ b | (a :: Type) ~ (b :: Type) |
-| a ~~ b, homogeneously | a ~ b | (a :: Type) ~ (b :: Type) |
-| a ~~ b, heterogeneously | a ~~ c | (a :: Type) ~~ (c :: k) |
-| a ~# b, homogeneously | a ~ b | (a :: Type) ~ (b :: Type) |
-| a ~# b, heterogeneously | a ~~ c | (a :: Type) ~~ (c :: k) |
-| Coercible a b (homogeneous) | Coercible a b | Coercible @Type a b |
-| a ~R# b, homogeneously | Coercible a b | Coercible @Type a b |
-| a ~R# b, heterogeneously | a ~R# b | (a :: Type) ~R# (c :: k) |
-|-------------------------------|----------------------------|-----------------------------|
-| Predicate | -fprint-equality-relations | Both flags |
-|-------------------------------|----------------------------|-----------------------------|
-| a ~ b (homogeneous) | a ~ b | (a :: Type) ~ (b :: Type) |
-| a ~~ b, homogeneously | a ~~ b | (a :: Type) ~~ (b :: Type) |
-| a ~~ b, heterogeneously | a ~~ c | (a :: Type) ~~ (c :: k) |
-| a ~# b, homogeneously | a ~# b | (a :: Type) ~# (b :: Type) |
-| a ~# b, heterogeneously | a ~# c | (a :: Type) ~# (c :: k) |
-| Coercible a b (homogeneous) | Coercible a b | Coercible @Type a b |
-| a ~R# b, homogeneously | a ~R# b | (a :: Type) ~R# (b :: Type) |
-| a ~R# b, heterogeneously | a ~R# b | (a :: Type) ~R# (c :: k) |
---------------------------------------------------------------------------------------------
-
-(* There is no heterogeneous, representational, lifted equality counterpart
-to (~~). There could be, but there seems to be no use for it.)
-
-This table adheres to the following rules:
-
-A. With -fprint-equality-relations, print the true equality relation.
-B. Without -fprint-equality-relations:
- i. If the equality is representational and homogeneous, use Coercible.
- ii. Otherwise, if the equality is representational, use ~R#.
- iii. If the equality is nominal and homogeneous, use ~.
- iv. Otherwise, if the equality is nominal, use ~~.
-C. With -fprint-explicit-kinds, print kinds on both sides of an infix operator,
- as above; or print the kind with Coercible.
-D. Without -fprint-explicit-kinds, don't print kinds.
-
-A hetero-kinded equality is used homogeneously when it is applied to two
-identical kinds. Unfortunately, determining this from an IfaceType isn't
-possible since we can't see through type synonyms. Consequently, we need to
-record whether this particular application is homogeneous in IfaceTyConSort
-for the purposes of pretty-printing.
-
-See Note [The equality types story] in TysPrim.
--}
-
-data IfaceTyConInfo -- Used to guide pretty-printing
- -- and to disambiguate D from 'D (they share a name)
- = IfaceTyConInfo { ifaceTyConIsPromoted :: PromotionFlag
- , ifaceTyConSort :: IfaceTyConSort }
- deriving (Eq)
-
-data IfaceMCoercion
- = IfaceMRefl
- | IfaceMCo IfaceCoercion
-
-data IfaceCoercion
- = IfaceReflCo IfaceType
- | IfaceGReflCo Role IfaceType (IfaceMCoercion)
- | IfaceFunCo Role IfaceCoercion IfaceCoercion
- | IfaceTyConAppCo Role IfaceTyCon [IfaceCoercion]
- | IfaceAppCo IfaceCoercion IfaceCoercion
- | IfaceForAllCo IfaceBndr IfaceCoercion IfaceCoercion
- | IfaceCoVarCo IfLclName
- | IfaceAxiomInstCo IfExtName BranchIndex [IfaceCoercion]
- | IfaceAxiomRuleCo IfLclName [IfaceCoercion]
- -- There are only a fixed number of CoAxiomRules, so it suffices
- -- to use an IfaceLclName to distinguish them.
- -- See Note [Adding built-in type families] in TcTypeNats
- | IfaceUnivCo IfaceUnivCoProv Role IfaceType IfaceType
- | IfaceSymCo IfaceCoercion
- | IfaceTransCo IfaceCoercion IfaceCoercion
- | IfaceNthCo Int IfaceCoercion
- | IfaceLRCo LeftOrRight IfaceCoercion
- | IfaceInstCo IfaceCoercion IfaceCoercion
- | IfaceKindCo IfaceCoercion
- | IfaceSubCo IfaceCoercion
- | IfaceFreeCoVar CoVar -- See Note [Free tyvars in IfaceType]
- | IfaceHoleCo CoVar -- ^ See Note [Holes in IfaceCoercion]
-
-data IfaceUnivCoProv
- = IfaceUnsafeCoerceProv
- | IfacePhantomProv IfaceCoercion
- | IfaceProofIrrelProv IfaceCoercion
- | IfacePluginProv String
-
-{- Note [Holes in IfaceCoercion]
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-When typechecking fails the typechecker will produce a HoleCo to stand
-in place of the unproven assertion. While we generally don't want to
-let these unproven assertions leak into interface files, we still need
-to be able to pretty-print them as we use IfaceType's pretty-printer
-to render Types. For this reason IfaceCoercion has a IfaceHoleCo
-constructor; however, we fails when asked to serialize to a
-IfaceHoleCo to ensure that they don't end up in an interface file.
-
-
-%************************************************************************
-%* *
- Functions over IFaceTypes
-* *
-************************************************************************
--}
-
-ifaceTyConHasKey :: IfaceTyCon -> Unique -> Bool
-ifaceTyConHasKey tc key = ifaceTyConName tc `hasKey` key
-
-isIfaceLiftedTypeKind :: IfaceKind -> Bool
-isIfaceLiftedTypeKind (IfaceTyConApp tc IA_Nil)
- = isLiftedTypeKindTyConName (ifaceTyConName tc)
-isIfaceLiftedTypeKind (IfaceTyConApp tc
- (IA_Arg (IfaceTyConApp ptr_rep_lifted IA_Nil)
- Required IA_Nil))
- = tc `ifaceTyConHasKey` tYPETyConKey
- && ptr_rep_lifted `ifaceTyConHasKey` liftedRepDataConKey
-isIfaceLiftedTypeKind _ = False
-
-splitIfaceSigmaTy :: IfaceType -> ([IfaceForAllBndr], [IfacePredType], IfaceType)
--- Mainly for printing purposes
---
--- Here we split nested IfaceSigmaTy properly.
---
--- @
--- forall t. T t => forall m a b. M m => (a -> m b) -> t a -> m (t b)
--- @
---
--- If you called @splitIfaceSigmaTy@ on this type:
---
--- @
--- ([t, m, a, b], [T t, M m], (a -> m b) -> t a -> m (t b))
--- @
-splitIfaceSigmaTy ty
- = case (bndrs, theta) of
- ([], []) -> (bndrs, theta, tau)
- _ -> let (bndrs', theta', tau') = splitIfaceSigmaTy tau
- in (bndrs ++ bndrs', theta ++ theta', tau')
- where
- (bndrs, rho) = split_foralls ty
- (theta, tau) = split_rho rho
-
- split_foralls (IfaceForAllTy bndr ty)
- = case split_foralls ty of { (bndrs, rho) -> (bndr:bndrs, rho) }
- split_foralls rho = ([], rho)
-
- split_rho (IfaceFunTy InvisArg ty1 ty2)
- = case split_rho ty2 of { (ps, tau) -> (ty1:ps, tau) }
- split_rho tau = ([], tau)
-
-suppressIfaceInvisibles :: DynFlags -> [IfaceTyConBinder] -> [a] -> [a]
-suppressIfaceInvisibles dflags tys xs
- | gopt Opt_PrintExplicitKinds dflags = xs
- | otherwise = suppress tys xs
- where
- suppress _ [] = []
- suppress [] a = a
- suppress (k:ks) (x:xs)
- | isInvisibleTyConBinder k = suppress ks xs
- | otherwise = x : suppress ks xs
-
-stripIfaceInvisVars :: DynFlags -> [IfaceTyConBinder] -> [IfaceTyConBinder]
-stripIfaceInvisVars dflags tyvars
- | gopt Opt_PrintExplicitKinds dflags = tyvars
- | otherwise = filterOut isInvisibleTyConBinder tyvars
-
--- | Extract an 'IfaceBndr' from an 'IfaceForAllBndr'.
-ifForAllBndrVar :: IfaceForAllBndr -> IfaceBndr
-ifForAllBndrVar = binderVar
-
--- | Extract the variable name from an 'IfaceForAllBndr'.
-ifForAllBndrName :: IfaceForAllBndr -> IfLclName
-ifForAllBndrName fab = ifaceBndrName (ifForAllBndrVar fab)
-
--- | Extract an 'IfaceBndr' from an 'IfaceTyConBinder'.
-ifTyConBinderVar :: IfaceTyConBinder -> IfaceBndr
-ifTyConBinderVar = binderVar
-
--- | Extract the variable name from an 'IfaceTyConBinder'.
-ifTyConBinderName :: IfaceTyConBinder -> IfLclName
-ifTyConBinderName tcb = ifaceBndrName (ifTyConBinderVar tcb)
-
-ifTypeIsVarFree :: IfaceType -> Bool
--- Returns True if the type definitely has no variables at all
--- Just used to control pretty printing
-ifTypeIsVarFree ty = go ty
- where
- go (IfaceTyVar {}) = False
- go (IfaceFreeTyVar {}) = False
- go (IfaceAppTy fun args) = go fun && go_args args
- go (IfaceFunTy _ arg res) = go arg && go res
- go (IfaceForAllTy {}) = False
- go (IfaceTyConApp _ args) = go_args args
- go (IfaceTupleTy _ _ args) = go_args args
- go (IfaceLitTy _) = True
- go (IfaceCastTy {}) = False -- Safe
- go (IfaceCoercionTy {}) = False -- Safe
-
- go_args IA_Nil = True
- go_args (IA_Arg arg _ args) = go arg && go_args args
-
-{- Note [Substitution on IfaceType]
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-Substitutions on IfaceType are done only during pretty-printing to
-construct the result type of a GADT, and does not deal with binders
-(eg IfaceForAll), so it doesn't need fancy capture stuff. -}
-
-type IfaceTySubst = FastStringEnv IfaceType -- Note [Substitution on IfaceType]
-
-mkIfaceTySubst :: [(IfLclName,IfaceType)] -> IfaceTySubst
--- See Note [Substitution on IfaceType]
-mkIfaceTySubst eq_spec = mkFsEnv eq_spec
-
-inDomIfaceTySubst :: IfaceTySubst -> IfaceTvBndr -> Bool
--- See Note [Substitution on IfaceType]
-inDomIfaceTySubst subst (fs, _) = isJust (lookupFsEnv subst fs)
-
-substIfaceType :: IfaceTySubst -> IfaceType -> IfaceType
--- See Note [Substitution on IfaceType]
-substIfaceType env ty
- = go ty
- where
- go (IfaceFreeTyVar tv) = IfaceFreeTyVar tv
- go (IfaceTyVar tv) = substIfaceTyVar env tv
- go (IfaceAppTy t ts) = IfaceAppTy (go t) (substIfaceAppArgs env ts)
- go (IfaceFunTy af t1 t2) = IfaceFunTy af (go t1) (go t2)
- go ty@(IfaceLitTy {}) = ty
- go (IfaceTyConApp tc tys) = IfaceTyConApp tc (substIfaceAppArgs env tys)
- go (IfaceTupleTy s i tys) = IfaceTupleTy s i (substIfaceAppArgs env tys)
- go (IfaceForAllTy {}) = pprPanic "substIfaceType" (ppr ty)
- go (IfaceCastTy ty co) = IfaceCastTy (go ty) (go_co co)
- go (IfaceCoercionTy co) = IfaceCoercionTy (go_co co)
-
- go_mco IfaceMRefl = IfaceMRefl
- go_mco (IfaceMCo co) = IfaceMCo $ go_co co
-
- go_co (IfaceReflCo ty) = IfaceReflCo (go ty)
- go_co (IfaceGReflCo r ty mco) = IfaceGReflCo r (go ty) (go_mco mco)
- go_co (IfaceFunCo r c1 c2) = IfaceFunCo r (go_co c1) (go_co c2)
- go_co (IfaceTyConAppCo r tc cos) = IfaceTyConAppCo r tc (go_cos cos)
- go_co (IfaceAppCo c1 c2) = IfaceAppCo (go_co c1) (go_co c2)
- go_co (IfaceForAllCo {}) = pprPanic "substIfaceCoercion" (ppr ty)
- go_co (IfaceFreeCoVar cv) = IfaceFreeCoVar cv
- go_co (IfaceCoVarCo cv) = IfaceCoVarCo cv
- go_co (IfaceHoleCo cv) = IfaceHoleCo cv
- go_co (IfaceAxiomInstCo a i cos) = IfaceAxiomInstCo a i (go_cos cos)
- go_co (IfaceUnivCo prov r t1 t2) = IfaceUnivCo (go_prov prov) r (go t1) (go t2)
- go_co (IfaceSymCo co) = IfaceSymCo (go_co co)
- go_co (IfaceTransCo co1 co2) = IfaceTransCo (go_co co1) (go_co co2)
- go_co (IfaceNthCo n co) = IfaceNthCo n (go_co co)
- go_co (IfaceLRCo lr co) = IfaceLRCo lr (go_co co)
- go_co (IfaceInstCo c1 c2) = IfaceInstCo (go_co c1) (go_co c2)
- go_co (IfaceKindCo co) = IfaceKindCo (go_co co)
- go_co (IfaceSubCo co) = IfaceSubCo (go_co co)
- go_co (IfaceAxiomRuleCo n cos) = IfaceAxiomRuleCo n (go_cos cos)
-
- go_cos = map go_co
-
- go_prov IfaceUnsafeCoerceProv = IfaceUnsafeCoerceProv
- go_prov (IfacePhantomProv co) = IfacePhantomProv (go_co co)
- go_prov (IfaceProofIrrelProv co) = IfaceProofIrrelProv (go_co co)
- go_prov (IfacePluginProv str) = IfacePluginProv str
-
-substIfaceAppArgs :: IfaceTySubst -> IfaceAppArgs -> IfaceAppArgs
-substIfaceAppArgs env args
- = go args
- where
- go IA_Nil = IA_Nil
- go (IA_Arg ty arg tys) = IA_Arg (substIfaceType env ty) arg (go tys)
-
-substIfaceTyVar :: IfaceTySubst -> IfLclName -> IfaceType
-substIfaceTyVar env tv
- | Just ty <- lookupFsEnv env tv = ty
- | otherwise = IfaceTyVar tv
-
-
-{-
-************************************************************************
-* *
- Functions over IfaceAppArgs
-* *
-************************************************************************
--}
-
-stripInvisArgs :: DynFlags -> IfaceAppArgs -> IfaceAppArgs
-stripInvisArgs dflags tys
- | gopt Opt_PrintExplicitKinds dflags = tys
- | otherwise = suppress_invis tys
- where
- suppress_invis c
- = case c of
- IA_Nil -> IA_Nil
- IA_Arg t argf ts
- | isVisibleArgFlag argf
- -> IA_Arg t argf $ suppress_invis ts
- -- Keep recursing through the remainder of the arguments, as it's
- -- possible that there are remaining invisible ones.
- -- See the "In type declarations" section of Note [VarBndrs,
- -- TyCoVarBinders, TyConBinders, and visibility] in TyCoRep.
- | otherwise
- -> suppress_invis ts
-
-appArgsIfaceTypes :: IfaceAppArgs -> [IfaceType]
-appArgsIfaceTypes IA_Nil = []
-appArgsIfaceTypes (IA_Arg t _ ts) = t : appArgsIfaceTypes ts
-
-appArgsIfaceTypesArgFlags :: IfaceAppArgs -> [(IfaceType, ArgFlag)]
-appArgsIfaceTypesArgFlags IA_Nil = []
-appArgsIfaceTypesArgFlags (IA_Arg t a ts)
- = (t, a) : appArgsIfaceTypesArgFlags ts
-
-ifaceVisAppArgsLength :: IfaceAppArgs -> Int
-ifaceVisAppArgsLength = go 0
- where
- go !n IA_Nil = n
- go n (IA_Arg _ argf rest)
- | isVisibleArgFlag argf = go (n+1) rest
- | otherwise = go n rest
-
-{-
-Note [Suppressing invisible arguments]
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-We use the IfaceAppArgs data type to specify which of the arguments to a type
-should be displayed when pretty-printing, under the control of
--fprint-explicit-kinds.
-See also Type.filterOutInvisibleTypes.
-For example, given
-
- T :: forall k. (k->*) -> k -> * -- Ordinary kind polymorphism
- 'Just :: forall k. k -> 'Maybe k -- Promoted
-
-we want
-
- T * Tree Int prints as T Tree Int
- 'Just * prints as Just *
-
-For type constructors (IfaceTyConApp), IfaceAppArgs is a quite natural fit,
-since the corresponding Core constructor:
-
- data Type
- = ...
- | TyConApp TyCon [Type]
-
-Already puts all of its arguments into a list. So when converting a Type to an
-IfaceType (see toIfaceAppArgsX in ToIface), we simply use the kind of the TyCon
-(which is cached) to guide the process of converting the argument Types into an
-IfaceAppArgs list.
-
-We also want this behavior for IfaceAppTy, since given:
-
- data Proxy (a :: k)
- f :: forall (t :: forall a. a -> Type). Proxy Type (t Bool True)
-
-We want to print the return type as `Proxy (t True)` without the use of
--fprint-explicit-kinds (#15330). Accomplishing this is trickier than in the
-tycon case, because the corresponding Core constructor for IfaceAppTy:
-
- data Type
- = ...
- | AppTy Type Type
-
-Only stores one argument at a time. Therefore, when converting an AppTy to an
-IfaceAppTy (in toIfaceTypeX in ToIface), we:
-
-1. Flatten the chain of AppTys down as much as possible
-2. Use typeKind to determine the function Type's kind
-3. Use this kind to guide the process of converting the argument Types into an
- IfaceAppArgs list.
-
-By flattening the arguments like this, we obtain two benefits:
-
-(a) We can reuse the same machinery to pretty-print IfaceTyConApp arguments as
- we do IfaceTyApp arguments, which means that we only need to implement the
- logic to filter out invisible arguments once.
-(b) Unlike for tycons, finding the kind of a type in general (through typeKind)
- is not a constant-time operation, so by flattening the arguments first, we
- decrease the number of times we have to call typeKind.
-
-Note [Pretty-printing invisible arguments]
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-Note [Suppressing invisible arguments] is all about how to avoid printing
-invisible arguments when the -fprint-explicit-kinds flag is disables. Well,
-what about when it's enabled? Then we can and should print invisible kind
-arguments, and this Note explains how we do it.
-
-As two running examples, consider the following code:
-
- {-# LANGUAGE PolyKinds #-}
- data T1 a
- data T2 (a :: k)
-
-When displaying these types (with -fprint-explicit-kinds on), we could just
-do the following:
-
- T1 k a
- T2 k a
-
-That certainly gets the job done. But it lacks a crucial piece of information:
-is the `k` argument inferred or specified? To communicate this, we use visible
-kind application syntax to distinguish the two cases:
-
- T1 @{k} a
- T2 @k a
-
-Here, @{k} indicates that `k` is an inferred argument, and @k indicates that
-`k` is a specified argument. (See
-Note [VarBndrs, TyCoVarBinders, TyConBinders, and visibility] in TyCoRep for
-a lengthier explanation on what "inferred" and "specified" mean.)
-
-************************************************************************
-* *
- Pretty-printing
-* *
-************************************************************************
--}
-
-if_print_coercions :: SDoc -- ^ if printing coercions
- -> SDoc -- ^ otherwise
- -> SDoc
-if_print_coercions yes no
- = sdocWithDynFlags $ \dflags ->
- getPprStyle $ \style ->
- if gopt Opt_PrintExplicitCoercions dflags
- || dumpStyle style || debugStyle style
- then yes
- else no
-
-pprIfaceInfixApp :: PprPrec -> SDoc -> SDoc -> SDoc -> SDoc
-pprIfaceInfixApp ctxt_prec pp_tc pp_ty1 pp_ty2
- = maybeParen ctxt_prec opPrec $
- sep [pp_ty1, pp_tc <+> pp_ty2]
-
-pprIfacePrefixApp :: PprPrec -> SDoc -> [SDoc] -> SDoc
-pprIfacePrefixApp ctxt_prec pp_fun pp_tys
- | null pp_tys = pp_fun
- | otherwise = maybeParen ctxt_prec appPrec $
- hang pp_fun 2 (sep pp_tys)
-
-isIfaceTauType :: IfaceType -> Bool
-isIfaceTauType (IfaceForAllTy _ _) = False
-isIfaceTauType (IfaceFunTy InvisArg _ _) = False
-isIfaceTauType _ = True
-
--- ----------------------------- Printing binders ------------------------------------
-
-instance Outputable IfaceBndr where
- ppr (IfaceIdBndr bndr) = pprIfaceIdBndr bndr
- ppr (IfaceTvBndr bndr) = char '@' <+> pprIfaceTvBndr bndr (SuppressBndrSig False)
- (UseBndrParens False)
-
-pprIfaceBndrs :: [IfaceBndr] -> SDoc
-pprIfaceBndrs bs = sep (map ppr bs)
-
-pprIfaceLamBndr :: IfaceLamBndr -> SDoc
-pprIfaceLamBndr (b, IfaceNoOneShot) = ppr b
-pprIfaceLamBndr (b, IfaceOneShot) = ppr b <> text "[OneShot]"
-
-pprIfaceIdBndr :: IfaceIdBndr -> SDoc
-pprIfaceIdBndr (name, ty) = parens (ppr name <+> dcolon <+> ppr ty)
-
-{- Note [Suppressing binder signatures]
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-When printing the binders in a 'forall', we want to keep the kind annotations:
-
- forall (a :: k). blah
- ^^^^
- good
-
-On the other hand, when we print the binders of a data declaration in :info,
-the kind information would be redundant due to the standalone kind signature:
-
- type F :: Symbol -> Type
- type F (s :: Symbol) = blah
- ^^^^^^^^^
- redundant
-
-Here we'd like to omit the kind annotation:
-
- type F :: Symbol -> Type
- type F s = blah
--}
-
--- | Do we want to suppress kind annotations on binders?
--- See Note [Suppressing binder signatures]
-newtype SuppressBndrSig = SuppressBndrSig Bool
-
-newtype UseBndrParens = UseBndrParens Bool
-
-pprIfaceTvBndr :: IfaceTvBndr -> SuppressBndrSig -> UseBndrParens -> SDoc
-pprIfaceTvBndr (tv, ki) (SuppressBndrSig suppress_sig) (UseBndrParens use_parens)
- | suppress_sig = ppr tv
- | isIfaceLiftedTypeKind ki = ppr tv
- | otherwise = maybe_parens (ppr tv <+> dcolon <+> ppr ki)
- where
- maybe_parens | use_parens = parens
- | otherwise = id
-
-pprIfaceTyConBinders :: SuppressBndrSig -> [IfaceTyConBinder] -> SDoc
-pprIfaceTyConBinders suppress_sig = sep . map go
- where
- go :: IfaceTyConBinder -> SDoc
- go (Bndr (IfaceIdBndr bndr) _) = pprIfaceIdBndr bndr
- go (Bndr (IfaceTvBndr bndr) vis) =
- -- See Note [Pretty-printing invisible arguments]
- case vis of
- AnonTCB VisArg -> ppr_bndr (UseBndrParens True)
- AnonTCB InvisArg -> char '@' <> braces (ppr_bndr (UseBndrParens False))
- -- The above case is rare. (See Note [AnonTCB InvisArg] in TyCon.)
- -- Should we print these differently?
- NamedTCB Required -> ppr_bndr (UseBndrParens True)
- NamedTCB Specified -> char '@' <> ppr_bndr (UseBndrParens True)
- NamedTCB Inferred -> char '@' <> braces (ppr_bndr (UseBndrParens False))
- where
- ppr_bndr = pprIfaceTvBndr bndr suppress_sig
-
-instance Binary IfaceBndr where
- put_ bh (IfaceIdBndr aa) = do
- putByte bh 0
- put_ bh aa
- put_ bh (IfaceTvBndr ab) = do
- putByte bh 1
- put_ bh ab
- get bh = do
- h <- getByte bh
- case h of
- 0 -> do aa <- get bh
- return (IfaceIdBndr aa)
- _ -> do ab <- get bh
- return (IfaceTvBndr ab)
-
-instance Binary IfaceOneShot where
- put_ bh IfaceNoOneShot = do
- putByte bh 0
- put_ bh IfaceOneShot = do
- putByte bh 1
- get bh = do
- h <- getByte bh
- case h of
- 0 -> do return IfaceNoOneShot
- _ -> do return IfaceOneShot
-
--- ----------------------------- Printing IfaceType ------------------------------------
-
----------------------------------
-instance Outputable IfaceType where
- ppr ty = pprIfaceType ty
-
-pprIfaceType, pprParendIfaceType :: IfaceType -> SDoc
-pprIfaceType = pprPrecIfaceType topPrec
-pprParendIfaceType = pprPrecIfaceType appPrec
-
-pprPrecIfaceType :: PprPrec -> IfaceType -> SDoc
--- We still need `eliminateRuntimeRep`, since the `pprPrecIfaceType` maybe
--- called from other places, besides `:type` and `:info`.
-pprPrecIfaceType prec ty = eliminateRuntimeRep (ppr_ty prec) ty
-
-ppr_sigma :: PprPrec -> IfaceType -> SDoc
-ppr_sigma ctxt_prec ty
- = maybeParen ctxt_prec funPrec (pprIfaceSigmaType ShowForAllMust ty)
-
-ppr_ty :: PprPrec -> IfaceType -> SDoc
-ppr_ty ctxt_prec ty@(IfaceForAllTy {}) = ppr_sigma ctxt_prec ty
-ppr_ty ctxt_prec ty@(IfaceFunTy InvisArg _ _) = ppr_sigma ctxt_prec ty
-
-ppr_ty _ (IfaceFreeTyVar tyvar) = ppr tyvar -- This is the main reason for IfaceFreeTyVar!
-ppr_ty _ (IfaceTyVar tyvar) = ppr tyvar -- See Note [TcTyVars in IfaceType]
-ppr_ty ctxt_prec (IfaceTyConApp tc tys) = pprTyTcApp ctxt_prec tc tys
-ppr_ty ctxt_prec (IfaceTupleTy i p tys) = pprTuple ctxt_prec i p tys
-ppr_ty _ (IfaceLitTy n) = pprIfaceTyLit n
- -- Function types
-ppr_ty ctxt_prec (IfaceFunTy _ ty1 ty2) -- Should be VisArg
- = -- We don't want to lose synonyms, so we mustn't use splitFunTys here.
- maybeParen ctxt_prec funPrec $
- sep [ppr_ty funPrec ty1, sep (ppr_fun_tail ty2)]
- where
- ppr_fun_tail (IfaceFunTy VisArg ty1 ty2)
- = (arrow <+> ppr_ty funPrec ty1) : ppr_fun_tail ty2
- ppr_fun_tail other_ty
- = [arrow <+> pprIfaceType other_ty]
-
-ppr_ty ctxt_prec (IfaceAppTy t ts)
- = if_print_coercions
- ppr_app_ty
- ppr_app_ty_no_casts
- where
- ppr_app_ty =
- sdocWithDynFlags $ \dflags ->
- pprIfacePrefixApp ctxt_prec
- (ppr_ty funPrec t)
- (map (ppr_app_arg appPrec) (tys_wo_kinds dflags))
-
- tys_wo_kinds dflags = appArgsIfaceTypesArgFlags $ stripInvisArgs dflags ts
-
- -- Strip any casts from the head of the application
- ppr_app_ty_no_casts =
- case t of
- IfaceCastTy head _ -> ppr_ty ctxt_prec (mk_app_tys head ts)
- _ -> ppr_app_ty
-
- mk_app_tys :: IfaceType -> IfaceAppArgs -> IfaceType
- mk_app_tys (IfaceTyConApp tc tys1) tys2 =
- IfaceTyConApp tc (tys1 `mappend` tys2)
- mk_app_tys t1 tys2 = IfaceAppTy t1 tys2
-
-ppr_ty ctxt_prec (IfaceCastTy ty co)
- = if_print_coercions
- (parens (ppr_ty topPrec ty <+> text "|>" <+> ppr co))
- (ppr_ty ctxt_prec ty)
-
-ppr_ty ctxt_prec (IfaceCoercionTy co)
- = if_print_coercions
- (ppr_co ctxt_prec co)
- (text "<>")
-
-{- Note [Defaulting RuntimeRep variables]
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-RuntimeRep variables are considered by many (most?) users to be little
-more than syntactic noise. When the notion was introduced there was a
-significant and understandable push-back from those with pedagogy in
-mind, which argued that RuntimeRep variables would throw a wrench into
-nearly any teach approach since they appear in even the lowly ($)
-function's type,
-
- ($) :: forall (w :: RuntimeRep) a (b :: TYPE w). (a -> b) -> a -> b
-
-which is significantly less readable than its non RuntimeRep-polymorphic type of
-
- ($) :: (a -> b) -> a -> b
-
-Moreover, unboxed types don't appear all that often in run-of-the-mill
-Haskell programs, so it makes little sense to make all users pay this
-syntactic overhead.
-
-For this reason it was decided that we would hide RuntimeRep variables
-for now (see #11549). We do this by defaulting all type variables of
-kind RuntimeRep to LiftedRep. This is done in a pass right before
-pretty-printing (defaultRuntimeRepVars, controlled by
--fprint-explicit-runtime-reps)
-
-This applies to /quantified/ variables like 'w' above. What about
-variables that are /free/ in the type being printed, which certainly
-happens in error messages. Suppose (#16074) we are reporting a
-mismatch between two skolems
- (a :: RuntimeRep) ~ (b :: RuntimeRep)
-We certainly don't want to say "Can't match LiftedRep ~ LiftedRep"!
-
-But if we are printing the type
- (forall (a :: Type r). blah
-we do want to turn that (free) r into LiftedRep, so it prints as
- (forall a. blah)
-
-Conclusion: keep track of whether we we are in the kind of a
-binder; ohly if so, convert free RuntimeRep variables to LiftedRep.
--}
-
--- | Default 'RuntimeRep' variables to 'LiftedPtr'. e.g.
---
--- @
--- ($) :: forall (r :: GHC.Types.RuntimeRep) a (b :: TYPE r).
--- (a -> b) -> a -> b
--- @
---
--- turns in to,
---
--- @ ($) :: forall a (b :: *). (a -> b) -> a -> b @
---
--- We do this to prevent RuntimeRep variables from incurring a significant
--- syntactic overhead in otherwise simple type signatures (e.g. ($)). See
--- Note [Defaulting RuntimeRep variables] and #11549 for further discussion.
---
-defaultRuntimeRepVars :: IfaceType -> IfaceType
-defaultRuntimeRepVars ty = go False emptyFsEnv ty
- where
- go :: Bool -- True <=> Inside the kind of a binder
- -> FastStringEnv () -- Set of enclosing forall-ed RuntimeRep variables
- -> IfaceType -- (replace them with LiftedRep)
- -> IfaceType
- go ink subs (IfaceForAllTy (Bndr (IfaceTvBndr (var, var_kind)) argf) ty)
- | isRuntimeRep var_kind
- , isInvisibleArgFlag argf -- Don't default *visible* quantification
- -- or we get the mess in #13963
- = let subs' = extendFsEnv subs var ()
- -- Record that we should replace it with LiftedRep,
- -- and recurse, discarding the forall
- in go ink subs' ty
-
- go ink subs (IfaceForAllTy bndr ty)
- = IfaceForAllTy (go_ifacebndr subs bndr) (go ink subs ty)
-
- go _ subs ty@(IfaceTyVar tv)
- | tv `elemFsEnv` subs
- = IfaceTyConApp liftedRep IA_Nil
- | otherwise
- = ty
-
- go in_kind _ ty@(IfaceFreeTyVar tv)
- -- See Note [Defaulting RuntimeRep variables], about free vars
- | in_kind && Type.isRuntimeRepTy (tyVarKind tv)
- = IfaceTyConApp liftedRep IA_Nil
- | otherwise
- = ty
-
- go ink subs (IfaceTyConApp tc tc_args)
- = IfaceTyConApp tc (go_args ink subs tc_args)
-
- go ink subs (IfaceTupleTy sort is_prom tc_args)
- = IfaceTupleTy sort is_prom (go_args ink subs tc_args)
-
- go ink subs (IfaceFunTy af arg res)
- = IfaceFunTy af (go ink subs arg) (go ink subs res)
-
- go ink subs (IfaceAppTy t ts)
- = IfaceAppTy (go ink subs t) (go_args ink subs ts)
-
- go ink subs (IfaceCastTy x co)
- = IfaceCastTy (go ink subs x) co
-
- go _ _ ty@(IfaceLitTy {}) = ty
- go _ _ ty@(IfaceCoercionTy {}) = ty
-
- go_ifacebndr :: FastStringEnv () -> IfaceForAllBndr -> IfaceForAllBndr
- go_ifacebndr subs (Bndr (IfaceIdBndr (n, t)) argf)
- = Bndr (IfaceIdBndr (n, go True subs t)) argf
- go_ifacebndr subs (Bndr (IfaceTvBndr (n, t)) argf)
- = Bndr (IfaceTvBndr (n, go True subs t)) argf
-
- go_args :: Bool -> FastStringEnv () -> IfaceAppArgs -> IfaceAppArgs
- go_args _ _ IA_Nil = IA_Nil
- go_args ink subs (IA_Arg ty argf args)
- = IA_Arg (go ink subs ty) argf (go_args ink subs args)
-
- liftedRep :: IfaceTyCon
- liftedRep = IfaceTyCon dc_name (IfaceTyConInfo IsPromoted IfaceNormalTyCon)
- where dc_name = getName liftedRepDataConTyCon
-
- isRuntimeRep :: IfaceType -> Bool
- isRuntimeRep (IfaceTyConApp tc _) =
- tc `ifaceTyConHasKey` runtimeRepTyConKey
- isRuntimeRep _ = False
-
-eliminateRuntimeRep :: (IfaceType -> SDoc) -> IfaceType -> SDoc
-eliminateRuntimeRep f ty
- = sdocWithDynFlags $ \dflags ->
- getPprStyle $ \sty ->
- if userStyle sty && not (gopt Opt_PrintExplicitRuntimeReps dflags)
- then f (defaultRuntimeRepVars ty)
- else f ty
-
-instance Outputable IfaceAppArgs where
- ppr tca = pprIfaceAppArgs tca
-
-pprIfaceAppArgs, pprParendIfaceAppArgs :: IfaceAppArgs -> SDoc
-pprIfaceAppArgs = ppr_app_args topPrec
-pprParendIfaceAppArgs = ppr_app_args appPrec
-
-ppr_app_args :: PprPrec -> IfaceAppArgs -> SDoc
-ppr_app_args ctx_prec = go
- where
- go :: IfaceAppArgs -> SDoc
- go IA_Nil = empty
- go (IA_Arg t argf ts) = ppr_app_arg ctx_prec (t, argf) <+> go ts
-
--- See Note [Pretty-printing invisible arguments]
-ppr_app_arg :: PprPrec -> (IfaceType, ArgFlag) -> SDoc
-ppr_app_arg ctx_prec (t, argf) =
- sdocWithDynFlags $ \dflags ->
- let print_kinds = gopt Opt_PrintExplicitKinds dflags
- in case argf of
- Required -> ppr_ty ctx_prec t
- Specified | print_kinds
- -> char '@' <> ppr_ty appPrec t
- Inferred | print_kinds
- -> char '@' <> braces (ppr_ty topPrec t)
- _ -> empty
-
--------------------
-pprIfaceForAllPart :: [IfaceForAllBndr] -> [IfacePredType] -> SDoc -> SDoc
-pprIfaceForAllPart tvs ctxt sdoc
- = ppr_iface_forall_part ShowForAllWhen tvs ctxt sdoc
-
--- | Like 'pprIfaceForAllPart', but always uses an explicit @forall@.
-pprIfaceForAllPartMust :: [IfaceForAllBndr] -> [IfacePredType] -> SDoc -> SDoc
-pprIfaceForAllPartMust tvs ctxt sdoc
- = ppr_iface_forall_part ShowForAllMust tvs ctxt sdoc
-
-pprIfaceForAllCoPart :: [(IfLclName, IfaceCoercion)] -> SDoc -> SDoc
-pprIfaceForAllCoPart tvs sdoc
- = sep [ pprIfaceForAllCo tvs, sdoc ]
-
-ppr_iface_forall_part :: ShowForAllFlag
- -> [IfaceForAllBndr] -> [IfacePredType] -> SDoc -> SDoc
-ppr_iface_forall_part show_forall tvs ctxt sdoc
- = sep [ case show_forall of
- ShowForAllMust -> pprIfaceForAll tvs
- ShowForAllWhen -> pprUserIfaceForAll tvs
- , pprIfaceContextArr ctxt
- , sdoc]
-
--- | Render the "forall ... ." or "forall ... ->" bit of a type.
-pprIfaceForAll :: [IfaceForAllBndr] -> SDoc
-pprIfaceForAll [] = empty
-pprIfaceForAll bndrs@(Bndr _ vis : _)
- = sep [ add_separator (forAllLit <+> fsep docs)
- , pprIfaceForAll bndrs' ]
- where
- (bndrs', docs) = ppr_itv_bndrs bndrs vis
-
- add_separator stuff = case vis of
- Required -> stuff <+> arrow
- _inv -> stuff <> dot
-
-
--- | Render the ... in @(forall ... .)@ or @(forall ... ->)@.
--- Returns both the list of not-yet-rendered binders and the doc.
--- No anonymous binders here!
-ppr_itv_bndrs :: [IfaceForAllBndr]
- -> ArgFlag -- ^ visibility of the first binder in the list
- -> ([IfaceForAllBndr], [SDoc])
-ppr_itv_bndrs all_bndrs@(bndr@(Bndr _ vis) : bndrs) vis1
- | vis `sameVis` vis1 = let (bndrs', doc) = ppr_itv_bndrs bndrs vis1 in
- (bndrs', pprIfaceForAllBndr bndr : doc)
- | otherwise = (all_bndrs, [])
-ppr_itv_bndrs [] _ = ([], [])
-
-pprIfaceForAllCo :: [(IfLclName, IfaceCoercion)] -> SDoc
-pprIfaceForAllCo [] = empty
-pprIfaceForAllCo tvs = text "forall" <+> pprIfaceForAllCoBndrs tvs <> dot
-
-pprIfaceForAllCoBndrs :: [(IfLclName, IfaceCoercion)] -> SDoc
-pprIfaceForAllCoBndrs bndrs = hsep $ map pprIfaceForAllCoBndr bndrs
-
-pprIfaceForAllBndr :: IfaceForAllBndr -> SDoc
-pprIfaceForAllBndr bndr =
- case bndr of
- Bndr (IfaceTvBndr tv) Inferred ->
- sdocWithDynFlags $ \dflags ->
- if gopt Opt_PrintExplicitForalls dflags
- then braces $ pprIfaceTvBndr tv suppress_sig (UseBndrParens False)
- else pprIfaceTvBndr tv suppress_sig (UseBndrParens True)
- Bndr (IfaceTvBndr tv) _ ->
- pprIfaceTvBndr tv suppress_sig (UseBndrParens True)
- Bndr (IfaceIdBndr idv) _ -> pprIfaceIdBndr idv
- where
- -- See Note [Suppressing binder signatures] in IfaceType
- suppress_sig = SuppressBndrSig False
-
-pprIfaceForAllCoBndr :: (IfLclName, IfaceCoercion) -> SDoc
-pprIfaceForAllCoBndr (tv, kind_co)
- = parens (ppr tv <+> dcolon <+> pprIfaceCoercion kind_co)
-
--- | Show forall flag
---
--- Unconditionally show the forall quantifier with ('ShowForAllMust')
--- or when ('ShowForAllWhen') the names used are free in the binder
--- or when compiling with -fprint-explicit-foralls.
-data ShowForAllFlag = ShowForAllMust | ShowForAllWhen
-
-pprIfaceSigmaType :: ShowForAllFlag -> IfaceType -> SDoc
-pprIfaceSigmaType show_forall ty
- = eliminateRuntimeRep ppr_fn ty
- where
- ppr_fn iface_ty =
- let (tvs, theta, tau) = splitIfaceSigmaTy iface_ty
- in ppr_iface_forall_part show_forall tvs theta (ppr tau)
-
-pprUserIfaceForAll :: [IfaceForAllBndr] -> SDoc
-pprUserIfaceForAll tvs
- = sdocWithDynFlags $ \dflags ->
- -- See Note [When to print foralls] in this module.
- ppWhen (any tv_has_kind_var tvs
- || any tv_is_required tvs
- || gopt Opt_PrintExplicitForalls dflags) $
- pprIfaceForAll tvs
- where
- tv_has_kind_var (Bndr (IfaceTvBndr (_,kind)) _)
- = not (ifTypeIsVarFree kind)
- tv_has_kind_var _ = False
-
- tv_is_required = isVisibleArgFlag . binderArgFlag
-
-{-
-Note [When to print foralls]
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-We opt to explicitly pretty-print `forall`s if any of the following
-criteria are met:
-
-1. -fprint-explicit-foralls is on.
-
-2. A bound type variable has a polymorphic kind. E.g.,
-
- forall k (a::k). Proxy a -> Proxy a
-
- Since a's kind mentions a variable k, we print the foralls.
-
-3. A bound type variable is a visible argument (#14238).
- Suppose we are printing the kind of:
-
- T :: forall k -> k -> Type
-
- The "forall k ->" notation means that this kind argument is required.
- That is, it must be supplied at uses of T. E.g.,
-
- f :: T (Type->Type) Monad -> Int
-
- So we print an explicit "T :: forall k -> k -> Type",
- because omitting it and printing "T :: k -> Type" would be
- utterly misleading.
-
- See Note [VarBndrs, TyCoVarBinders, TyConBinders, and visibility]
- in TyCoRep.
-
-N.B. Until now (Aug 2018) we didn't check anything for coercion variables.
-
-Note [Printing foralls in type family instances]
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-We use the same criteria as in Note [When to print foralls] to determine
-whether a type family instance should be pretty-printed with an explicit
-`forall`. Example:
-
- type family Foo (a :: k) :: k where
- Foo Maybe = []
- Foo (a :: Type) = Int
- Foo a = a
-
-Without -fprint-explicit-foralls enabled, this will be pretty-printed as:
-
-type family Foo (a :: k) :: k where
- Foo Maybe = []
- Foo a = Int
- forall k (a :: k). Foo a = a
-
-Note that only the third equation has an explicit forall, since it has a type
-variable with a non-Type kind. (If -fprint-explicit-foralls were enabled, then
-the second equation would be preceded with `forall a.`.)
-
-There is one tricky point in the implementation: what visibility
-do we give the type variables in a type family instance? Type family instances
-only store type *variables*, not type variable *binders*, and only the latter
-has visibility information. We opt to default the visibility of each of these
-type variables to Specified because users can't ever instantiate these
-variables manually, so the choice of visibility is only relevant to
-pretty-printing. (This is why the `k` in `forall k (a :: k). ...` above is
-printed the way it is, even though it wasn't written explicitly in the
-original source code.)
-
-We adopt the same strategy for data family instances. Example:
-
- data family DF (a :: k)
- data instance DF '[a, b] = DFList
-
-That data family instance is pretty-printed as:
-
- data instance forall j (a :: j) (b :: j). DF '[a, b] = DFList
-
-This is despite that the representation tycon for this data instance (call it
-$DF:List) actually has different visibilities for its binders.
-However, the visibilities of these binders are utterly irrelevant to the
-programmer, who cares only about the specificity of variables in `DF`'s type,
-not $DF:List's type. Therefore, we opt to pretty-print all variables in data
-family instances as Specified.
-
-Note [Printing promoted type constructors]
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-Consider this GHCi session (#14343)
- > _ :: Proxy '[ 'True ]
- error:
- Found hole: _ :: Proxy '['True]
-
-This would be bad, because the '[' looks like a character literal.
-Solution: in type-level lists and tuples, add a leading space
-if the first type is itself promoted. See pprSpaceIfPromotedTyCon.
--}
-
-
--------------------
-
--- | Prefix a space if the given 'IfaceType' is a promoted 'TyCon'.
--- See Note [Printing promoted type constructors]
-pprSpaceIfPromotedTyCon :: IfaceType -> SDoc -> SDoc
-pprSpaceIfPromotedTyCon (IfaceTyConApp tyCon _)
- = case ifaceTyConIsPromoted (ifaceTyConInfo tyCon) of
- IsPromoted -> (space <>)
- _ -> id
-pprSpaceIfPromotedTyCon _
- = id
-
--- See equivalent function in TyCoRep.hs
-pprIfaceTyList :: PprPrec -> IfaceType -> IfaceType -> SDoc
--- Given a type-level list (t1 ': t2), see if we can print
--- it in list notation [t1, ...].
--- Precondition: Opt_PrintExplicitKinds is off
-pprIfaceTyList ctxt_prec ty1 ty2
- = case gather ty2 of
- (arg_tys, Nothing)
- -> char '\'' <> brackets (pprSpaceIfPromotedTyCon ty1 (fsep
- (punctuate comma (map (ppr_ty topPrec) (ty1:arg_tys)))))
- (arg_tys, Just tl)
- -> maybeParen ctxt_prec funPrec $ hang (ppr_ty funPrec ty1)
- 2 (fsep [ colon <+> ppr_ty funPrec ty | ty <- arg_tys ++ [tl]])
- where
- gather :: IfaceType -> ([IfaceType], Maybe IfaceType)
- -- (gather ty) = (tys, Nothing) means ty is a list [t1, .., tn]
- -- = (tys, Just tl) means ty is of form t1:t2:...tn:tl
- gather (IfaceTyConApp tc tys)
- | tc `ifaceTyConHasKey` consDataConKey
- , IA_Arg _ argf (IA_Arg ty1 Required (IA_Arg ty2 Required IA_Nil)) <- tys
- , isInvisibleArgFlag argf
- , (args, tl) <- gather ty2
- = (ty1:args, tl)
- | tc `ifaceTyConHasKey` nilDataConKey
- = ([], Nothing)
- gather ty = ([], Just ty)
-
-pprIfaceTypeApp :: PprPrec -> IfaceTyCon -> IfaceAppArgs -> SDoc
-pprIfaceTypeApp prec tc args = pprTyTcApp prec tc args
-
-pprTyTcApp :: PprPrec -> IfaceTyCon -> IfaceAppArgs -> SDoc
-pprTyTcApp ctxt_prec tc tys =
- sdocWithDynFlags $ \dflags ->
- getPprStyle $ \style ->
- pprTyTcApp' ctxt_prec tc tys dflags style
-
-pprTyTcApp' :: PprPrec -> IfaceTyCon -> IfaceAppArgs
- -> DynFlags -> PprStyle -> SDoc
-pprTyTcApp' ctxt_prec tc tys dflags style
- | ifaceTyConName tc `hasKey` ipClassKey
- , IA_Arg (IfaceLitTy (IfaceStrTyLit n))
- Required (IA_Arg ty Required IA_Nil) <- tys
- = maybeParen ctxt_prec funPrec
- $ char '?' <> ftext n <> text "::" <> ppr_ty topPrec ty
-
- | IfaceTupleTyCon arity sort <- ifaceTyConSort info
- , not (debugStyle style)
- , arity == ifaceVisAppArgsLength tys
- = pprTuple ctxt_prec sort (ifaceTyConIsPromoted info) tys
-
- | IfaceSumTyCon arity <- ifaceTyConSort info
- = pprSum arity (ifaceTyConIsPromoted info) tys
-
- | tc `ifaceTyConHasKey` consDataConKey
- , not (gopt Opt_PrintExplicitKinds dflags)
- , IA_Arg _ argf (IA_Arg ty1 Required (IA_Arg ty2 Required IA_Nil)) <- tys
- , isInvisibleArgFlag argf
- = pprIfaceTyList ctxt_prec ty1 ty2
-
- | tc `ifaceTyConHasKey` tYPETyConKey
- , IA_Arg (IfaceTyConApp rep IA_Nil) Required IA_Nil <- tys
- , rep `ifaceTyConHasKey` liftedRepDataConKey
- = ppr_kind_type ctxt_prec
-
- | otherwise
- = getPprDebug $ \dbg ->
- if | not dbg && tc `ifaceTyConHasKey` errorMessageTypeErrorFamKey
- -- Suppress detail unless you _really_ want to see
- -> text "(TypeError ...)"
-
- | Just doc <- ppr_equality ctxt_prec tc (appArgsIfaceTypes tys)
- -> doc
-
- | otherwise
- -> ppr_iface_tc_app ppr_app_arg ctxt_prec tc tys_wo_kinds
- where
- info = ifaceTyConInfo tc
- tys_wo_kinds = appArgsIfaceTypesArgFlags $ stripInvisArgs dflags tys
-
-ppr_kind_type :: PprPrec -> SDoc
-ppr_kind_type ctxt_prec =
- sdocWithDynFlags $ \dflags ->
- if useStarIsType dflags
- then maybeParen ctxt_prec starPrec $
- unicodeSyntax (char '★') (char '*')
- else text "Type"
-
--- | Pretty-print a type-level equality.
--- Returns (Just doc) if the argument is a /saturated/ application
--- of eqTyCon (~)
--- eqPrimTyCon (~#)
--- eqReprPrimTyCon (~R#)
--- heqTyCon (~~)
---
--- See Note [Equality predicates in IfaceType]
--- and Note [The equality types story] in TysPrim
-ppr_equality :: PprPrec -> IfaceTyCon -> [IfaceType] -> Maybe SDoc
-ppr_equality ctxt_prec tc args
- | hetero_eq_tc
- , [k1, k2, t1, t2] <- args
- = Just $ print_equality (k1, k2, t1, t2)
-
- | hom_eq_tc
- , [k, t1, t2] <- args
- = Just $ print_equality (k, k, t1, t2)
-
- | otherwise
- = Nothing
- where
- homogeneous = tc_name `hasKey` eqTyConKey -- (~)
- || hetero_tc_used_homogeneously
- where
- hetero_tc_used_homogeneously
- = case ifaceTyConSort $ ifaceTyConInfo tc of
- IfaceEqualityTyCon -> True
- _other -> False
- -- True <=> a heterogeneous equality whose arguments
- -- are (in this case) of the same kind
-
- tc_name = ifaceTyConName tc
- pp = ppr_ty
- hom_eq_tc = tc_name `hasKey` eqTyConKey -- (~)
- hetero_eq_tc = tc_name `hasKey` eqPrimTyConKey -- (~#)
- || tc_name `hasKey` eqReprPrimTyConKey -- (~R#)
- || tc_name `hasKey` heqTyConKey -- (~~)
- nominal_eq_tc = tc_name `hasKey` heqTyConKey -- (~~)
- || tc_name `hasKey` eqPrimTyConKey -- (~#)
- print_equality args =
- sdocWithDynFlags $ \dflags ->
- getPprStyle $ \style ->
- print_equality' args style dflags
-
- print_equality' (ki1, ki2, ty1, ty2) style dflags
- | -- If -fprint-equality-relations is on, just print the original TyCon
- print_eqs
- = ppr_infix_eq (ppr tc)
-
- | -- Homogeneous use of heterogeneous equality (ty1 ~~ ty2)
- -- or unlifted equality (ty1 ~# ty2)
- nominal_eq_tc, homogeneous
- = ppr_infix_eq (text "~")
-
- | -- Heterogeneous use of unlifted equality (ty1 ~# ty2)
- not homogeneous
- = ppr_infix_eq (ppr heqTyCon)
-
- | -- Homogeneous use of representational unlifted equality (ty1 ~R# ty2)
- tc_name `hasKey` eqReprPrimTyConKey, homogeneous
- = let ki | print_kinds = [pp appPrec ki1]
- | otherwise = []
- in pprIfacePrefixApp ctxt_prec (ppr coercibleTyCon)
- (ki ++ [pp appPrec ty1, pp appPrec ty2])
-
- -- The other cases work as you'd expect
- | otherwise
- = ppr_infix_eq (ppr tc)
- where
- ppr_infix_eq :: SDoc -> SDoc
- ppr_infix_eq eq_op = pprIfaceInfixApp ctxt_prec eq_op
- (pp_ty_ki ty1 ki1) (pp_ty_ki ty2 ki2)
- where
- pp_ty_ki ty ki
- | print_kinds
- = parens (pp topPrec ty <+> dcolon <+> pp opPrec ki)
- | otherwise
- = pp opPrec ty
-
- print_kinds = gopt Opt_PrintExplicitKinds dflags
- print_eqs = gopt Opt_PrintEqualityRelations dflags ||
- dumpStyle style || debugStyle style
-
-
-pprIfaceCoTcApp :: PprPrec -> IfaceTyCon -> [IfaceCoercion] -> SDoc
-pprIfaceCoTcApp ctxt_prec tc tys =
- ppr_iface_tc_app (\prec (co, _) -> ppr_co prec co) ctxt_prec tc
- (map (, Required) tys)
- -- We are trying to re-use ppr_iface_tc_app here, which requires its
- -- arguments to be accompanied by visibilities. But visibility is
- -- irrelevant when printing coercions, so just default everything to
- -- Required.
-
--- | Pretty-prints an application of a type constructor to some arguments
--- (whose visibilities are known). This is polymorphic (over @a@) since we use
--- this function to pretty-print two different things:
---
--- 1. Types (from `pprTyTcApp'`)
---
--- 2. Coercions (from 'pprIfaceCoTcApp')
-ppr_iface_tc_app :: (PprPrec -> (a, ArgFlag) -> SDoc)
- -> PprPrec -> IfaceTyCon -> [(a, ArgFlag)] -> SDoc
-ppr_iface_tc_app pp _ tc [ty]
- | tc `ifaceTyConHasKey` listTyConKey = pprPromotionQuote tc <> brackets (pp topPrec ty)
-
-ppr_iface_tc_app pp ctxt_prec tc tys
- | tc `ifaceTyConHasKey` liftedTypeKindTyConKey
- = ppr_kind_type ctxt_prec
-
- | not (isSymOcc (nameOccName (ifaceTyConName tc)))
- = pprIfacePrefixApp ctxt_prec (ppr tc) (map (pp appPrec) tys)
-
- | [ ty1@(_, Required)
- , ty2@(_, Required) ] <- tys
- -- Infix, two visible arguments (we know nothing of precedence though).
- -- Don't apply this special case if one of the arguments is invisible,
- -- lest we print something like (@LiftedRep -> @LiftedRep) (#15941).
- = pprIfaceInfixApp ctxt_prec (ppr tc)
- (pp opPrec ty1) (pp opPrec ty2)
-
- | otherwise
- = pprIfacePrefixApp ctxt_prec (parens (ppr tc)) (map (pp appPrec) tys)
-
-pprSum :: Arity -> PromotionFlag -> IfaceAppArgs -> SDoc
-pprSum _arity is_promoted args
- = -- drop the RuntimeRep vars.
- -- See Note [Unboxed tuple RuntimeRep vars] in TyCon
- let tys = appArgsIfaceTypes args
- args' = drop (length tys `div` 2) tys
- in pprPromotionQuoteI is_promoted
- <> sumParens (pprWithBars (ppr_ty topPrec) args')
-
-pprTuple :: PprPrec -> TupleSort -> PromotionFlag -> IfaceAppArgs -> SDoc
-pprTuple ctxt_prec sort promoted args =
- case promoted of
- IsPromoted
- -> let tys = appArgsIfaceTypes args
- args' = drop (length tys `div` 2) tys
- spaceIfPromoted = case args' of
- arg0:_ -> pprSpaceIfPromotedTyCon arg0
- _ -> id
- in ppr_tuple_app args' $
- pprPromotionQuoteI IsPromoted <>
- tupleParens sort (spaceIfPromoted (pprWithCommas pprIfaceType args'))
-
- NotPromoted
- | ConstraintTuple <- sort
- , IA_Nil <- args
- -> maybeParen ctxt_prec sigPrec $
- text "() :: Constraint"
-
- | otherwise
- -> -- drop the RuntimeRep vars.
- -- See Note [Unboxed tuple RuntimeRep vars] in TyCon
- let tys = appArgsIfaceTypes args
- args' = case sort of
- UnboxedTuple -> drop (length tys `div` 2) tys
- _ -> tys
- in
- ppr_tuple_app args' $
- pprPromotionQuoteI promoted <>
- tupleParens sort (pprWithCommas pprIfaceType args')
- where
- ppr_tuple_app :: [IfaceType] -> SDoc -> SDoc
- ppr_tuple_app args_wo_runtime_reps ppr_args_w_parens
- -- Special-case unary boxed tuples so that they are pretty-printed as
- -- `Unit x`, not `(x)`
- | [_] <- args_wo_runtime_reps
- , BoxedTuple <- sort
- = let unit_tc_info = IfaceTyConInfo promoted IfaceNormalTyCon
- unit_tc = IfaceTyCon (tupleTyConName sort 1) unit_tc_info in
- pprPrecIfaceType ctxt_prec $ IfaceTyConApp unit_tc args
- | otherwise
- = ppr_args_w_parens
-
-pprIfaceTyLit :: IfaceTyLit -> SDoc
-pprIfaceTyLit (IfaceNumTyLit n) = integer n
-pprIfaceTyLit (IfaceStrTyLit n) = text (show n)
-
-pprIfaceCoercion, pprParendIfaceCoercion :: IfaceCoercion -> SDoc
-pprIfaceCoercion = ppr_co topPrec
-pprParendIfaceCoercion = ppr_co appPrec
-
-ppr_co :: PprPrec -> IfaceCoercion -> SDoc
-ppr_co _ (IfaceReflCo ty) = angleBrackets (ppr ty) <> ppr_role Nominal
-ppr_co _ (IfaceGReflCo r ty IfaceMRefl)
- = angleBrackets (ppr ty) <> ppr_role r
-ppr_co ctxt_prec (IfaceGReflCo r ty (IfaceMCo co))
- = ppr_special_co ctxt_prec
- (text "GRefl" <+> ppr r <+> pprParendIfaceType ty) [co]
-ppr_co ctxt_prec (IfaceFunCo r co1 co2)
- = maybeParen ctxt_prec funPrec $
- sep (ppr_co funPrec co1 : ppr_fun_tail co2)
- where
- ppr_fun_tail (IfaceFunCo r co1 co2)
- = (arrow <> ppr_role r <+> ppr_co funPrec co1) : ppr_fun_tail co2
- ppr_fun_tail other_co
- = [arrow <> ppr_role r <+> pprIfaceCoercion other_co]
-
-ppr_co _ (IfaceTyConAppCo r tc cos)
- = parens (pprIfaceCoTcApp topPrec tc cos) <> ppr_role r
-ppr_co ctxt_prec (IfaceAppCo co1 co2)
- = maybeParen ctxt_prec appPrec $
- ppr_co funPrec co1 <+> pprParendIfaceCoercion co2
-ppr_co ctxt_prec co@(IfaceForAllCo {})
- = maybeParen ctxt_prec funPrec $
- pprIfaceForAllCoPart tvs (pprIfaceCoercion inner_co)
- where
- (tvs, inner_co) = split_co co
-
- split_co (IfaceForAllCo (IfaceTvBndr (name, _)) kind_co co')
- = let (tvs, co'') = split_co co' in ((name,kind_co):tvs,co'')
- split_co (IfaceForAllCo (IfaceIdBndr (name, _)) kind_co co')
- = let (tvs, co'') = split_co co' in ((name,kind_co):tvs,co'')
- split_co co' = ([], co')
-
--- Why these three? See Note [TcTyVars in IfaceType]
-ppr_co _ (IfaceFreeCoVar covar) = ppr covar
-ppr_co _ (IfaceCoVarCo covar) = ppr covar
-ppr_co _ (IfaceHoleCo covar) = braces (ppr covar)
-
-ppr_co ctxt_prec (IfaceUnivCo IfaceUnsafeCoerceProv r ty1 ty2)
- = maybeParen ctxt_prec appPrec $
- text "UnsafeCo" <+> ppr r <+>
- pprParendIfaceType ty1 <+> pprParendIfaceType ty2
-
-ppr_co _ (IfaceUnivCo prov role ty1 ty2)
- = text "Univ" <> (parens $
- sep [ ppr role <+> pprIfaceUnivCoProv prov
- , dcolon <+> ppr ty1 <> comma <+> ppr ty2 ])
-
-ppr_co ctxt_prec (IfaceInstCo co ty)
- = maybeParen ctxt_prec appPrec $
- text "Inst" <+> pprParendIfaceCoercion co
- <+> pprParendIfaceCoercion ty
-
-ppr_co ctxt_prec (IfaceAxiomRuleCo tc cos)
- = maybeParen ctxt_prec appPrec $ ppr tc <+> parens (interpp'SP cos)
-
-ppr_co ctxt_prec (IfaceAxiomInstCo n i cos)
- = ppr_special_co ctxt_prec (ppr n <> brackets (ppr i)) cos
-ppr_co ctxt_prec (IfaceSymCo co)
- = ppr_special_co ctxt_prec (text "Sym") [co]
-ppr_co ctxt_prec (IfaceTransCo co1 co2)
- = maybeParen ctxt_prec opPrec $
- ppr_co opPrec co1 <+> semi <+> ppr_co opPrec co2
-ppr_co ctxt_prec (IfaceNthCo d co)
- = ppr_special_co ctxt_prec (text "Nth:" <> int d) [co]
-ppr_co ctxt_prec (IfaceLRCo lr co)
- = ppr_special_co ctxt_prec (ppr lr) [co]
-ppr_co ctxt_prec (IfaceSubCo co)
- = ppr_special_co ctxt_prec (text "Sub") [co]
-ppr_co ctxt_prec (IfaceKindCo co)
- = ppr_special_co ctxt_prec (text "Kind") [co]
-
-ppr_special_co :: PprPrec -> SDoc -> [IfaceCoercion] -> SDoc
-ppr_special_co ctxt_prec doc cos
- = maybeParen ctxt_prec appPrec
- (sep [doc, nest 4 (sep (map pprParendIfaceCoercion cos))])
-
-ppr_role :: Role -> SDoc
-ppr_role r = underscore <> pp_role
- where pp_role = case r of
- Nominal -> char 'N'
- Representational -> char 'R'
- Phantom -> char 'P'
-
-------------------
-pprIfaceUnivCoProv :: IfaceUnivCoProv -> SDoc
-pprIfaceUnivCoProv IfaceUnsafeCoerceProv
- = text "unsafe"
-pprIfaceUnivCoProv (IfacePhantomProv co)
- = text "phantom" <+> pprParendIfaceCoercion co
-pprIfaceUnivCoProv (IfaceProofIrrelProv co)
- = text "irrel" <+> pprParendIfaceCoercion co
-pprIfaceUnivCoProv (IfacePluginProv s)
- = text "plugin" <+> doubleQuotes (text s)
-
--------------------
-instance Outputable IfaceTyCon where
- ppr tc = pprPromotionQuote tc <> ppr (ifaceTyConName tc)
-
-pprPromotionQuote :: IfaceTyCon -> SDoc
-pprPromotionQuote tc =
- pprPromotionQuoteI $ ifaceTyConIsPromoted $ ifaceTyConInfo tc
-
-pprPromotionQuoteI :: PromotionFlag -> SDoc
-pprPromotionQuoteI NotPromoted = empty
-pprPromotionQuoteI IsPromoted = char '\''
-
-instance Outputable IfaceCoercion where
- ppr = pprIfaceCoercion
-
-instance Binary IfaceTyCon where
- put_ bh (IfaceTyCon n i) = put_ bh n >> put_ bh i
-
- get bh = do n <- get bh
- i <- get bh
- return (IfaceTyCon n i)
-
-instance Binary IfaceTyConSort where
- put_ bh IfaceNormalTyCon = putByte bh 0
- put_ bh (IfaceTupleTyCon arity sort) = putByte bh 1 >> put_ bh arity >> put_ bh sort
- put_ bh (IfaceSumTyCon arity) = putByte bh 2 >> put_ bh arity
- put_ bh IfaceEqualityTyCon = putByte bh 3
-
- get bh = do
- n <- getByte bh
- case n of
- 0 -> return IfaceNormalTyCon
- 1 -> IfaceTupleTyCon <$> get bh <*> get bh
- 2 -> IfaceSumTyCon <$> get bh
- _ -> return IfaceEqualityTyCon
-
-instance Binary IfaceTyConInfo where
- put_ bh (IfaceTyConInfo i s) = put_ bh i >> put_ bh s
-
- get bh = IfaceTyConInfo <$> get bh <*> get bh
-
-instance Outputable IfaceTyLit where
- ppr = pprIfaceTyLit
-
-instance Binary IfaceTyLit where
- put_ bh (IfaceNumTyLit n) = putByte bh 1 >> put_ bh n
- put_ bh (IfaceStrTyLit n) = putByte bh 2 >> put_ bh n
-
- get bh =
- do tag <- getByte bh
- case tag of
- 1 -> do { n <- get bh
- ; return (IfaceNumTyLit n) }
- 2 -> do { n <- get bh
- ; return (IfaceStrTyLit n) }
- _ -> panic ("get IfaceTyLit " ++ show tag)
-
-instance Binary IfaceAppArgs where
- put_ bh tk =
- case tk of
- IA_Arg t a ts -> putByte bh 0 >> put_ bh t >> put_ bh a >> put_ bh ts
- IA_Nil -> putByte bh 1
-
- get bh =
- do c <- getByte bh
- case c of
- 0 -> do
- t <- get bh
- a <- get bh
- ts <- get bh
- return $! IA_Arg t a ts
- 1 -> return IA_Nil
- _ -> panic ("get IfaceAppArgs " ++ show c)
-
--------------------
-
--- Some notes about printing contexts
---
--- In the event that we are printing a singleton context (e.g. @Eq a@) we can
--- omit parentheses. However, we must take care to set the precedence correctly
--- to opPrec, since something like @a :~: b@ must be parenthesized (see
--- #9658).
---
--- When printing a larger context we use 'fsep' instead of 'sep' so that
--- the context doesn't get displayed as a giant column. Rather than,
--- instance (Eq a,
--- Eq b,
--- Eq c,
--- Eq d,
--- Eq e,
--- Eq f,
--- Eq g,
--- Eq h,
--- Eq i,
--- Eq j,
--- Eq k,
--- Eq l) =>
--- Eq (a, b, c, d, e, f, g, h, i, j, k, l)
---
--- we want
---
--- instance (Eq a, Eq b, Eq c, Eq d, Eq e, Eq f, Eq g, Eq h, Eq i,
--- Eq j, Eq k, Eq l) =>
--- Eq (a, b, c, d, e, f, g, h, i, j, k, l)
-
-
-
--- | Prints "(C a, D b) =>", including the arrow.
--- Used when we want to print a context in a type, so we
--- use 'funPrec' to decide whether to parenthesise a singleton
--- predicate; e.g. Num a => a -> a
-pprIfaceContextArr :: [IfacePredType] -> SDoc
-pprIfaceContextArr [] = empty
-pprIfaceContextArr [pred] = ppr_ty funPrec pred <+> darrow
-pprIfaceContextArr preds = ppr_parend_preds preds <+> darrow
-
--- | Prints a context or @()@ if empty
--- You give it the context precedence
-pprIfaceContext :: PprPrec -> [IfacePredType] -> SDoc
-pprIfaceContext _ [] = text "()"
-pprIfaceContext prec [pred] = ppr_ty prec pred
-pprIfaceContext _ preds = ppr_parend_preds preds
-
-ppr_parend_preds :: [IfacePredType] -> SDoc
-ppr_parend_preds preds = parens (fsep (punctuate comma (map ppr preds)))
-
-instance Binary IfaceType where
- put_ _ (IfaceFreeTyVar tv)
- = pprPanic "Can't serialise IfaceFreeTyVar" (ppr tv)
-
- put_ bh (IfaceForAllTy aa ab) = do
- putByte bh 0
- put_ bh aa
- put_ bh ab
- put_ bh (IfaceTyVar ad) = do
- putByte bh 1
- put_ bh ad
- put_ bh (IfaceAppTy ae af) = do
- putByte bh 2
- put_ bh ae
- put_ bh af
- put_ bh (IfaceFunTy af ag ah) = do
- putByte bh 3
- put_ bh af
- put_ bh ag
- put_ bh ah
- put_ bh (IfaceTyConApp tc tys)
- = do { putByte bh 5; put_ bh tc; put_ bh tys }
- put_ bh (IfaceCastTy a b)
- = do { putByte bh 6; put_ bh a; put_ bh b }
- put_ bh (IfaceCoercionTy a)
- = do { putByte bh 7; put_ bh a }
- put_ bh (IfaceTupleTy s i tys)
- = do { putByte bh 8; put_ bh s; put_ bh i; put_ bh tys }
- put_ bh (IfaceLitTy n)
- = do { putByte bh 9; put_ bh n }
-
- get bh = do
- h <- getByte bh
- case h of
- 0 -> do aa <- get bh
- ab <- get bh
- return (IfaceForAllTy aa ab)
- 1 -> do ad <- get bh
- return (IfaceTyVar ad)
- 2 -> do ae <- get bh
- af <- get bh
- return (IfaceAppTy ae af)
- 3 -> do af <- get bh
- ag <- get bh
- ah <- get bh
- return (IfaceFunTy af ag ah)
- 5 -> do { tc <- get bh; tys <- get bh
- ; return (IfaceTyConApp tc tys) }
- 6 -> do { a <- get bh; b <- get bh
- ; return (IfaceCastTy a b) }
- 7 -> do { a <- get bh
- ; return (IfaceCoercionTy a) }
-
- 8 -> do { s <- get bh; i <- get bh; tys <- get bh
- ; return (IfaceTupleTy s i tys) }
- _ -> do n <- get bh
- return (IfaceLitTy n)
-
-instance Binary IfaceMCoercion where
- put_ bh IfaceMRefl = do
- putByte bh 1
- put_ bh (IfaceMCo co) = do
- putByte bh 2
- put_ bh co
-
- get bh = do
- tag <- getByte bh
- case tag of
- 1 -> return IfaceMRefl
- 2 -> do a <- get bh
- return $ IfaceMCo a
- _ -> panic ("get IfaceMCoercion " ++ show tag)
-
-instance Binary IfaceCoercion where
- put_ bh (IfaceReflCo a) = do
- putByte bh 1
- put_ bh a
- put_ bh (IfaceGReflCo a b c) = do
- putByte bh 2
- put_ bh a
- put_ bh b
- put_ bh c
- put_ bh (IfaceFunCo a b c) = do
- putByte bh 3
- put_ bh a
- put_ bh b
- put_ bh c
- put_ bh (IfaceTyConAppCo a b c) = do
- putByte bh 4
- put_ bh a
- put_ bh b
- put_ bh c
- put_ bh (IfaceAppCo a b) = do
- putByte bh 5
- put_ bh a
- put_ bh b
- put_ bh (IfaceForAllCo a b c) = do
- putByte bh 6
- put_ bh a
- put_ bh b
- put_ bh c
- put_ bh (IfaceCoVarCo a) = do
- putByte bh 7
- put_ bh a
- put_ bh (IfaceAxiomInstCo a b c) = do
- putByte bh 8
- put_ bh a
- put_ bh b
- put_ bh c
- put_ bh (IfaceUnivCo a b c d) = do
- putByte bh 9
- put_ bh a
- put_ bh b
- put_ bh c
- put_ bh d
- put_ bh (IfaceSymCo a) = do
- putByte bh 10
- put_ bh a
- put_ bh (IfaceTransCo a b) = do
- putByte bh 11
- put_ bh a
- put_ bh b
- put_ bh (IfaceNthCo a b) = do
- putByte bh 12
- put_ bh a
- put_ bh b
- put_ bh (IfaceLRCo a b) = do
- putByte bh 13
- put_ bh a
- put_ bh b
- put_ bh (IfaceInstCo a b) = do
- putByte bh 14
- put_ bh a
- put_ bh b
- put_ bh (IfaceKindCo a) = do
- putByte bh 15
- put_ bh a
- put_ bh (IfaceSubCo a) = do
- putByte bh 16
- put_ bh a
- put_ bh (IfaceAxiomRuleCo a b) = do
- putByte bh 17
- put_ bh a
- put_ bh b
- put_ _ (IfaceFreeCoVar cv)
- = pprPanic "Can't serialise IfaceFreeCoVar" (ppr cv)
- put_ _ (IfaceHoleCo cv)
- = pprPanic "Can't serialise IfaceHoleCo" (ppr cv)
- -- See Note [Holes in IfaceCoercion]
-
- get bh = do
- tag <- getByte bh
- case tag of
- 1 -> do a <- get bh
- return $ IfaceReflCo a
- 2 -> do a <- get bh
- b <- get bh
- c <- get bh
- return $ IfaceGReflCo a b c
- 3 -> do a <- get bh
- b <- get bh
- c <- get bh
- return $ IfaceFunCo a b c
- 4 -> do a <- get bh
- b <- get bh
- c <- get bh
- return $ IfaceTyConAppCo a b c
- 5 -> do a <- get bh
- b <- get bh
- return $ IfaceAppCo a b
- 6 -> do a <- get bh
- b <- get bh
- c <- get bh
- return $ IfaceForAllCo a b c
- 7 -> do a <- get bh
- return $ IfaceCoVarCo a
- 8 -> do a <- get bh
- b <- get bh
- c <- get bh
- return $ IfaceAxiomInstCo a b c
- 9 -> do a <- get bh
- b <- get bh
- c <- get bh
- d <- get bh
- return $ IfaceUnivCo a b c d
- 10-> do a <- get bh
- return $ IfaceSymCo a
- 11-> do a <- get bh
- b <- get bh
- return $ IfaceTransCo a b
- 12-> do a <- get bh
- b <- get bh
- return $ IfaceNthCo a b
- 13-> do a <- get bh
- b <- get bh
- return $ IfaceLRCo a b
- 14-> do a <- get bh
- b <- get bh
- return $ IfaceInstCo a b
- 15-> do a <- get bh
- return $ IfaceKindCo a
- 16-> do a <- get bh
- return $ IfaceSubCo a
- 17-> do a <- get bh
- b <- get bh
- return $ IfaceAxiomRuleCo a b
- _ -> panic ("get IfaceCoercion " ++ show tag)
-
-instance Binary IfaceUnivCoProv where
- put_ bh IfaceUnsafeCoerceProv = putByte bh 1
- put_ bh (IfacePhantomProv a) = do
- putByte bh 2
- put_ bh a
- put_ bh (IfaceProofIrrelProv a) = do
- putByte bh 3
- put_ bh a
- put_ bh (IfacePluginProv a) = do
- putByte bh 4
- put_ bh a
-
- get bh = do
- tag <- getByte bh
- case tag of
- 1 -> return $ IfaceUnsafeCoerceProv
- 2 -> do a <- get bh
- return $ IfacePhantomProv a
- 3 -> do a <- get bh
- return $ IfaceProofIrrelProv a
- 4 -> do a <- get bh
- return $ IfacePluginProv a
- _ -> panic ("get IfaceUnivCoProv " ++ show tag)
-
-
-instance Binary (DefMethSpec IfaceType) where
- put_ bh VanillaDM = putByte bh 0
- put_ bh (GenericDM t) = putByte bh 1 >> put_ bh t
- get bh = do
- h <- getByte bh
- case h of
- 0 -> return VanillaDM
- _ -> do { t <- get bh; return (GenericDM t) }
-
-instance NFData IfaceType where
- rnf = \case
- IfaceFreeTyVar f1 -> f1 `seq` ()
- IfaceTyVar f1 -> rnf f1
- IfaceLitTy f1 -> rnf f1
- IfaceAppTy f1 f2 -> rnf f1 `seq` rnf f2
- IfaceFunTy f1 f2 f3 -> f1 `seq` rnf f2 `seq` rnf f3
- IfaceForAllTy f1 f2 -> f1 `seq` rnf f2
- IfaceTyConApp f1 f2 -> rnf f1 `seq` rnf f2
- IfaceCastTy f1 f2 -> rnf f1 `seq` rnf f2
- IfaceCoercionTy f1 -> rnf f1
- IfaceTupleTy f1 f2 f3 -> f1 `seq` f2 `seq` rnf f3
-
-instance NFData IfaceTyLit where
- rnf = \case
- IfaceNumTyLit f1 -> rnf f1
- IfaceStrTyLit f1 -> rnf f1
-
-instance NFData IfaceCoercion where
- rnf = \case
- IfaceReflCo f1 -> rnf f1
- IfaceGReflCo f1 f2 f3 -> f1 `seq` rnf f2 `seq` rnf f3
- IfaceFunCo f1 f2 f3 -> f1 `seq` rnf f2 `seq` rnf f3
- IfaceTyConAppCo f1 f2 f3 -> f1 `seq` rnf f2 `seq` rnf f3
- IfaceAppCo f1 f2 -> rnf f1 `seq` rnf f2
- IfaceForAllCo f1 f2 f3 -> rnf f1 `seq` rnf f2 `seq` rnf f3
- IfaceCoVarCo f1 -> rnf f1
- IfaceAxiomInstCo f1 f2 f3 -> rnf f1 `seq` rnf f2 `seq` rnf f3
- IfaceAxiomRuleCo f1 f2 -> rnf f1 `seq` rnf f2
- IfaceUnivCo f1 f2 f3 f4 -> rnf f1 `seq` f2 `seq` rnf f3 `seq` rnf f4
- IfaceSymCo f1 -> rnf f1
- IfaceTransCo f1 f2 -> rnf f1 `seq` rnf f2
- IfaceNthCo f1 f2 -> rnf f1 `seq` rnf f2
- IfaceLRCo f1 f2 -> f1 `seq` rnf f2
- IfaceInstCo f1 f2 -> rnf f1 `seq` rnf f2
- IfaceKindCo f1 -> rnf f1
- IfaceSubCo f1 -> rnf f1
- IfaceFreeCoVar f1 -> f1 `seq` ()
- IfaceHoleCo f1 -> f1 `seq` ()
-
-instance NFData IfaceUnivCoProv where
- rnf x = seq x ()
-
-instance NFData IfaceMCoercion where
- rnf x = seq x ()
-
-instance NFData IfaceOneShot where
- rnf x = seq x ()
-
-instance NFData IfaceTyConSort where
- rnf = \case
- IfaceNormalTyCon -> ()
- IfaceTupleTyCon arity sort -> rnf arity `seq` sort `seq` ()
- IfaceSumTyCon arity -> rnf arity
- IfaceEqualityTyCon -> ()
-
-instance NFData IfaceTyConInfo where
- rnf (IfaceTyConInfo f s) = f `seq` rnf s
-
-instance NFData IfaceTyCon where
- rnf (IfaceTyCon nm info) = rnf nm `seq` rnf info
-
-instance NFData IfaceBndr where
- rnf = \case
- IfaceIdBndr id_bndr -> rnf id_bndr
- IfaceTvBndr tv_bndr -> rnf tv_bndr
-
-instance NFData IfaceAppArgs where
- rnf = \case
- IA_Nil -> ()
- IA_Arg f1 f2 f3 -> rnf f1 `seq` f2 `seq` rnf f3
diff --git a/compiler/iface/IfaceType.hs-boot b/compiler/iface/IfaceType.hs-boot
deleted file mode 100644
index 44f1f3cfc2..0000000000
--- a/compiler/iface/IfaceType.hs-boot
+++ /dev/null
@@ -1,15 +0,0 @@
--- Used only by ToIface.hs-boot
-
-module IfaceType( IfaceType, IfaceTyCon, IfaceForAllBndr
- , IfaceCoercion, IfaceTyLit, IfaceAppArgs ) where
-
-import Var (VarBndr, ArgFlag)
-
-data IfaceAppArgs
-
-data IfaceType
-data IfaceTyCon
-data IfaceTyLit
-data IfaceCoercion
-data IfaceBndr
-type IfaceForAllBndr = VarBndr IfaceBndr ArgFlag
diff --git a/compiler/iface/LoadIface.hs b/compiler/iface/LoadIface.hs
deleted file mode 100644
index 176b6cd0d0..0000000000
--- a/compiler/iface/LoadIface.hs
+++ /dev/null
@@ -1,1289 +0,0 @@
-{-
-(c) The University of Glasgow 2006
-(c) The GRASP/AQUA Project, Glasgow University, 1992-1998
-
-
-Loading interface files
--}
-
-{-# LANGUAGE CPP, BangPatterns, RecordWildCards, NondecreasingIndentation #-}
-{-# LANGUAGE TypeFamilies #-}
-{-# OPTIONS_GHC -fno-warn-orphans #-}
-module LoadIface (
- -- Importing one thing
- tcLookupImported_maybe, importDecl,
- checkWiredInTyCon, ifCheckWiredInThing,
-
- -- RnM/TcM functions
- loadModuleInterface, loadModuleInterfaces,
- loadSrcInterface, loadSrcInterface_maybe,
- loadInterfaceForName, loadInterfaceForNameMaybe, loadInterfaceForModule,
-
- -- IfM functions
- loadInterface,
- loadSysInterface, loadUserInterface, loadPluginInterface,
- findAndReadIface, readIface, -- Used when reading the module's old interface
- loadDecls, -- Should move to TcIface and be renamed
- initExternalPackageState,
- moduleFreeHolesPrecise,
- needWiredInHomeIface, loadWiredInHomeIface,
-
- pprModIfaceSimple,
- ifaceStats, pprModIface, showIface
- ) where
-
-#include "HsVersions.h"
-
-import GhcPrelude
-
-import {-# SOURCE #-} TcIface( tcIfaceDecl, tcIfaceRules, tcIfaceInst,
- tcIfaceFamInst,
- tcIfaceAnnotations, tcIfaceCompleteSigs )
-
-import DynFlags
-import IfaceSyn
-import IfaceEnv
-import HscTypes
-
-import BasicTypes hiding (SuccessFlag(..))
-import TcRnMonad
-
-import Constants
-import PrelNames
-import PrelInfo
-import PrimOp ( allThePrimOps, primOpFixity, primOpOcc )
-import MkId ( seqId )
-import TysPrim ( funTyConName )
-import Rules
-import TyCon
-import Annotations
-import InstEnv
-import FamInstEnv
-import Name
-import NameEnv
-import Avail
-import Module
-import Maybes
-import ErrUtils
-import Finder
-import UniqFM
-import SrcLoc
-import Outputable
-import BinIface
-import Panic
-import Util
-import FastString
-import Fingerprint
-import Hooks
-import FieldLabel
-import RnModIface
-import UniqDSet
-import Plugins
-
-import Control.Monad
-import Control.Exception
-import Data.IORef
-import System.FilePath
-
-{-
-************************************************************************
-* *
-* tcImportDecl is the key function for "faulting in" *
-* imported things
-* *
-************************************************************************
-
-The main idea is this. We are chugging along type-checking source code, and
-find a reference to GHC.Base.map. We call tcLookupGlobal, which doesn't find
-it in the EPS type envt. So it
- 1 loads GHC.Base.hi
- 2 gets the decl for GHC.Base.map
- 3 typechecks it via tcIfaceDecl
- 4 and adds it to the type env in the EPS
-
-Note that DURING STEP 4, we may find that map's type mentions a type
-constructor that also
-
-Notice that for imported things we read the current version from the EPS
-mutable variable. This is important in situations like
- ...$(e1)...$(e2)...
-where the code that e1 expands to might import some defns that
-also turn out to be needed by the code that e2 expands to.
--}
-
-tcLookupImported_maybe :: Name -> TcM (MaybeErr MsgDoc TyThing)
--- Returns (Failed err) if we can't find the interface file for the thing
-tcLookupImported_maybe name
- = do { hsc_env <- getTopEnv
- ; mb_thing <- liftIO (lookupTypeHscEnv hsc_env name)
- ; case mb_thing of
- Just thing -> return (Succeeded thing)
- Nothing -> tcImportDecl_maybe name }
-
-tcImportDecl_maybe :: Name -> TcM (MaybeErr MsgDoc TyThing)
--- Entry point for *source-code* uses of importDecl
-tcImportDecl_maybe name
- | Just thing <- wiredInNameTyThing_maybe name
- = do { when (needWiredInHomeIface thing)
- (initIfaceTcRn (loadWiredInHomeIface name))
- -- See Note [Loading instances for wired-in things]
- ; return (Succeeded thing) }
- | otherwise
- = initIfaceTcRn (importDecl name)
-
-importDecl :: Name -> IfM lcl (MaybeErr MsgDoc TyThing)
--- Get the TyThing for this Name from an interface file
--- It's not a wired-in thing -- the caller caught that
-importDecl name
- = ASSERT( not (isWiredInName name) )
- do { traceIf nd_doc
-
- -- Load the interface, which should populate the PTE
- ; mb_iface <- ASSERT2( isExternalName name, ppr name )
- loadInterface nd_doc (nameModule name) ImportBySystem
- ; case mb_iface of {
- Failed err_msg -> return (Failed err_msg) ;
- Succeeded _ -> do
-
- -- Now look it up again; this time we should find it
- { eps <- getEps
- ; case lookupTypeEnv (eps_PTE eps) name of
- Just thing -> return $ Succeeded thing
- Nothing -> let doc = whenPprDebug (found_things_msg eps $$ empty)
- $$ not_found_msg
- in return $ Failed doc
- }}}
- where
- nd_doc = text "Need decl for" <+> ppr name
- not_found_msg = hang (text "Can't find interface-file declaration for" <+>
- pprNameSpace (nameNameSpace name) <+> ppr name)
- 2 (vcat [text "Probable cause: bug in .hi-boot file, or inconsistent .hi file",
- text "Use -ddump-if-trace to get an idea of which file caused the error"])
- found_things_msg eps =
- hang (text "Found the following declarations in" <+> ppr (nameModule name) <> colon)
- 2 (vcat (map ppr $ filter is_interesting $ nameEnvElts $ eps_PTE eps))
- where
- is_interesting thing = nameModule name == nameModule (getName thing)
-
-
-{-
-************************************************************************
-* *
- Checks for wired-in things
-* *
-************************************************************************
-
-Note [Loading instances for wired-in things]
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-We need to make sure that we have at least *read* the interface files
-for any module with an instance decl or RULE that we might want.
-
-* If the instance decl is an orphan, we have a whole separate mechanism
- (loadOrphanModules)
-
-* If the instance decl is not an orphan, then the act of looking at the
- TyCon or Class will force in the defining module for the
- TyCon/Class, and hence the instance decl
-
-* BUT, if the TyCon is a wired-in TyCon, we don't really need its interface;
- but we must make sure we read its interface in case it has instances or
- rules. That is what LoadIface.loadWiredInHomeIface does. It's called
- from TcIface.{tcImportDecl, checkWiredInTyCon, ifCheckWiredInThing}
-
-* HOWEVER, only do this for TyCons. There are no wired-in Classes. There
- are some wired-in Ids, but we don't want to load their interfaces. For
- example, Control.Exception.Base.recSelError is wired in, but that module
- is compiled late in the base library, and we don't want to force it to
- load before it's been compiled!
-
-All of this is done by the type checker. The renamer plays no role.
-(It used to, but no longer.)
--}
-
-checkWiredInTyCon :: TyCon -> TcM ()
--- Ensure that the home module of the TyCon (and hence its instances)
--- are loaded. See Note [Loading instances for wired-in things]
--- It might not be a wired-in tycon (see the calls in TcUnify),
--- in which case this is a no-op.
-checkWiredInTyCon tc
- | not (isWiredInName tc_name)
- = return ()
- | otherwise
- = do { mod <- getModule
- ; traceIf (text "checkWiredInTyCon" <+> ppr tc_name $$ ppr mod)
- ; ASSERT( isExternalName tc_name )
- when (mod /= nameModule tc_name)
- (initIfaceTcRn (loadWiredInHomeIface tc_name))
- -- Don't look for (non-existent) Float.hi when
- -- compiling Float.hs, which mentions Float of course
- -- A bit yukky to call initIfaceTcRn here
- }
- where
- tc_name = tyConName tc
-
-ifCheckWiredInThing :: TyThing -> IfL ()
--- Even though we are in an interface file, we want to make
--- sure the instances of a wired-in thing are loaded (imagine f :: Double -> Double)
--- Ditto want to ensure that RULES are loaded too
--- See Note [Loading instances for wired-in things]
-ifCheckWiredInThing thing
- = do { mod <- getIfModule
- -- Check whether we are typechecking the interface for this
- -- very module. E.g when compiling the base library in --make mode
- -- we may typecheck GHC.Base.hi. At that point, GHC.Base is not in
- -- the HPT, so without the test we'll demand-load it into the PIT!
- -- C.f. the same test in checkWiredInTyCon above
- ; let name = getName thing
- ; ASSERT2( isExternalName name, ppr name )
- when (needWiredInHomeIface thing && mod /= nameModule name)
- (loadWiredInHomeIface name) }
-
-needWiredInHomeIface :: TyThing -> Bool
--- Only for TyCons; see Note [Loading instances for wired-in things]
-needWiredInHomeIface (ATyCon {}) = True
-needWiredInHomeIface _ = False
-
-
-{-
-************************************************************************
-* *
- loadSrcInterface, loadOrphanModules, loadInterfaceForName
-
- These three are called from TcM-land
-* *
-************************************************************************
--}
-
--- | Load the interface corresponding to an @import@ directive in
--- source code. On a failure, fail in the monad with an error message.
-loadSrcInterface :: SDoc
- -> ModuleName
- -> IsBootInterface -- {-# SOURCE #-} ?
- -> Maybe FastString -- "package", if any
- -> RnM ModIface
-
-loadSrcInterface doc mod want_boot maybe_pkg
- = do { res <- loadSrcInterface_maybe doc mod want_boot maybe_pkg
- ; case res of
- Failed err -> failWithTc err
- Succeeded iface -> return iface }
-
--- | Like 'loadSrcInterface', but returns a 'MaybeErr'.
-loadSrcInterface_maybe :: SDoc
- -> ModuleName
- -> IsBootInterface -- {-# SOURCE #-} ?
- -> Maybe FastString -- "package", if any
- -> RnM (MaybeErr MsgDoc ModIface)
-
-loadSrcInterface_maybe doc mod want_boot maybe_pkg
- -- We must first find which Module this import refers to. This involves
- -- calling the Finder, which as a side effect will search the filesystem
- -- and create a ModLocation. If successful, loadIface will read the
- -- interface; it will call the Finder again, but the ModLocation will be
- -- cached from the first search.
- = do { hsc_env <- getTopEnv
- ; res <- liftIO $ findImportedModule hsc_env mod maybe_pkg
- ; case res of
- Found _ mod -> initIfaceTcRn $ loadInterface doc mod (ImportByUser want_boot)
- -- TODO: Make sure this error message is good
- err -> return (Failed (cannotFindModule (hsc_dflags hsc_env) mod err)) }
-
--- | Load interface directly for a fully qualified 'Module'. (This is a fairly
--- rare operation, but in particular it is used to load orphan modules
--- in order to pull their instances into the global package table and to
--- handle some operations in GHCi).
-loadModuleInterface :: SDoc -> Module -> TcM ModIface
-loadModuleInterface doc mod = initIfaceTcRn (loadSysInterface doc mod)
-
--- | Load interfaces for a collection of modules.
-loadModuleInterfaces :: SDoc -> [Module] -> TcM ()
-loadModuleInterfaces doc mods
- | null mods = return ()
- | otherwise = initIfaceTcRn (mapM_ load mods)
- where
- load mod = loadSysInterface (doc <+> parens (ppr mod)) mod
-
--- | Loads the interface for a given Name.
--- Should only be called for an imported name;
--- otherwise loadSysInterface may not find the interface
-loadInterfaceForName :: SDoc -> Name -> TcRn ModIface
-loadInterfaceForName doc name
- = do { when debugIsOn $ -- Check pre-condition
- do { this_mod <- getModule
- ; MASSERT2( not (nameIsLocalOrFrom this_mod name), ppr name <+> parens doc ) }
- ; ASSERT2( isExternalName name, ppr name )
- initIfaceTcRn $ loadSysInterface doc (nameModule name) }
-
--- | Only loads the interface for external non-local names.
-loadInterfaceForNameMaybe :: SDoc -> Name -> TcRn (Maybe ModIface)
-loadInterfaceForNameMaybe doc name
- = do { this_mod <- getModule
- ; if nameIsLocalOrFrom this_mod name || not (isExternalName name)
- then return Nothing
- else Just <$> (initIfaceTcRn $ loadSysInterface doc (nameModule name))
- }
-
--- | Loads the interface for a given Module.
-loadInterfaceForModule :: SDoc -> Module -> TcRn ModIface
-loadInterfaceForModule doc m
- = do
- -- Should not be called with this module
- when debugIsOn $ do
- this_mod <- getModule
- MASSERT2( this_mod /= m, ppr m <+> parens doc )
- initIfaceTcRn $ loadSysInterface doc m
-
-{-
-*********************************************************
-* *
- loadInterface
-
- The main function to load an interface
- for an imported module, and put it in
- the External Package State
-* *
-*********************************************************
--}
-
--- | An 'IfM' function to load the home interface for a wired-in thing,
--- so that we're sure that we see its instance declarations and rules
--- See Note [Loading instances for wired-in things]
-loadWiredInHomeIface :: Name -> IfM lcl ()
-loadWiredInHomeIface name
- = ASSERT( isWiredInName name )
- do _ <- loadSysInterface doc (nameModule name); return ()
- where
- doc = text "Need home interface for wired-in thing" <+> ppr name
-
-------------------
--- | Loads a system interface and throws an exception if it fails
-loadSysInterface :: SDoc -> Module -> IfM lcl ModIface
-loadSysInterface doc mod_name = loadInterfaceWithException doc mod_name ImportBySystem
-
-------------------
--- | Loads a user interface and throws an exception if it fails. The first parameter indicates
--- whether we should import the boot variant of the module
-loadUserInterface :: Bool -> SDoc -> Module -> IfM lcl ModIface
-loadUserInterface is_boot doc mod_name
- = loadInterfaceWithException doc mod_name (ImportByUser is_boot)
-
-loadPluginInterface :: SDoc -> Module -> IfM lcl ModIface
-loadPluginInterface doc mod_name
- = loadInterfaceWithException doc mod_name ImportByPlugin
-
-------------------
--- | A wrapper for 'loadInterface' that throws an exception if it fails
-loadInterfaceWithException :: SDoc -> Module -> WhereFrom -> IfM lcl ModIface
-loadInterfaceWithException doc mod_name where_from
- = withException (loadInterface doc mod_name where_from)
-
-------------------
-loadInterface :: SDoc -> Module -> WhereFrom
- -> IfM lcl (MaybeErr MsgDoc ModIface)
-
--- loadInterface looks in both the HPT and PIT for the required interface
--- If not found, it loads it, and puts it in the PIT (always).
-
--- If it can't find a suitable interface file, we
--- a) modify the PackageIfaceTable to have an empty entry
--- (to avoid repeated complaints)
--- b) return (Left message)
---
--- It's not necessarily an error for there not to be an interface
--- file -- perhaps the module has changed, and that interface
--- is no longer used
-
-loadInterface doc_str mod from
- | isHoleModule mod
- -- Hole modules get special treatment
- = do dflags <- getDynFlags
- -- Redo search for our local hole module
- loadInterface doc_str (mkModule (thisPackage dflags) (moduleName mod)) from
- | otherwise
- = withTimingSilentD (text "loading interface") (pure ()) $
- do { -- Read the state
- (eps,hpt) <- getEpsAndHpt
- ; gbl_env <- getGblEnv
-
- ; traceIf (text "Considering whether to load" <+> ppr mod <+> ppr from)
-
- -- Check whether we have the interface already
- ; dflags <- getDynFlags
- ; case lookupIfaceByModule hpt (eps_PIT eps) mod of {
- Just iface
- -> return (Succeeded iface) ; -- Already loaded
- -- The (src_imp == mi_boot iface) test checks that the already-loaded
- -- interface isn't a boot iface. This can conceivably happen,
- -- if an earlier import had a before we got to real imports. I think.
- _ -> do {
-
- -- READ THE MODULE IN
- ; read_result <- case (wantHiBootFile dflags eps mod from) of
- Failed err -> return (Failed err)
- Succeeded hi_boot_file -> computeInterface doc_str hi_boot_file mod
- ; case read_result of {
- Failed err -> do
- { let fake_iface = emptyFullModIface mod
-
- ; updateEps_ $ \eps ->
- eps { eps_PIT = extendModuleEnv (eps_PIT eps) (mi_module fake_iface) fake_iface }
- -- Not found, so add an empty iface to
- -- the EPS map so that we don't look again
-
- ; return (Failed err) } ;
-
- -- Found and parsed!
- -- We used to have a sanity check here that looked for:
- -- * System importing ..
- -- * a home package module ..
- -- * that we know nothing about (mb_dep == Nothing)!
- --
- -- But this is no longer valid because thNameToGhcName allows users to
- -- cause the system to load arbitrary interfaces (by supplying an appropriate
- -- Template Haskell original-name).
- Succeeded (iface, loc) ->
- let
- loc_doc = text loc
- in
- initIfaceLcl (mi_semantic_module iface) loc_doc (mi_boot iface) $ do
-
- dontLeakTheHPT $ do
-
- -- Load the new ModIface into the External Package State
- -- Even home-package interfaces loaded by loadInterface
- -- (which only happens in OneShot mode; in Batch/Interactive
- -- mode, home-package modules are loaded one by one into the HPT)
- -- are put in the EPS.
- --
- -- The main thing is to add the ModIface to the PIT, but
- -- we also take the
- -- IfaceDecls, IfaceClsInst, IfaceFamInst, IfaceRules,
- -- out of the ModIface and put them into the big EPS pools
-
- -- NB: *first* we do loadDecl, so that the provenance of all the locally-defined
- --- names is done correctly (notably, whether this is an .hi file or .hi-boot file).
- -- If we do loadExport first the wrong info gets into the cache (unless we
- -- explicitly tag each export which seems a bit of a bore)
-
- ; ignore_prags <- goptM Opt_IgnoreInterfacePragmas
- ; new_eps_decls <- loadDecls ignore_prags (mi_decls iface)
- ; new_eps_insts <- mapM tcIfaceInst (mi_insts iface)
- ; new_eps_fam_insts <- mapM tcIfaceFamInst (mi_fam_insts iface)
- ; new_eps_rules <- tcIfaceRules ignore_prags (mi_rules iface)
- ; new_eps_anns <- tcIfaceAnnotations (mi_anns iface)
- ; new_eps_complete_sigs <- tcIfaceCompleteSigs (mi_complete_sigs iface)
-
- ; let { final_iface = iface {
- mi_decls = panic "No mi_decls in PIT",
- mi_insts = panic "No mi_insts in PIT",
- mi_fam_insts = panic "No mi_fam_insts in PIT",
- mi_rules = panic "No mi_rules in PIT",
- mi_anns = panic "No mi_anns in PIT"
- }
- }
-
- ; let bad_boot = mi_boot iface && fmap fst (if_rec_types gbl_env) == Just mod
- -- Warn warn against an EPS-updating import
- -- of one's own boot file! (one-shot only)
- -- See Note [Loading your own hi-boot file]
- -- in MkIface.
-
- ; WARN( bad_boot, ppr mod )
- updateEps_ $ \ eps ->
- if elemModuleEnv mod (eps_PIT eps) || is_external_sig dflags iface
- then eps
- else if bad_boot
- -- See Note [Loading your own hi-boot file]
- then eps { eps_PTE = addDeclsToPTE (eps_PTE eps) new_eps_decls }
- else
- eps {
- eps_PIT = extendModuleEnv (eps_PIT eps) mod final_iface,
- eps_PTE = addDeclsToPTE (eps_PTE eps) new_eps_decls,
- eps_rule_base = extendRuleBaseList (eps_rule_base eps)
- new_eps_rules,
- eps_complete_matches
- = extendCompleteMatchMap
- (eps_complete_matches eps)
- new_eps_complete_sigs,
- eps_inst_env = extendInstEnvList (eps_inst_env eps)
- new_eps_insts,
- eps_fam_inst_env = extendFamInstEnvList (eps_fam_inst_env eps)
- new_eps_fam_insts,
- eps_ann_env = extendAnnEnvList (eps_ann_env eps)
- new_eps_anns,
- eps_mod_fam_inst_env
- = let
- fam_inst_env =
- extendFamInstEnvList emptyFamInstEnv
- new_eps_fam_insts
- in
- extendModuleEnv (eps_mod_fam_inst_env eps)
- mod
- fam_inst_env,
- eps_stats = addEpsInStats (eps_stats eps)
- (length new_eps_decls)
- (length new_eps_insts)
- (length new_eps_rules) }
-
- ; -- invoke plugins
- res <- withPlugins dflags interfaceLoadAction final_iface
- ; return (Succeeded res)
- }}}}
-
-{- Note [Loading your own hi-boot file]
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-Generally speaking, when compiling module M, we should not
-load M.hi boot into the EPS. After all, we are very shortly
-going to have full information about M. Moreover, see
-Note [Do not update EPS with your own hi-boot] in MkIface.
-
-But there is a HORRIBLE HACK here.
-
-* At the end of tcRnImports, we call checkFamInstConsistency to
- check consistency of imported type-family instances
- See Note [The type family instance consistency story] in FamInst
-
-* Alas, those instances may refer to data types defined in M,
- if there is a M.hs-boot.
-
-* And that means we end up loading M.hi-boot, because those
- data types are not yet in the type environment.
-
-But in this weird case, /all/ we need is the types. We don't need
-instances, rules etc. And if we put the instances in the EPS
-we get "duplicate instance" warnings when we compile the "real"
-instance in M itself. Hence the strange business of just updateing
-the eps_PTE.
-
-This really happens in practice. The module HsExpr.hs gets
-"duplicate instance" errors if this hack is not present.
-
-This is a mess.
-
-
-Note [HPT space leak] (#15111)
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-In IfL, we defer some work until it is demanded using forkM, such
-as building TyThings from IfaceDecls. These thunks are stored in
-the ExternalPackageState, and they might never be poked. If we're
-not careful, these thunks will capture the state of the loaded
-program when we read an interface file, and retain all that data
-for ever.
-
-Therefore, when loading a package interface file , we use a "clean"
-version of the HscEnv with all the data about the currently loaded
-program stripped out. Most of the fields can be panics because
-we'll never read them, but hsc_HPT needs to be empty because this
-interface will cause other interfaces to be loaded recursively, and
-when looking up those interfaces we use the HPT in loadInterface.
-We know that none of the interfaces below here can refer to
-home-package modules however, so it's safe for the HPT to be empty.
--}
-
-dontLeakTheHPT :: IfL a -> IfL a
-dontLeakTheHPT thing_inside = do
- let
- cleanTopEnv HscEnv{..} =
- let
- -- wrinkle: when we're typechecking in --backpack mode, the
- -- instantiation of a signature might reside in the HPT, so
- -- this case breaks the assumption that EPS interfaces only
- -- refer to other EPS interfaces. We can detect when we're in
- -- typechecking-only mode by using hscTarget==HscNothing, and
- -- in that case we don't empty the HPT. (admittedly this is
- -- a bit of a hack, better suggestions welcome). A number of
- -- tests in testsuite/tests/backpack break without this
- -- tweak.
- !hpt | hscTarget hsc_dflags == HscNothing = hsc_HPT
- | otherwise = emptyHomePackageTable
- in
- HscEnv { hsc_targets = panic "cleanTopEnv: hsc_targets"
- , hsc_mod_graph = panic "cleanTopEnv: hsc_mod_graph"
- , hsc_IC = panic "cleanTopEnv: hsc_IC"
- , hsc_HPT = hpt
- , .. }
-
- updTopEnv cleanTopEnv $ do
- !_ <- getTopEnv -- force the updTopEnv
- thing_inside
-
-
--- | Returns @True@ if a 'ModIface' comes from an external package.
--- In this case, we should NOT load it into the EPS; the entities
--- should instead come from the local merged signature interface.
-is_external_sig :: DynFlags -> ModIface -> Bool
-is_external_sig dflags iface =
- -- It's a signature iface...
- mi_semantic_module iface /= mi_module iface &&
- -- and it's not from the local package
- moduleUnitId (mi_module iface) /= thisPackage dflags
-
--- | This is an improved version of 'findAndReadIface' which can also
--- handle the case when a user requests @p[A=<B>]:M@ but we only
--- have an interface for @p[A=<A>]:M@ (the indefinite interface.
--- If we are not trying to build code, we load the interface we have,
--- *instantiating it* according to how the holes are specified.
--- (Of course, if we're actually building code, this is a hard error.)
---
--- In the presence of holes, 'computeInterface' has an important invariant:
--- to load module M, its set of transitively reachable requirements must
--- have an up-to-date local hi file for that requirement. Note that if
--- we are loading the interface of a requirement, this does not
--- apply to the requirement itself; e.g., @p[A=<A>]:A@ does not require
--- A.hi to be up-to-date (and indeed, we MUST NOT attempt to read A.hi, unless
--- we are actually typechecking p.)
-computeInterface ::
- SDoc -> IsBootInterface -> Module
- -> TcRnIf gbl lcl (MaybeErr MsgDoc (ModIface, FilePath))
-computeInterface doc_str hi_boot_file mod0 = do
- MASSERT( not (isHoleModule mod0) )
- dflags <- getDynFlags
- case splitModuleInsts mod0 of
- (imod, Just indef) | not (unitIdIsDefinite (thisPackage dflags)) -> do
- r <- findAndReadIface doc_str imod mod0 hi_boot_file
- case r of
- Succeeded (iface0, path) -> do
- hsc_env <- getTopEnv
- r <- liftIO $
- rnModIface hsc_env (indefUnitIdInsts (indefModuleUnitId indef))
- Nothing iface0
- case r of
- Right x -> return (Succeeded (x, path))
- Left errs -> liftIO . throwIO . mkSrcErr $ errs
- Failed err -> return (Failed err)
- (mod, _) ->
- findAndReadIface doc_str mod mod0 hi_boot_file
-
--- | Compute the signatures which must be compiled in order to
--- load the interface for a 'Module'. The output of this function
--- is always a subset of 'moduleFreeHoles'; it is more precise
--- because in signature @p[A=<A>,B=<B>]:B@, although the free holes
--- are A and B, B might not depend on A at all!
---
--- If this is invoked on a signature, this does NOT include the
--- signature itself; e.g. precise free module holes of
--- @p[A=<A>,B=<B>]:B@ never includes B.
-moduleFreeHolesPrecise
- :: SDoc -> Module
- -> TcRnIf gbl lcl (MaybeErr MsgDoc (UniqDSet ModuleName))
-moduleFreeHolesPrecise doc_str mod
- | moduleIsDefinite mod = return (Succeeded emptyUniqDSet)
- | otherwise =
- case splitModuleInsts mod of
- (imod, Just indef) -> do
- let insts = indefUnitIdInsts (indefModuleUnitId indef)
- traceIf (text "Considering whether to load" <+> ppr mod <+>
- text "to compute precise free module holes")
- (eps, hpt) <- getEpsAndHpt
- case tryEpsAndHpt eps hpt `firstJust` tryDepsCache eps imod insts of
- Just r -> return (Succeeded r)
- Nothing -> readAndCache imod insts
- (_, Nothing) -> return (Succeeded emptyUniqDSet)
- where
- tryEpsAndHpt eps hpt =
- fmap mi_free_holes (lookupIfaceByModule hpt (eps_PIT eps) mod)
- tryDepsCache eps imod insts =
- case lookupInstalledModuleEnv (eps_free_holes eps) imod of
- Just ifhs -> Just (renameFreeHoles ifhs insts)
- _otherwise -> Nothing
- readAndCache imod insts = do
- mb_iface <- findAndReadIface (text "moduleFreeHolesPrecise" <+> doc_str) imod mod False
- case mb_iface of
- Succeeded (iface, _) -> do
- let ifhs = mi_free_holes iface
- -- Cache it
- updateEps_ (\eps ->
- eps { eps_free_holes = extendInstalledModuleEnv (eps_free_holes eps) imod ifhs })
- return (Succeeded (renameFreeHoles ifhs insts))
- Failed err -> return (Failed err)
-
-wantHiBootFile :: DynFlags -> ExternalPackageState -> Module -> WhereFrom
- -> MaybeErr MsgDoc IsBootInterface
--- Figure out whether we want Foo.hi or Foo.hi-boot
-wantHiBootFile dflags eps mod from
- = case from of
- ImportByUser usr_boot
- | usr_boot && not this_package
- -> Failed (badSourceImport mod)
- | otherwise -> Succeeded usr_boot
-
- ImportByPlugin
- -> Succeeded False
-
- ImportBySystem
- | not this_package -- If the module to be imported is not from this package
- -> Succeeded False -- don't look it up in eps_is_boot, because that is keyed
- -- on the ModuleName of *home-package* modules only.
- -- We never import boot modules from other packages!
-
- | otherwise
- -> case lookupUFM (eps_is_boot eps) (moduleName mod) of
- Just (_, is_boot) -> Succeeded is_boot
- Nothing -> Succeeded False
- -- The boot-ness of the requested interface,
- -- based on the dependencies in directly-imported modules
- where
- this_package = thisPackage dflags == moduleUnitId mod
-
-badSourceImport :: Module -> SDoc
-badSourceImport mod
- = hang (text "You cannot {-# SOURCE #-} import a module from another package")
- 2 (text "but" <+> quotes (ppr mod) <+> ptext (sLit "is from package")
- <+> quotes (ppr (moduleUnitId mod)))
-
------------------------------------------------------
--- Loading type/class/value decls
--- We pass the full Module name here, replete with
--- its package info, so that we can build a Name for
--- each binder with the right package info in it
--- All subsequent lookups, including crucially lookups during typechecking
--- the declaration itself, will find the fully-glorious Name
---
--- We handle ATs specially. They are not main declarations, but also not
--- implicit things (in particular, adding them to `implicitTyThings' would mess
--- things up in the renaming/type checking of source programs).
------------------------------------------------------
-
-addDeclsToPTE :: PackageTypeEnv -> [(Name,TyThing)] -> PackageTypeEnv
-addDeclsToPTE pte things = extendNameEnvList pte things
-
-loadDecls :: Bool
- -> [(Fingerprint, IfaceDecl)]
- -> IfL [(Name,TyThing)]
-loadDecls ignore_prags ver_decls
- = do { thingss <- mapM (loadDecl ignore_prags) ver_decls
- ; return (concat thingss)
- }
-
-loadDecl :: Bool -- Don't load pragmas into the decl pool
- -> (Fingerprint, IfaceDecl)
- -> IfL [(Name,TyThing)] -- The list can be poked eagerly, but the
- -- TyThings are forkM'd thunks
-loadDecl ignore_prags (_version, decl)
- = do { -- Populate the name cache with final versions of all
- -- the names associated with the decl
- let main_name = ifName decl
-
- -- Typecheck the thing, lazily
- -- NB. Firstly, the laziness is there in case we never need the
- -- declaration (in one-shot mode), and secondly it is there so that
- -- we don't look up the occurrence of a name before calling mk_new_bndr
- -- on the binder. This is important because we must get the right name
- -- which includes its nameParent.
-
- ; thing <- forkM doc $ do { bumpDeclStats main_name
- ; tcIfaceDecl ignore_prags decl }
-
- -- Populate the type environment with the implicitTyThings too.
- --
- -- Note [Tricky iface loop]
- -- ~~~~~~~~~~~~~~~~~~~~~~~~
- -- Summary: The delicate point here is that 'mini-env' must be
- -- buildable from 'thing' without demanding any of the things
- -- 'forkM'd by tcIfaceDecl.
- --
- -- In more detail: Consider the example
- -- data T a = MkT { x :: T a }
- -- The implicitTyThings of T are: [ <datacon MkT>, <selector x>]
- -- (plus their workers, wrappers, coercions etc etc)
- --
- -- We want to return an environment
- -- [ "MkT" -> <datacon MkT>, "x" -> <selector x>, ... ]
- -- (where the "MkT" is the *Name* associated with MkT, etc.)
- --
- -- We do this by mapping the implicit_names to the associated
- -- TyThings. By the invariant on ifaceDeclImplicitBndrs and
- -- implicitTyThings, we can use getOccName on the implicit
- -- TyThings to make this association: each Name's OccName should
- -- be the OccName of exactly one implicitTyThing. So the key is
- -- to define a "mini-env"
- --
- -- [ 'MkT' -> <datacon MkT>, 'x' -> <selector x>, ... ]
- -- where the 'MkT' here is the *OccName* associated with MkT.
- --
- -- However, there is a subtlety: due to how type checking needs
- -- to be staged, we can't poke on the forkM'd thunks inside the
- -- implicitTyThings while building this mini-env.
- -- If we poke these thunks too early, two problems could happen:
- -- (1) When processing mutually recursive modules across
- -- hs-boot boundaries, poking too early will do the
- -- type-checking before the recursive knot has been tied,
- -- so things will be type-checked in the wrong
- -- environment, and necessary variables won't be in
- -- scope.
- --
- -- (2) Looking up one OccName in the mini_env will cause
- -- others to be looked up, which might cause that
- -- original one to be looked up again, and hence loop.
- --
- -- The code below works because of the following invariant:
- -- getOccName on a TyThing does not force the suspended type
- -- checks in order to extract the name. For example, we don't
- -- poke on the "T a" type of <selector x> on the way to
- -- extracting <selector x>'s OccName. Of course, there is no
- -- reason in principle why getting the OccName should force the
- -- thunks, but this means we need to be careful in
- -- implicitTyThings and its helper functions.
- --
- -- All a bit too finely-balanced for my liking.
-
- -- This mini-env and lookup function mediates between the
- --'Name's n and the map from 'OccName's to the implicit TyThings
- ; let mini_env = mkOccEnv [(getOccName t, t) | t <- implicitTyThings thing]
- lookup n = case lookupOccEnv mini_env (getOccName n) of
- Just thing -> thing
- Nothing ->
- pprPanic "loadDecl" (ppr main_name <+> ppr n $$ ppr (decl))
-
- ; implicit_names <- mapM lookupIfaceTop (ifaceDeclImplicitBndrs decl)
-
--- ; traceIf (text "Loading decl for " <> ppr main_name $$ ppr implicit_names)
- ; return $ (main_name, thing) :
- -- uses the invariant that implicit_names and
- -- implicitTyThings are bijective
- [(n, lookup n) | n <- implicit_names]
- }
- where
- doc = text "Declaration for" <+> ppr (ifName decl)
-
-bumpDeclStats :: Name -> IfL () -- Record that one more declaration has actually been used
-bumpDeclStats name
- = do { traceIf (text "Loading decl for" <+> ppr name)
- ; updateEps_ (\eps -> let stats = eps_stats eps
- in eps { eps_stats = stats { n_decls_out = n_decls_out stats + 1 } })
- }
-
-{-
-*********************************************************
-* *
-\subsection{Reading an interface file}
-* *
-*********************************************************
-
-Note [Home module load error]
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-If the sought-for interface is in the current package (as determined
-by -package-name flag) then it jolly well should already be in the HPT
-because we process home-package modules in dependency order. (Except
-in one-shot mode; see notes with hsc_HPT decl in HscTypes).
-
-It is possible (though hard) to get this error through user behaviour.
- * Suppose package P (modules P1, P2) depends on package Q (modules Q1,
- Q2, with Q2 importing Q1)
- * We compile both packages.
- * Now we edit package Q so that it somehow depends on P
- * Now recompile Q with --make (without recompiling P).
- * Then Q1 imports, say, P1, which in turn depends on Q2. So Q2
- is a home-package module which is not yet in the HPT! Disaster.
-
-This actually happened with P=base, Q=ghc-prim, via the AMP warnings.
-See #8320.
--}
-
-findAndReadIface :: SDoc
- -- The unique identifier of the on-disk module we're
- -- looking for
- -> InstalledModule
- -- The *actual* module we're looking for. We use
- -- this to check the consistency of the requirements
- -- of the module we read out.
- -> Module
- -> IsBootInterface -- True <=> Look for a .hi-boot file
- -- False <=> Look for .hi file
- -> TcRnIf gbl lcl (MaybeErr MsgDoc (ModIface, FilePath))
- -- Nothing <=> file not found, or unreadable, or illegible
- -- Just x <=> successfully found and parsed
-
- -- It *doesn't* add an error to the monad, because
- -- sometimes it's ok to fail... see notes with loadInterface
-findAndReadIface doc_str mod wanted_mod_with_insts hi_boot_file
- = do traceIf (sep [hsep [text "Reading",
- if hi_boot_file
- then text "[boot]"
- else Outputable.empty,
- text "interface for",
- ppr mod <> semi],
- nest 4 (text "reason:" <+> doc_str)])
-
- -- Check for GHC.Prim, and return its static interface
- -- TODO: make this check a function
- if mod `installedModuleEq` gHC_PRIM
- then do
- iface <- getHooked ghcPrimIfaceHook ghcPrimIface
- return (Succeeded (iface,
- "<built in interface for GHC.Prim>"))
- else do
- dflags <- getDynFlags
- -- Look for the file
- hsc_env <- getTopEnv
- mb_found <- liftIO (findExactModule hsc_env mod)
- case mb_found of
- InstalledFound loc mod -> do
- -- Found file, so read it
- let file_path = addBootSuffix_maybe hi_boot_file
- (ml_hi_file loc)
-
- -- See Note [Home module load error]
- if installedModuleUnitId mod `installedUnitIdEq` thisPackage dflags &&
- not (isOneShot (ghcMode dflags))
- then return (Failed (homeModError mod loc))
- else do r <- read_file file_path
- checkBuildDynamicToo r
- return r
- err -> do
- traceIf (text "...not found")
- dflags <- getDynFlags
- return (Failed (cannotFindInterface dflags
- (installedModuleName mod) err))
- where read_file file_path = do
- traceIf (text "readIFace" <+> text file_path)
- -- Figure out what is recorded in mi_module. If this is
- -- a fully definite interface, it'll match exactly, but
- -- if it's indefinite, the inside will be uninstantiated!
- dflags <- getDynFlags
- let wanted_mod =
- case splitModuleInsts wanted_mod_with_insts of
- (_, Nothing) -> wanted_mod_with_insts
- (_, Just indef_mod) ->
- indefModuleToModule dflags
- (generalizeIndefModule indef_mod)
- read_result <- readIface wanted_mod file_path
- case read_result of
- Failed err -> return (Failed (badIfaceFile file_path err))
- Succeeded iface -> return (Succeeded (iface, file_path))
- -- Don't forget to fill in the package name...
- checkBuildDynamicToo (Succeeded (iface, filePath)) = do
- dflags <- getDynFlags
- -- Indefinite interfaces are ALWAYS non-dynamic, and
- -- that's OK.
- let is_definite_iface = moduleIsDefinite (mi_module iface)
- when is_definite_iface $
- whenGeneratingDynamicToo dflags $ withDoDynamicToo $ do
- let ref = canGenerateDynamicToo dflags
- dynFilePath = addBootSuffix_maybe hi_boot_file
- $ replaceExtension filePath (dynHiSuf dflags)
- r <- read_file dynFilePath
- case r of
- Succeeded (dynIface, _)
- | mi_mod_hash (mi_final_exts iface) == mi_mod_hash (mi_final_exts dynIface) ->
- return ()
- | otherwise ->
- do traceIf (text "Dynamic hash doesn't match")
- liftIO $ writeIORef ref False
- Failed err ->
- do traceIf (text "Failed to load dynamic interface file:" $$ err)
- liftIO $ writeIORef ref False
- checkBuildDynamicToo _ = return ()
-
--- @readIface@ tries just the one file.
-
-readIface :: Module -> FilePath
- -> TcRnIf gbl lcl (MaybeErr MsgDoc ModIface)
- -- Failed err <=> file not found, or unreadable, or illegible
- -- Succeeded iface <=> successfully found and parsed
-
-readIface wanted_mod file_path
- = do { res <- tryMostM $
- readBinIface CheckHiWay QuietBinIFaceReading file_path
- ; dflags <- getDynFlags
- ; case res of
- Right iface
- -- NB: This check is NOT just a sanity check, it is
- -- critical for correctness of recompilation checking
- -- (it lets us tell when -this-unit-id has changed.)
- | wanted_mod == actual_mod
- -> return (Succeeded iface)
- | otherwise -> return (Failed err)
- where
- actual_mod = mi_module iface
- err = hiModuleNameMismatchWarn dflags wanted_mod actual_mod
-
- Left exn -> return (Failed (text (showException exn)))
- }
-
-{-
-*********************************************************
-* *
- Wired-in interface for GHC.Prim
-* *
-*********************************************************
--}
-
-initExternalPackageState :: ExternalPackageState
-initExternalPackageState
- = EPS {
- eps_is_boot = emptyUFM,
- eps_PIT = emptyPackageIfaceTable,
- eps_free_holes = emptyInstalledModuleEnv,
- eps_PTE = emptyTypeEnv,
- eps_inst_env = emptyInstEnv,
- eps_fam_inst_env = emptyFamInstEnv,
- eps_rule_base = mkRuleBase builtinRules,
- -- Initialise the EPS rule pool with the built-in rules
- eps_mod_fam_inst_env
- = emptyModuleEnv,
- eps_complete_matches = emptyUFM,
- eps_ann_env = emptyAnnEnv,
- eps_stats = EpsStats { n_ifaces_in = 0, n_decls_in = 0, n_decls_out = 0
- , n_insts_in = 0, n_insts_out = 0
- , n_rules_in = length builtinRules, n_rules_out = 0 }
- }
-
-{-
-*********************************************************
-* *
- Wired-in interface for GHC.Prim
-* *
-*********************************************************
--}
-
-ghcPrimIface :: ModIface
-ghcPrimIface
- = empty_iface {
- mi_exports = ghcPrimExports,
- mi_decls = [],
- mi_fixities = fixities,
- mi_final_exts = (mi_final_exts empty_iface){ mi_fix_fn = mkIfaceFixCache fixities }
- }
- where
- empty_iface = emptyFullModIface gHC_PRIM
-
- -- The fixities listed here for @`seq`@ or @->@ should match
- -- those in primops.txt.pp (from which Haddock docs are generated).
- fixities = (getOccName seqId, Fixity NoSourceText 0 InfixR)
- : (occName funTyConName, funTyFixity) -- trac #10145
- : mapMaybe mkFixity allThePrimOps
- mkFixity op = (,) (primOpOcc op) <$> primOpFixity op
-
-{-
-*********************************************************
-* *
-\subsection{Statistics}
-* *
-*********************************************************
--}
-
-ifaceStats :: ExternalPackageState -> SDoc
-ifaceStats eps
- = hcat [text "Renamer stats: ", msg]
- where
- stats = eps_stats eps
- msg = vcat
- [int (n_ifaces_in stats) <+> text "interfaces read",
- hsep [ int (n_decls_out stats), text "type/class/variable imported, out of",
- int (n_decls_in stats), text "read"],
- hsep [ int (n_insts_out stats), text "instance decls imported, out of",
- int (n_insts_in stats), text "read"],
- hsep [ int (n_rules_out stats), text "rule decls imported, out of",
- int (n_rules_in stats), text "read"]
- ]
-
-{-
-************************************************************************
-* *
- Printing interfaces
-* *
-************************************************************************
-
-Note [Name qualification with --show-iface]
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-In order to disambiguate between identifiers from different modules, we qualify
-all names that don't originate in the current module. In order to keep visual
-noise as low as possible, we keep local names unqualified.
-
-For some background on this choice see trac #15269.
--}
-
--- | Read binary interface, and print it out
-showIface :: HscEnv -> FilePath -> IO ()
-showIface hsc_env filename = do
- -- skip the hi way check; we don't want to worry about profiled vs.
- -- non-profiled interfaces, for example.
- iface <- initTcRnIf 's' hsc_env () () $
- readBinIface IgnoreHiWay TraceBinIFaceReading filename
- let dflags = hsc_dflags hsc_env
- -- See Note [Name qualification with --show-iface]
- qualifyImportedNames mod _
- | mod == mi_module iface = NameUnqual
- | otherwise = NameNotInScope1
- print_unqual = QueryQualify qualifyImportedNames
- neverQualifyModules
- neverQualifyPackages
- putLogMsg dflags NoReason SevDump noSrcSpan
- (mkDumpStyle dflags print_unqual) (pprModIface iface)
-
--- Show a ModIface but don't display details; suitable for ModIfaces stored in
--- the EPT.
-pprModIfaceSimple :: ModIface -> SDoc
-pprModIfaceSimple iface = ppr (mi_module iface) $$ pprDeps (mi_deps iface) $$ nest 2 (vcat (map pprExport (mi_exports iface)))
-
-pprModIface :: ModIface -> SDoc
--- Show a ModIface
-pprModIface iface@ModIface{ mi_final_exts = exts }
- = vcat [ text "interface"
- <+> ppr (mi_module iface) <+> pp_hsc_src (mi_hsc_src iface)
- <+> (if mi_orphan exts then text "[orphan module]" else Outputable.empty)
- <+> (if mi_finsts exts then text "[family instance module]" else Outputable.empty)
- <+> (if mi_hpc iface then text "[hpc]" else Outputable.empty)
- <+> integer hiVersion
- , nest 2 (text "interface hash:" <+> ppr (mi_iface_hash exts))
- , nest 2 (text "ABI hash:" <+> ppr (mi_mod_hash exts))
- , nest 2 (text "export-list hash:" <+> ppr (mi_exp_hash exts))
- , nest 2 (text "orphan hash:" <+> ppr (mi_orphan_hash exts))
- , nest 2 (text "flag hash:" <+> ppr (mi_flag_hash exts))
- , nest 2 (text "opt_hash:" <+> ppr (mi_opt_hash exts))
- , nest 2 (text "hpc_hash:" <+> ppr (mi_hpc_hash exts))
- , nest 2 (text "plugin_hash:" <+> ppr (mi_plugin_hash exts))
- , nest 2 (text "sig of:" <+> ppr (mi_sig_of iface))
- , nest 2 (text "used TH splices:" <+> ppr (mi_used_th iface))
- , nest 2 (text "where")
- , text "exports:"
- , nest 2 (vcat (map pprExport (mi_exports iface)))
- , pprDeps (mi_deps iface)
- , vcat (map pprUsage (mi_usages iface))
- , vcat (map pprIfaceAnnotation (mi_anns iface))
- , pprFixities (mi_fixities iface)
- , vcat [ppr ver $$ nest 2 (ppr decl) | (ver,decl) <- mi_decls iface]
- , vcat (map ppr (mi_insts iface))
- , vcat (map ppr (mi_fam_insts iface))
- , vcat (map ppr (mi_rules iface))
- , ppr (mi_warns iface)
- , pprTrustInfo (mi_trust iface)
- , pprTrustPkg (mi_trust_pkg iface)
- , vcat (map ppr (mi_complete_sigs iface))
- , text "module header:" $$ nest 2 (ppr (mi_doc_hdr iface))
- , text "declaration docs:" $$ nest 2 (ppr (mi_decl_docs iface))
- , text "arg docs:" $$ nest 2 (ppr (mi_arg_docs iface))
- ]
- where
- pp_hsc_src HsBootFile = text "[boot]"
- pp_hsc_src HsigFile = text "[hsig]"
- pp_hsc_src HsSrcFile = Outputable.empty
-
-{-
-When printing export lists, we print like this:
- Avail f f
- AvailTC C [C, x, y] C(x,y)
- AvailTC C [x, y] C!(x,y) -- Exporting x, y but not C
--}
-
-pprExport :: IfaceExport -> SDoc
-pprExport (Avail n) = ppr n
-pprExport (AvailTC _ [] []) = Outputable.empty
-pprExport (AvailTC n ns0 fs)
- = case ns0 of
- (n':ns) | n==n' -> ppr n <> pp_export ns fs
- _ -> ppr n <> vbar <> pp_export ns0 fs
- where
- pp_export [] [] = Outputable.empty
- pp_export names fs = braces (hsep (map ppr names ++ map (ppr . flLabel) fs))
-
-pprUsage :: Usage -> SDoc
-pprUsage usage@UsagePackageModule{}
- = pprUsageImport usage usg_mod
-pprUsage usage@UsageHomeModule{}
- = pprUsageImport usage usg_mod_name $$
- nest 2 (
- maybe Outputable.empty (\v -> text "exports: " <> ppr v) (usg_exports usage) $$
- vcat [ ppr n <+> ppr v | (n,v) <- usg_entities usage ]
- )
-pprUsage usage@UsageFile{}
- = hsep [text "addDependentFile",
- doubleQuotes (text (usg_file_path usage)),
- ppr (usg_file_hash usage)]
-pprUsage usage@UsageMergedRequirement{}
- = hsep [text "merged", ppr (usg_mod usage), ppr (usg_mod_hash usage)]
-
-pprUsageImport :: Outputable a => Usage -> (Usage -> a) -> SDoc
-pprUsageImport usage usg_mod'
- = hsep [text "import", safe, ppr (usg_mod' usage),
- ppr (usg_mod_hash usage)]
- where
- safe | usg_safe usage = text "safe"
- | otherwise = text " -/ "
-
-pprDeps :: Dependencies -> SDoc
-pprDeps (Deps { dep_mods = mods, dep_pkgs = pkgs, dep_orphs = orphs,
- dep_finsts = finsts })
- = vcat [text "module dependencies:" <+> fsep (map ppr_mod mods),
- text "package dependencies:" <+> fsep (map ppr_pkg pkgs),
- text "orphans:" <+> fsep (map ppr orphs),
- text "family instance modules:" <+> fsep (map ppr finsts)
- ]
- where
- ppr_mod (mod_name, boot) = ppr mod_name <+> ppr_boot boot
- ppr_pkg (pkg,trust_req) = ppr pkg <>
- (if trust_req then text "*" else Outputable.empty)
- ppr_boot True = text "[boot]"
- ppr_boot False = Outputable.empty
-
-pprFixities :: [(OccName, Fixity)] -> SDoc
-pprFixities [] = Outputable.empty
-pprFixities fixes = text "fixities" <+> pprWithCommas pprFix fixes
- where
- pprFix (occ,fix) = ppr fix <+> ppr occ
-
-pprTrustInfo :: IfaceTrustInfo -> SDoc
-pprTrustInfo trust = text "trusted:" <+> ppr trust
-
-pprTrustPkg :: Bool -> SDoc
-pprTrustPkg tpkg = text "require own pkg trusted:" <+> ppr tpkg
-
-instance Outputable Warnings where
- ppr = pprWarns
-
-pprWarns :: Warnings -> SDoc
-pprWarns NoWarnings = Outputable.empty
-pprWarns (WarnAll txt) = text "Warn all" <+> ppr txt
-pprWarns (WarnSome prs) = text "Warnings"
- <+> vcat (map pprWarning prs)
- where pprWarning (name, txt) = ppr name <+> ppr txt
-
-pprIfaceAnnotation :: IfaceAnnotation -> SDoc
-pprIfaceAnnotation (IfaceAnnotation { ifAnnotatedTarget = target, ifAnnotatedValue = serialized })
- = ppr target <+> text "annotated by" <+> ppr serialized
-
-{-
-*********************************************************
-* *
-\subsection{Errors}
-* *
-*********************************************************
--}
-
-badIfaceFile :: String -> SDoc -> SDoc
-badIfaceFile file err
- = vcat [text "Bad interface file:" <+> text file,
- nest 4 err]
-
-hiModuleNameMismatchWarn :: DynFlags -> Module -> Module -> MsgDoc
-hiModuleNameMismatchWarn dflags requested_mod read_mod
- | moduleUnitId requested_mod == moduleUnitId read_mod =
- sep [text "Interface file contains module" <+> quotes (ppr read_mod) <> comma,
- text "but we were expecting module" <+> quotes (ppr requested_mod),
- sep [text "Probable cause: the source code which generated interface file",
- text "has an incompatible module name"
- ]
- ]
- | otherwise =
- -- ToDo: This will fail to have enough qualification when the package IDs
- -- are the same
- withPprStyle (mkUserStyle dflags alwaysQualify AllTheWay) $
- -- we want the Modules below to be qualified with package names,
- -- so reset the PrintUnqualified setting.
- hsep [ text "Something is amiss; requested module "
- , ppr requested_mod
- , text "differs from name found in the interface file"
- , ppr read_mod
- , parens (text "if these names look the same, try again with -dppr-debug")
- ]
-
-homeModError :: InstalledModule -> ModLocation -> SDoc
--- See Note [Home module load error]
-homeModError mod location
- = text "attempting to use module " <> quotes (ppr mod)
- <> (case ml_hs_file location of
- Just file -> space <> parens (text file)
- Nothing -> Outputable.empty)
- <+> text "which is not loaded"
diff --git a/compiler/iface/LoadIface.hs-boot b/compiler/iface/LoadIface.hs-boot
deleted file mode 100644
index ff2b3efb1a..0000000000
--- a/compiler/iface/LoadIface.hs-boot
+++ /dev/null
@@ -1,7 +0,0 @@
-module LoadIface where
-import Module (Module)
-import TcRnMonad (IfM)
-import HscTypes (ModIface)
-import Outputable (SDoc)
-
-loadSysInterface :: SDoc -> Module -> IfM lcl ModIface
diff --git a/compiler/iface/MkIface.hs b/compiler/iface/MkIface.hs
deleted file mode 100644
index 02948d67c8..0000000000
--- a/compiler/iface/MkIface.hs
+++ /dev/null
@@ -1,2078 +0,0 @@
-{-
-(c) The University of Glasgow 2006-2008
-(c) The GRASP/AQUA Project, Glasgow University, 1993-1998
--}
-
-{-# LANGUAGE CPP, NondecreasingIndentation #-}
-{-# LANGUAGE MultiWayIf #-}
-
--- | Module for constructing @ModIface@ values (interface files),
--- writing them to disk and comparing two versions to see if
--- recompilation is required.
-module MkIface (
- mkPartialIface,
- mkFullIface,
-
- mkIfaceTc,
-
- writeIfaceFile, -- Write the interface file
-
- checkOldIface, -- See if recompilation is required, by
- -- comparing version information
- RecompileRequired(..), recompileRequired,
- mkIfaceExports,
-
- coAxiomToIfaceDecl,
- tyThingToIfaceDecl -- Converting things to their Iface equivalents
- ) where
-
-{-
- -----------------------------------------------
- Recompilation checking
- -----------------------------------------------
-
-A complete description of how recompilation checking works can be
-found in the wiki commentary:
-
- https://gitlab.haskell.org/ghc/ghc/wikis/commentary/compiler/recompilation-avoidance
-
-Please read the above page for a top-down description of how this all
-works. Notes below cover specific issues related to the implementation.
-
-Basic idea:
-
- * In the mi_usages information in an interface, we record the
- fingerprint of each free variable of the module
-
- * In mkIface, we compute the fingerprint of each exported thing A.f.
- For each external thing that A.f refers to, we include the fingerprint
- of the external reference when computing the fingerprint of A.f. So
- if anything that A.f depends on changes, then A.f's fingerprint will
- change.
- Also record any dependent files added with
- * addDependentFile
- * #include
- * -optP-include
-
- * In checkOldIface we compare the mi_usages for the module with
- the actual fingerprint for all each thing recorded in mi_usages
--}
-
-#include "HsVersions.h"
-
-import GhcPrelude
-
-import IfaceSyn
-import BinFingerprint
-import LoadIface
-import ToIface
-import FlagChecker
-
-import DsUsage ( mkUsageInfo, mkUsedNames, mkDependencies )
-import Id
-import Annotations
-import CoreSyn
-import Class
-import TyCon
-import CoAxiom
-import ConLike
-import DataCon
-import Type
-import TcType
-import InstEnv
-import FamInstEnv
-import TcRnMonad
-import GHC.Hs
-import HscTypes
-import Finder
-import DynFlags
-import VarEnv
-import Var
-import Name
-import Avail
-import RdrName
-import NameEnv
-import NameSet
-import Module
-import BinIface
-import ErrUtils
-import Digraph
-import SrcLoc
-import Outputable
-import BasicTypes hiding ( SuccessFlag(..) )
-import Unique
-import Util hiding ( eqListBy )
-import FastString
-import Maybes
-import Binary
-import Fingerprint
-import Exception
-import UniqSet
-import Packages
-import ExtractDocs
-
-import Control.Monad
-import Data.Function
-import Data.List
-import qualified Data.Map as Map
-import qualified Data.Set as Set
-import Data.Ord
-import Data.IORef
-import System.Directory
-import System.FilePath
-import Plugins ( PluginRecompile(..), PluginWithArgs(..), LoadedPlugin(..),
- pluginRecompile', plugins )
-
---Qualified import so we can define a Semigroup instance
--- but it doesn't clash with Outputable.<>
-import qualified Data.Semigroup
-
-{-
-************************************************************************
-* *
-\subsection{Completing an interface}
-* *
-************************************************************************
--}
-
-mkPartialIface :: HscEnv
- -> ModDetails
- -> ModGuts
- -> PartialModIface
-mkPartialIface hsc_env mod_details
- ModGuts{ mg_module = this_mod
- , mg_hsc_src = hsc_src
- , mg_usages = usages
- , mg_used_th = used_th
- , mg_deps = deps
- , mg_rdr_env = rdr_env
- , mg_fix_env = fix_env
- , mg_warns = warns
- , mg_hpc_info = hpc_info
- , mg_safe_haskell = safe_mode
- , mg_trust_pkg = self_trust
- , mg_doc_hdr = doc_hdr
- , mg_decl_docs = decl_docs
- , mg_arg_docs = arg_docs
- }
- = mkIface_ hsc_env this_mod hsc_src used_th deps rdr_env fix_env warns hpc_info self_trust
- safe_mode usages doc_hdr decl_docs arg_docs mod_details
-
--- | Fully instantiate a interface
--- Adds fingerprints and potentially code generator produced information.
-mkFullIface :: HscEnv -> PartialModIface -> IO ModIface
-mkFullIface hsc_env partial_iface = do
- full_iface <-
- {-# SCC "addFingerprints" #-}
- addFingerprints hsc_env partial_iface
-
- -- Debug printing
- dumpIfSet_dyn (hsc_dflags hsc_env) Opt_D_dump_hi "FINAL INTERFACE" FormatText (pprModIface full_iface)
-
- return full_iface
-
--- | Make an interface from the results of typechecking only. Useful
--- for non-optimising compilation, or where we aren't generating any
--- object code at all ('HscNothing').
-mkIfaceTc :: HscEnv
- -> SafeHaskellMode -- The safe haskell mode
- -> ModDetails -- gotten from mkBootModDetails, probably
- -> TcGblEnv -- Usages, deprecations, etc
- -> IO ModIface
-mkIfaceTc hsc_env safe_mode mod_details
- tc_result@TcGblEnv{ tcg_mod = this_mod,
- tcg_src = hsc_src,
- tcg_imports = imports,
- tcg_rdr_env = rdr_env,
- tcg_fix_env = fix_env,
- tcg_merged = merged,
- tcg_warns = warns,
- tcg_hpc = other_hpc_info,
- tcg_th_splice_used = tc_splice_used,
- tcg_dependent_files = dependent_files
- }
- = do
- let used_names = mkUsedNames tc_result
- let pluginModules =
- map lpModule (cachedPlugins (hsc_dflags hsc_env))
- deps <- mkDependencies
- (thisInstalledUnitId (hsc_dflags hsc_env))
- (map mi_module pluginModules) tc_result
- let hpc_info = emptyHpcInfo other_hpc_info
- used_th <- readIORef tc_splice_used
- dep_files <- (readIORef dependent_files)
- -- Do NOT use semantic module here; this_mod in mkUsageInfo
- -- is used solely to decide if we should record a dependency
- -- or not. When we instantiate a signature, the semantic
- -- module is something we want to record dependencies for,
- -- but if you pass that in here, we'll decide it's the local
- -- module and does not need to be recorded as a dependency.
- -- See Note [Identity versus semantic module]
- usages <- mkUsageInfo hsc_env this_mod (imp_mods imports) used_names
- dep_files merged pluginModules
-
- let (doc_hdr', doc_map, arg_map) = extractDocs tc_result
-
- let partial_iface = mkIface_ hsc_env
- this_mod hsc_src
- used_th deps rdr_env
- fix_env warns hpc_info
- (imp_trust_own_pkg imports) safe_mode usages
- doc_hdr' doc_map arg_map
- mod_details
-
- mkFullIface hsc_env partial_iface
-
-mkIface_ :: HscEnv -> Module -> HscSource
- -> Bool -> Dependencies -> GlobalRdrEnv
- -> NameEnv FixItem -> Warnings -> HpcInfo
- -> Bool
- -> SafeHaskellMode
- -> [Usage]
- -> Maybe HsDocString
- -> DeclDocMap
- -> ArgDocMap
- -> ModDetails
- -> PartialModIface
-mkIface_ hsc_env
- this_mod hsc_src used_th deps rdr_env fix_env src_warns
- hpc_info pkg_trust_req safe_mode usages
- doc_hdr decl_docs arg_docs
- ModDetails{ md_insts = insts,
- md_fam_insts = fam_insts,
- md_rules = rules,
- md_anns = anns,
- md_types = type_env,
- md_exports = exports,
- md_complete_sigs = complete_sigs }
--- NB: notice that mkIface does not look at the bindings
--- only at the TypeEnv. The previous Tidy phase has
--- put exactly the info into the TypeEnv that we want
--- to expose in the interface
-
- = do
- let semantic_mod = canonicalizeHomeModule (hsc_dflags hsc_env) (moduleName this_mod)
- entities = typeEnvElts type_env
- decls = [ tyThingToIfaceDecl entity
- | entity <- entities,
- let name = getName entity,
- not (isImplicitTyThing entity),
- -- No implicit Ids and class tycons in the interface file
- not (isWiredInName name),
- -- Nor wired-in things; the compiler knows about them anyhow
- nameIsLocalOrFrom semantic_mod name ]
- -- Sigh: see Note [Root-main Id] in TcRnDriver
- -- NB: ABSOLUTELY need to check against semantic_mod,
- -- because all of the names in an hsig p[H=<H>]:H
- -- are going to be for <H>, not the former id!
- -- See Note [Identity versus semantic module]
-
- fixities = sortBy (comparing fst)
- [(occ,fix) | FixItem occ fix <- nameEnvElts fix_env]
- -- The order of fixities returned from nameEnvElts is not
- -- deterministic, so we sort by OccName to canonicalize it.
- -- See Note [Deterministic UniqFM] in UniqDFM for more details.
- warns = src_warns
- iface_rules = map coreRuleToIfaceRule rules
- iface_insts = map instanceToIfaceInst $ fixSafeInstances safe_mode insts
- iface_fam_insts = map famInstToIfaceFamInst fam_insts
- trust_info = setSafeMode safe_mode
- annotations = map mkIfaceAnnotation anns
- icomplete_sigs = map mkIfaceCompleteSig complete_sigs
-
- ModIface {
- mi_module = this_mod,
- -- Need to record this because it depends on the -instantiated-with flag
- -- which could change
- mi_sig_of = if semantic_mod == this_mod
- then Nothing
- else Just semantic_mod,
- mi_hsc_src = hsc_src,
- mi_deps = deps,
- mi_usages = usages,
- mi_exports = mkIfaceExports exports,
-
- -- Sort these lexicographically, so that
- -- the result is stable across compilations
- mi_insts = sortBy cmp_inst iface_insts,
- mi_fam_insts = sortBy cmp_fam_inst iface_fam_insts,
- mi_rules = sortBy cmp_rule iface_rules,
-
- mi_fixities = fixities,
- mi_warns = warns,
- mi_anns = annotations,
- mi_globals = maybeGlobalRdrEnv rdr_env,
- mi_used_th = used_th,
- mi_decls = decls,
- mi_hpc = isHpcUsed hpc_info,
- mi_trust = trust_info,
- mi_trust_pkg = pkg_trust_req,
- mi_complete_sigs = icomplete_sigs,
- mi_doc_hdr = doc_hdr,
- mi_decl_docs = decl_docs,
- mi_arg_docs = arg_docs,
- mi_final_exts = () }
- where
- cmp_rule = comparing ifRuleName
- -- Compare these lexicographically by OccName, *not* by unique,
- -- because the latter is not stable across compilations:
- cmp_inst = comparing (nameOccName . ifDFun)
- cmp_fam_inst = comparing (nameOccName . ifFamInstTcName)
-
- dflags = hsc_dflags hsc_env
-
- -- We only fill in mi_globals if the module was compiled to byte
- -- code. Otherwise, the compiler may not have retained all the
- -- top-level bindings and they won't be in the TypeEnv (see
- -- Desugar.addExportFlagsAndRules). The mi_globals field is used
- -- by GHCi to decide whether the module has its full top-level
- -- scope available. (#5534)
- maybeGlobalRdrEnv :: GlobalRdrEnv -> Maybe GlobalRdrEnv
- maybeGlobalRdrEnv rdr_env
- | targetRetainsAllBindings (hscTarget dflags) = Just rdr_env
- | otherwise = Nothing
-
- ifFamInstTcName = ifFamInstFam
-
------------------------------
-writeIfaceFile :: DynFlags -> FilePath -> ModIface -> IO ()
-writeIfaceFile dflags hi_file_path new_iface
- = do createDirectoryIfMissing True (takeDirectory hi_file_path)
- writeBinIface dflags hi_file_path new_iface
-
-
--- -----------------------------------------------------------------------------
--- Look up parents and versions of Names
-
--- This is like a global version of the mi_hash_fn field in each ModIface.
--- Given a Name, it finds the ModIface, and then uses mi_hash_fn to get
--- the parent and version info.
-
-mkHashFun
- :: HscEnv -- needed to look up versions
- -> ExternalPackageState -- ditto
- -> (Name -> IO Fingerprint)
-mkHashFun hsc_env eps name
- | isHoleModule orig_mod
- = lookup (mkModule (thisPackage dflags) (moduleName orig_mod))
- | otherwise
- = lookup orig_mod
- where
- dflags = hsc_dflags hsc_env
- hpt = hsc_HPT hsc_env
- pit = eps_PIT eps
- occ = nameOccName name
- orig_mod = nameModule name
- lookup mod = do
- MASSERT2( isExternalName name, ppr name )
- iface <- case lookupIfaceByModule hpt pit mod of
- Just iface -> return iface
- Nothing -> do
- -- This can occur when we're writing out ifaces for
- -- requirements; we didn't do any /real/ typechecking
- -- so there's no guarantee everything is loaded.
- -- Kind of a heinous hack.
- iface <- initIfaceLoad hsc_env . withException
- $ loadInterface (text "lookupVers2") mod ImportBySystem
- return iface
- return $ snd (mi_hash_fn (mi_final_exts iface) occ `orElse`
- pprPanic "lookupVers1" (ppr mod <+> ppr occ))
-
--- ---------------------------------------------------------------------------
--- Compute fingerprints for the interface
-
-{-
-Note [Fingerprinting IfaceDecls]
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-The general idea here is that we first examine the 'IfaceDecl's and determine
-the recursive groups of them. We then walk these groups in dependency order,
-serializing each contained 'IfaceDecl' to a "Binary" buffer which we then
-hash using MD5 to produce a fingerprint for the group.
-
-However, the serialization that we use is a bit funny: we override the @putName@
-operation with our own which serializes the hash of a 'Name' instead of the
-'Name' itself. This ensures that the fingerprint of a decl changes if anything
-in its transitive closure changes. This trick is why we must be careful about
-traversing in dependency order: we need to ensure that we have hashes for
-everything referenced by the decl which we are fingerprinting.
-
-Moreover, we need to be careful to distinguish between serialization of binding
-Names (e.g. the ifName field of a IfaceDecl) and non-binding (e.g. the ifInstCls
-field of a IfaceClsInst): only in the non-binding case should we include the
-fingerprint; in the binding case we shouldn't since it is merely the name of the
-thing that we are currently fingerprinting.
--}
-
--- | Add fingerprints for top-level declarations to a 'ModIface'.
---
--- See Note [Fingerprinting IfaceDecls]
-addFingerprints
- :: HscEnv
- -> PartialModIface
- -> IO ModIface
-addFingerprints hsc_env iface0
- = do
- eps <- hscEPS hsc_env
- let
- decls = mi_decls iface0
- warn_fn = mkIfaceWarnCache (mi_warns iface0)
- fix_fn = mkIfaceFixCache (mi_fixities iface0)
-
- -- The ABI of a declaration represents everything that is made
- -- visible about the declaration that a client can depend on.
- -- see IfaceDeclABI below.
- declABI :: IfaceDecl -> IfaceDeclABI
- -- TODO: I'm not sure if this should be semantic_mod or this_mod.
- -- See also Note [Identity versus semantic module]
- declABI decl = (this_mod, decl, extras)
- where extras = declExtras fix_fn ann_fn non_orph_rules non_orph_insts
- non_orph_fis top_lvl_name_env decl
-
- -- This is used for looking up the Name of a default method
- -- from its OccName. See Note [default method Name]
- top_lvl_name_env =
- mkOccEnv [ (nameOccName nm, nm)
- | IfaceId { ifName = nm } <- decls ]
-
- -- Dependency edges between declarations in the current module.
- -- This is computed by finding the free external names of each
- -- declaration, including IfaceDeclExtras (things that a
- -- declaration implicitly depends on).
- edges :: [ Node Unique IfaceDeclABI ]
- edges = [ DigraphNode abi (getUnique (getOccName decl)) out
- | decl <- decls
- , let abi = declABI decl
- , let out = localOccs $ freeNamesDeclABI abi
- ]
-
- name_module n = ASSERT2( isExternalName n, ppr n ) nameModule n
- localOccs =
- map (getUnique . getParent . getOccName)
- -- NB: names always use semantic module, so
- -- filtering must be on the semantic module!
- -- See Note [Identity versus semantic module]
- . filter ((== semantic_mod) . name_module)
- . nonDetEltsUniqSet
- -- It's OK to use nonDetEltsUFM as localOccs is only
- -- used to construct the edges and
- -- stronglyConnCompFromEdgedVertices is deterministic
- -- even with non-deterministic order of edges as
- -- explained in Note [Deterministic SCC] in Digraph.
- where getParent :: OccName -> OccName
- getParent occ = lookupOccEnv parent_map occ `orElse` occ
-
- -- maps OccNames to their parents in the current module.
- -- e.g. a reference to a constructor must be turned into a reference
- -- to the TyCon for the purposes of calculating dependencies.
- parent_map :: OccEnv OccName
- parent_map = foldl' extend emptyOccEnv decls
- where extend env d =
- extendOccEnvList env [ (b,n) | b <- ifaceDeclImplicitBndrs d ]
- where n = getOccName d
-
- -- Strongly-connected groups of declarations, in dependency order
- groups :: [SCC IfaceDeclABI]
- groups = stronglyConnCompFromEdgedVerticesUniq edges
-
- global_hash_fn = mkHashFun hsc_env eps
-
- -- How to output Names when generating the data to fingerprint.
- -- Here we want to output the fingerprint for each top-level
- -- Name, whether it comes from the current module or another
- -- module. In this way, the fingerprint for a declaration will
- -- change if the fingerprint for anything it refers to (transitively)
- -- changes.
- mk_put_name :: OccEnv (OccName,Fingerprint)
- -> BinHandle -> Name -> IO ()
- mk_put_name local_env bh name
- | isWiredInName name = putNameLiterally bh name
- -- wired-in names don't have fingerprints
- | otherwise
- = ASSERT2( isExternalName name, ppr name )
- let hash | nameModule name /= semantic_mod = global_hash_fn name
- -- Get it from the REAL interface!!
- -- This will trigger when we compile an hsig file
- -- and we know a backing impl for it.
- -- See Note [Identity versus semantic module]
- | semantic_mod /= this_mod
- , not (isHoleModule semantic_mod) = global_hash_fn name
- | otherwise = return (snd (lookupOccEnv local_env (getOccName name)
- `orElse` pprPanic "urk! lookup local fingerprint"
- (ppr name $$ ppr local_env)))
- -- This panic indicates that we got the dependency
- -- analysis wrong, because we needed a fingerprint for
- -- an entity that wasn't in the environment. To debug
- -- it, turn the panic into a trace, uncomment the
- -- pprTraces below, run the compile again, and inspect
- -- the output and the generated .hi file with
- -- --show-iface.
- in hash >>= put_ bh
-
- -- take a strongly-connected group of declarations and compute
- -- its fingerprint.
-
- fingerprint_group :: (OccEnv (OccName,Fingerprint),
- [(Fingerprint,IfaceDecl)])
- -> SCC IfaceDeclABI
- -> IO (OccEnv (OccName,Fingerprint),
- [(Fingerprint,IfaceDecl)])
-
- fingerprint_group (local_env, decls_w_hashes) (AcyclicSCC abi)
- = do let hash_fn = mk_put_name local_env
- decl = abiDecl abi
- --pprTrace "fingerprinting" (ppr (ifName decl) ) $ do
- hash <- computeFingerprint hash_fn abi
- env' <- extend_hash_env local_env (hash,decl)
- return (env', (hash,decl) : decls_w_hashes)
-
- fingerprint_group (local_env, decls_w_hashes) (CyclicSCC abis)
- = do let decls = map abiDecl abis
- local_env1 <- foldM extend_hash_env local_env
- (zip (repeat fingerprint0) decls)
- let hash_fn = mk_put_name local_env1
- -- pprTrace "fingerprinting" (ppr (map ifName decls) ) $ do
- let stable_abis = sortBy cmp_abiNames abis
- -- put the cycle in a canonical order
- hash <- computeFingerprint hash_fn stable_abis
- let pairs = zip (repeat hash) decls
- local_env2 <- foldM extend_hash_env local_env pairs
- return (local_env2, pairs ++ decls_w_hashes)
-
- -- we have fingerprinted the whole declaration, but we now need
- -- to assign fingerprints to all the OccNames that it binds, to
- -- use when referencing those OccNames in later declarations.
- --
- extend_hash_env :: OccEnv (OccName,Fingerprint)
- -> (Fingerprint,IfaceDecl)
- -> IO (OccEnv (OccName,Fingerprint))
- extend_hash_env env0 (hash,d) = do
- return (foldr (\(b,fp) env -> extendOccEnv env b (b,fp)) env0
- (ifaceDeclFingerprints hash d))
-
- --
- (local_env, decls_w_hashes) <-
- foldM fingerprint_group (emptyOccEnv, []) groups
-
- -- when calculating fingerprints, we always need to use canonical
- -- ordering for lists of things. In particular, the mi_deps has various
- -- lists of modules and suchlike, so put these all in canonical order:
- let sorted_deps = sortDependencies (mi_deps iface0)
-
- -- The export hash of a module depends on the orphan hashes of the
- -- orphan modules below us in the dependency tree. This is the way
- -- that changes in orphans get propagated all the way up the
- -- dependency tree.
- --
- -- Note [A bad dep_orphs optimization]
- -- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- -- In a previous version of this code, we filtered out orphan modules which
- -- were not from the home package, justifying it by saying that "we'd
- -- pick up the ABI hashes of the external module instead". This is wrong.
- -- Suppose that we have:
- --
- -- module External where
- -- instance Show (a -> b)
- --
- -- module Home1 where
- -- import External
- --
- -- module Home2 where
- -- import Home1
- --
- -- The export hash of Home1 needs to reflect the orphan instances of
- -- External. It's true that Home1 will get rebuilt if the orphans
- -- of External, but we also need to make sure Home2 gets rebuilt
- -- as well. See #12733 for more details.
- let orph_mods
- = filter (/= this_mod) -- Note [Do not update EPS with your own hi-boot]
- $ dep_orphs sorted_deps
- dep_orphan_hashes <- getOrphanHashes hsc_env orph_mods
-
- -- Note [Do not update EPS with your own hi-boot]
- -- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- -- (See also #10182). When your hs-boot file includes an orphan
- -- instance declaration, you may find that the dep_orphs of a module you
- -- import contains reference to yourself. DO NOT actually load this module
- -- or add it to the orphan hashes: you're going to provide the orphan
- -- instances yourself, no need to consult hs-boot; if you do load the
- -- interface into EPS, you will see a duplicate orphan instance.
-
- orphan_hash <- computeFingerprint (mk_put_name local_env)
- (map ifDFun orph_insts, orph_rules, orph_fis)
-
- -- the export list hash doesn't depend on the fingerprints of
- -- the Names it mentions, only the Names themselves, hence putNameLiterally.
- export_hash <- computeFingerprint putNameLiterally
- (mi_exports iface0,
- orphan_hash,
- dep_orphan_hashes,
- dep_pkgs (mi_deps iface0),
- -- See Note [Export hash depends on non-orphan family instances]
- dep_finsts (mi_deps iface0),
- -- dep_pkgs: see "Package Version Changes" on
- -- wiki/commentary/compiler/recompilation-avoidance
- mi_trust iface0)
- -- Make sure change of Safe Haskell mode causes recomp.
-
- -- Note [Export hash depends on non-orphan family instances]
- -- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- --
- -- Suppose we have:
- --
- -- module A where
- -- type instance F Int = Bool
- --
- -- module B where
- -- import A
- --
- -- module C where
- -- import B
- --
- -- The family instance consistency check for C depends on the dep_finsts of
- -- B. If we rename module A to A2, when the dep_finsts of B changes, we need
- -- to make sure that C gets rebuilt. Effectively, the dep_finsts are part of
- -- the exports of B, because C always considers them when checking
- -- consistency.
- --
- -- A full discussion is in #12723.
- --
- -- We do NOT need to hash dep_orphs, because this is implied by
- -- dep_orphan_hashes, and we do not need to hash ordinary class instances,
- -- because there is no eager consistency check as there is with type families
- -- (also we didn't store it anywhere!)
- --
-
- -- put the declarations in a canonical order, sorted by OccName
- let sorted_decls = Map.elems $ Map.fromList $
- [(getOccName d, e) | e@(_, d) <- decls_w_hashes]
-
- -- the flag hash depends on:
- -- - (some of) dflags
- -- it returns two hashes, one that shouldn't change
- -- the abi hash and one that should
- flag_hash <- fingerprintDynFlags dflags this_mod putNameLiterally
-
- opt_hash <- fingerprintOptFlags dflags putNameLiterally
-
- hpc_hash <- fingerprintHpcFlags dflags putNameLiterally
-
- plugin_hash <- fingerprintPlugins hsc_env
-
- -- the ABI hash depends on:
- -- - decls
- -- - export list
- -- - orphans
- -- - deprecations
- -- - flag abi hash
- mod_hash <- computeFingerprint putNameLiterally
- (map fst sorted_decls,
- export_hash, -- includes orphan_hash
- mi_warns iface0)
-
- -- The interface hash depends on:
- -- - the ABI hash, plus
- -- - the module level annotations,
- -- - usages
- -- - deps (home and external packages, dependent files)
- -- - hpc
- iface_hash <- computeFingerprint putNameLiterally
- (mod_hash,
- ann_fn (mkVarOcc "module"), -- See mkIfaceAnnCache
- mi_usages iface0,
- sorted_deps,
- mi_hpc iface0)
-
- let
- final_iface_exts = ModIfaceBackend
- { mi_iface_hash = iface_hash
- , mi_mod_hash = mod_hash
- , mi_flag_hash = flag_hash
- , mi_opt_hash = opt_hash
- , mi_hpc_hash = hpc_hash
- , mi_plugin_hash = plugin_hash
- , mi_orphan = not ( all ifRuleAuto orph_rules
- -- See Note [Orphans and auto-generated rules]
- && null orph_insts
- && null orph_fis)
- , mi_finsts = not (null (mi_fam_insts iface0))
- , mi_exp_hash = export_hash
- , mi_orphan_hash = orphan_hash
- , mi_warn_fn = warn_fn
- , mi_fix_fn = fix_fn
- , mi_hash_fn = lookupOccEnv local_env
- }
- final_iface = iface0 { mi_decls = sorted_decls, mi_final_exts = final_iface_exts }
- --
- return final_iface
-
- where
- this_mod = mi_module iface0
- semantic_mod = mi_semantic_module iface0
- dflags = hsc_dflags hsc_env
- (non_orph_insts, orph_insts) = mkOrphMap ifInstOrph (mi_insts iface0)
- (non_orph_rules, orph_rules) = mkOrphMap ifRuleOrph (mi_rules iface0)
- (non_orph_fis, orph_fis) = mkOrphMap ifFamInstOrph (mi_fam_insts iface0)
- ann_fn = mkIfaceAnnCache (mi_anns iface0)
-
--- | Retrieve the orphan hashes 'mi_orphan_hash' for a list of modules
--- (in particular, the orphan modules which are transitively imported by the
--- current module).
---
--- Q: Why do we need the hash at all, doesn't the list of transitively
--- imported orphan modules suffice?
---
--- A: If one of our transitive imports adds a new orphan instance, our
--- export hash must change so that modules which import us rebuild. If we just
--- hashed the [Module], the hash would not change even when a new instance was
--- added to a module that already had an orphan instance.
---
--- Q: Why don't we just hash the orphan hashes of our direct dependencies?
--- Why the full transitive closure?
---
--- A: Suppose we have these modules:
---
--- module A where
--- instance Show (a -> b) where
--- module B where
--- import A -- **
--- module C where
--- import A
--- import B
---
--- Whether or not we add or remove the import to A in B affects the
--- orphan hash of B. But it shouldn't really affect the orphan hash
--- of C. If we hashed only direct dependencies, there would be no
--- way to tell that the net effect was a wash, and we'd be forced
--- to recompile C and everything else.
-getOrphanHashes :: HscEnv -> [Module] -> IO [Fingerprint]
-getOrphanHashes hsc_env mods = do
- eps <- hscEPS hsc_env
- let
- hpt = hsc_HPT hsc_env
- pit = eps_PIT eps
- get_orph_hash mod =
- case lookupIfaceByModule hpt pit mod of
- Just iface -> return (mi_orphan_hash (mi_final_exts iface))
- Nothing -> do -- similar to 'mkHashFun'
- iface <- initIfaceLoad hsc_env . withException
- $ loadInterface (text "getOrphanHashes") mod ImportBySystem
- return (mi_orphan_hash (mi_final_exts iface))
-
- --
- mapM get_orph_hash mods
-
-
-sortDependencies :: Dependencies -> Dependencies
-sortDependencies d
- = Deps { dep_mods = sortBy (compare `on` (moduleNameFS.fst)) (dep_mods d),
- dep_pkgs = sortBy (compare `on` fst) (dep_pkgs d),
- dep_orphs = sortBy stableModuleCmp (dep_orphs d),
- dep_finsts = sortBy stableModuleCmp (dep_finsts d),
- dep_plgins = sortBy (compare `on` moduleNameFS) (dep_plgins d) }
-
--- | Creates cached lookup for the 'mi_anns' field of ModIface
--- Hackily, we use "module" as the OccName for any module-level annotations
-mkIfaceAnnCache :: [IfaceAnnotation] -> OccName -> [AnnPayload]
-mkIfaceAnnCache anns
- = \n -> lookupOccEnv env n `orElse` []
- where
- pair (IfaceAnnotation target value) =
- (case target of
- NamedTarget occn -> occn
- ModuleTarget _ -> mkVarOcc "module"
- , [value])
- -- flipping (++), so the first argument is always short
- env = mkOccEnv_C (flip (++)) (map pair anns)
-
-{-
-************************************************************************
-* *
- The ABI of an IfaceDecl
-* *
-************************************************************************
-
-Note [The ABI of an IfaceDecl]
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-The ABI of a declaration consists of:
-
- (a) the full name of the identifier (inc. module and package,
- because these are used to construct the symbol name by which
- the identifier is known externally).
-
- (b) the declaration itself, as exposed to clients. That is, the
- definition of an Id is included in the fingerprint only if
- it is made available as an unfolding in the interface.
-
- (c) the fixity of the identifier (if it exists)
- (d) for Ids: rules
- (e) for classes: instances, fixity & rules for methods
- (f) for datatypes: instances, fixity & rules for constrs
-
-Items (c)-(f) are not stored in the IfaceDecl, but instead appear
-elsewhere in the interface file. But they are *fingerprinted* with
-the declaration itself. This is done by grouping (c)-(f) in IfaceDeclExtras,
-and fingerprinting that as part of the declaration.
--}
-
-type IfaceDeclABI = (Module, IfaceDecl, IfaceDeclExtras)
-
-data IfaceDeclExtras
- = IfaceIdExtras IfaceIdExtras
-
- | IfaceDataExtras
- (Maybe Fixity) -- Fixity of the tycon itself (if it exists)
- [IfaceInstABI] -- Local class and family instances of this tycon
- -- See Note [Orphans] in InstEnv
- [AnnPayload] -- Annotations of the type itself
- [IfaceIdExtras] -- For each constructor: fixity, RULES and annotations
-
- | IfaceClassExtras
- (Maybe Fixity) -- Fixity of the class itself (if it exists)
- [IfaceInstABI] -- Local instances of this class *or*
- -- of its associated data types
- -- See Note [Orphans] in InstEnv
- [AnnPayload] -- Annotations of the type itself
- [IfaceIdExtras] -- For each class method: fixity, RULES and annotations
- [IfExtName] -- Default methods. If a module
- -- mentions a class, then it can
- -- instantiate the class and thereby
- -- use the default methods, so we must
- -- include these in the fingerprint of
- -- a class.
-
- | IfaceSynonymExtras (Maybe Fixity) [AnnPayload]
-
- | IfaceFamilyExtras (Maybe Fixity) [IfaceInstABI] [AnnPayload]
-
- | IfaceOtherDeclExtras
-
-data IfaceIdExtras
- = IdExtras
- (Maybe Fixity) -- Fixity of the Id (if it exists)
- [IfaceRule] -- Rules for the Id
- [AnnPayload] -- Annotations for the Id
-
--- When hashing a class or family instance, we hash only the
--- DFunId or CoAxiom, because that depends on all the
--- information about the instance.
---
-type IfaceInstABI = IfExtName -- Name of DFunId or CoAxiom that is evidence for the instance
-
-abiDecl :: IfaceDeclABI -> IfaceDecl
-abiDecl (_, decl, _) = decl
-
-cmp_abiNames :: IfaceDeclABI -> IfaceDeclABI -> Ordering
-cmp_abiNames abi1 abi2 = getOccName (abiDecl abi1) `compare`
- getOccName (abiDecl abi2)
-
-freeNamesDeclABI :: IfaceDeclABI -> NameSet
-freeNamesDeclABI (_mod, decl, extras) =
- freeNamesIfDecl decl `unionNameSet` freeNamesDeclExtras extras
-
-freeNamesDeclExtras :: IfaceDeclExtras -> NameSet
-freeNamesDeclExtras (IfaceIdExtras id_extras)
- = freeNamesIdExtras id_extras
-freeNamesDeclExtras (IfaceDataExtras _ insts _ subs)
- = unionNameSets (mkNameSet insts : map freeNamesIdExtras subs)
-freeNamesDeclExtras (IfaceClassExtras _ insts _ subs defms)
- = unionNameSets $
- mkNameSet insts : mkNameSet defms : map freeNamesIdExtras subs
-freeNamesDeclExtras (IfaceSynonymExtras _ _)
- = emptyNameSet
-freeNamesDeclExtras (IfaceFamilyExtras _ insts _)
- = mkNameSet insts
-freeNamesDeclExtras IfaceOtherDeclExtras
- = emptyNameSet
-
-freeNamesIdExtras :: IfaceIdExtras -> NameSet
-freeNamesIdExtras (IdExtras _ rules _) = unionNameSets (map freeNamesIfRule rules)
-
-instance Outputable IfaceDeclExtras where
- ppr IfaceOtherDeclExtras = Outputable.empty
- ppr (IfaceIdExtras extras) = ppr_id_extras extras
- ppr (IfaceSynonymExtras fix anns) = vcat [ppr fix, ppr anns]
- ppr (IfaceFamilyExtras fix finsts anns) = vcat [ppr fix, ppr finsts, ppr anns]
- ppr (IfaceDataExtras fix insts anns stuff) = vcat [ppr fix, ppr_insts insts, ppr anns,
- ppr_id_extras_s stuff]
- ppr (IfaceClassExtras fix insts anns stuff defms) =
- vcat [ppr fix, ppr_insts insts, ppr anns,
- ppr_id_extras_s stuff, ppr defms]
-
-ppr_insts :: [IfaceInstABI] -> SDoc
-ppr_insts _ = text "<insts>"
-
-ppr_id_extras_s :: [IfaceIdExtras] -> SDoc
-ppr_id_extras_s stuff = vcat (map ppr_id_extras stuff)
-
-ppr_id_extras :: IfaceIdExtras -> SDoc
-ppr_id_extras (IdExtras fix rules anns) = ppr fix $$ vcat (map ppr rules) $$ vcat (map ppr anns)
-
--- This instance is used only to compute fingerprints
-instance Binary IfaceDeclExtras where
- get _bh = panic "no get for IfaceDeclExtras"
- put_ bh (IfaceIdExtras extras) = do
- putByte bh 1; put_ bh extras
- put_ bh (IfaceDataExtras fix insts anns cons) = do
- putByte bh 2; put_ bh fix; put_ bh insts; put_ bh anns; put_ bh cons
- put_ bh (IfaceClassExtras fix insts anns methods defms) = do
- putByte bh 3
- put_ bh fix
- put_ bh insts
- put_ bh anns
- put_ bh methods
- put_ bh defms
- put_ bh (IfaceSynonymExtras fix anns) = do
- putByte bh 4; put_ bh fix; put_ bh anns
- put_ bh (IfaceFamilyExtras fix finsts anns) = do
- putByte bh 5; put_ bh fix; put_ bh finsts; put_ bh anns
- put_ bh IfaceOtherDeclExtras = putByte bh 6
-
-instance Binary IfaceIdExtras where
- get _bh = panic "no get for IfaceIdExtras"
- put_ bh (IdExtras fix rules anns)= do { put_ bh fix; put_ bh rules; put_ bh anns }
-
-declExtras :: (OccName -> Maybe Fixity)
- -> (OccName -> [AnnPayload])
- -> OccEnv [IfaceRule]
- -> OccEnv [IfaceClsInst]
- -> OccEnv [IfaceFamInst]
- -> OccEnv IfExtName -- lookup default method names
- -> IfaceDecl
- -> IfaceDeclExtras
-
-declExtras fix_fn ann_fn rule_env inst_env fi_env dm_env decl
- = case decl of
- IfaceId{} -> IfaceIdExtras (id_extras n)
- IfaceData{ifCons=cons} ->
- IfaceDataExtras (fix_fn n)
- (map ifFamInstAxiom (lookupOccEnvL fi_env n) ++
- map ifDFun (lookupOccEnvL inst_env n))
- (ann_fn n)
- (map (id_extras . occName . ifConName) (visibleIfConDecls cons))
- IfaceClass{ifBody = IfConcreteClass { ifSigs=sigs, ifATs=ats }} ->
- IfaceClassExtras (fix_fn n) insts (ann_fn n) meths defms
- where
- insts = (map ifDFun $ (concatMap at_extras ats)
- ++ lookupOccEnvL inst_env n)
- -- Include instances of the associated types
- -- as well as instances of the class (#5147)
- meths = [id_extras (getOccName op) | IfaceClassOp op _ _ <- sigs]
- -- Names of all the default methods (see Note [default method Name])
- defms = [ dmName
- | IfaceClassOp bndr _ (Just _) <- sigs
- , let dmOcc = mkDefaultMethodOcc (nameOccName bndr)
- , Just dmName <- [lookupOccEnv dm_env dmOcc] ]
- IfaceSynonym{} -> IfaceSynonymExtras (fix_fn n)
- (ann_fn n)
- IfaceFamily{} -> IfaceFamilyExtras (fix_fn n)
- (map ifFamInstAxiom (lookupOccEnvL fi_env n))
- (ann_fn n)
- _other -> IfaceOtherDeclExtras
- where
- n = getOccName decl
- id_extras occ = IdExtras (fix_fn occ) (lookupOccEnvL rule_env occ) (ann_fn occ)
- at_extras (IfaceAT decl _) = lookupOccEnvL inst_env (getOccName decl)
-
-
-{- Note [default method Name] (see also #15970)
-
-The Names for the default methods aren't available in the IfaceSyn.
-
-* We originally start with a DefMethInfo from the class, contain a
- Name for the default method
-
-* We turn that into IfaceSyn as a DefMethSpec which lacks a Name
- entirely. Why? Because the Name can be derived from the method name
- (in TcIface), so doesn't need to be serialised into the interface
- file.
-
-But now we have to get the Name back, because the class declaration's
-fingerprint needs to depend on it (this was the bug in #15970). This
-is done in a slightly convoluted way:
-
-* Then, in addFingerprints we build a map that maps OccNames to Names
-
-* We pass that map to declExtras which laboriously looks up in the map
- (using the derived occurrence name) to recover the Name we have just
- thrown away.
--}
-
-lookupOccEnvL :: OccEnv [v] -> OccName -> [v]
-lookupOccEnvL env k = lookupOccEnv env k `orElse` []
-
-{-
--- for testing: use the md5sum command to generate fingerprints and
--- compare the results against our built-in version.
- fp' <- oldMD5 dflags bh
- if fp /= fp' then pprPanic "computeFingerprint" (ppr fp <+> ppr fp')
- else return fp
-
-oldMD5 dflags bh = do
- tmp <- newTempName dflags CurrentModule "bin"
- writeBinMem bh tmp
- tmp2 <- newTempName dflags CurrentModule "md5"
- let cmd = "md5sum " ++ tmp ++ " >" ++ tmp2
- r <- system cmd
- case r of
- ExitFailure _ -> throwGhcExceptionIO (PhaseFailed cmd r)
- ExitSuccess -> do
- hash_str <- readFile tmp2
- return $! readHexFingerprint hash_str
--}
-
-----------------------
--- mkOrphMap partitions instance decls or rules into
--- (a) an OccEnv for ones that are not orphans,
--- mapping the local OccName to a list of its decls
--- (b) a list of orphan decls
-mkOrphMap :: (decl -> IsOrphan) -- Extract orphan status from decl
- -> [decl] -- Sorted into canonical order
- -> (OccEnv [decl], -- Non-orphan decls associated with their key;
- -- each sublist in canonical order
- [decl]) -- Orphan decls; in canonical order
-mkOrphMap get_key decls
- = foldl' go (emptyOccEnv, []) decls
- where
- go (non_orphs, orphs) d
- | NotOrphan occ <- get_key d
- = (extendOccEnv_Acc (:) singleton non_orphs occ d, orphs)
- | otherwise = (non_orphs, d:orphs)
-
-{-
-************************************************************************
-* *
- COMPLETE Pragmas
-* *
-************************************************************************
--}
-
-mkIfaceCompleteSig :: CompleteMatch -> IfaceCompleteMatch
-mkIfaceCompleteSig (CompleteMatch cls tc) = IfaceCompleteMatch cls tc
-
-
-{-
-************************************************************************
-* *
- Keeping track of what we've slurped, and fingerprints
-* *
-************************************************************************
--}
-
-
-mkIfaceAnnotation :: Annotation -> IfaceAnnotation
-mkIfaceAnnotation (Annotation { ann_target = target, ann_value = payload })
- = IfaceAnnotation {
- ifAnnotatedTarget = fmap nameOccName target,
- ifAnnotatedValue = payload
- }
-
-mkIfaceExports :: [AvailInfo] -> [IfaceExport] -- Sort to make canonical
-mkIfaceExports exports
- = sortBy stableAvailCmp (map sort_subs exports)
- where
- sort_subs :: AvailInfo -> AvailInfo
- sort_subs (Avail n) = Avail n
- sort_subs (AvailTC n [] fs) = AvailTC n [] (sort_flds fs)
- sort_subs (AvailTC n (m:ms) fs)
- | n==m = AvailTC n (m:sortBy stableNameCmp ms) (sort_flds fs)
- | otherwise = AvailTC n (sortBy stableNameCmp (m:ms)) (sort_flds fs)
- -- Maintain the AvailTC Invariant
-
- sort_flds = sortBy (stableNameCmp `on` flSelector)
-
-{-
-Note [Original module]
-~~~~~~~~~~~~~~~~~~~~~
-Consider this:
- module X where { data family T }
- module Y( T(..) ) where { import X; data instance T Int = MkT Int }
-The exported Avail from Y will look like
- X.T{X.T, Y.MkT}
-That is, in Y,
- - only MkT is brought into scope by the data instance;
- - but the parent (used for grouping and naming in T(..) exports) is X.T
- - and in this case we export X.T too
-
-In the result of MkIfaceExports, the names are grouped by defining module,
-so we may need to split up a single Avail into multiple ones.
-
-Note [Internal used_names]
-~~~~~~~~~~~~~~~~~~~~~~~~~~
-Most of the used_names are External Names, but we can have Internal
-Names too: see Note [Binders in Template Haskell] in Convert, and
-#5362 for an example. Such Names are always
- - Such Names are always for locally-defined things, for which we
- don't gather usage info, so we can just ignore them in ent_map
- - They are always System Names, hence the assert, just as a double check.
-
-
-************************************************************************
-* *
- Load the old interface file for this module (unless
- we have it already), and check whether it is up to date
-* *
-************************************************************************
--}
-
-data RecompileRequired
- = UpToDate
- -- ^ everything is up to date, recompilation is not required
- | MustCompile
- -- ^ The .hs file has been touched, or the .o/.hi file does not exist
- | RecompBecause String
- -- ^ The .o/.hi files are up to date, but something else has changed
- -- to force recompilation; the String says what (one-line summary)
- deriving Eq
-
-instance Semigroup RecompileRequired where
- UpToDate <> r = r
- mc <> _ = mc
-
-instance Monoid RecompileRequired where
- mempty = UpToDate
-
-recompileRequired :: RecompileRequired -> Bool
-recompileRequired UpToDate = False
-recompileRequired _ = True
-
-
-
--- | Top level function to check if the version of an old interface file
--- is equivalent to the current source file the user asked us to compile.
--- If the same, we can avoid recompilation. We return a tuple where the
--- first element is a bool saying if we should recompile the object file
--- and the second is maybe the interface file, where Nothing means to
--- rebuild the interface file and not use the existing one.
-checkOldIface
- :: HscEnv
- -> ModSummary
- -> SourceModified
- -> Maybe ModIface -- Old interface from compilation manager, if any
- -> IO (RecompileRequired, Maybe ModIface)
-
-checkOldIface hsc_env mod_summary source_modified maybe_iface
- = do let dflags = hsc_dflags hsc_env
- showPass dflags $
- "Checking old interface for " ++
- (showPpr dflags $ ms_mod mod_summary) ++
- " (use -ddump-hi-diffs for more details)"
- initIfaceCheck (text "checkOldIface") hsc_env $
- check_old_iface hsc_env mod_summary source_modified maybe_iface
-
-check_old_iface
- :: HscEnv
- -> ModSummary
- -> SourceModified
- -> Maybe ModIface
- -> IfG (RecompileRequired, Maybe ModIface)
-
-check_old_iface hsc_env mod_summary src_modified maybe_iface
- = let dflags = hsc_dflags hsc_env
- getIface =
- case maybe_iface of
- Just _ -> do
- traceIf (text "We already have the old interface for" <+>
- ppr (ms_mod mod_summary))
- return maybe_iface
- Nothing -> loadIface
-
- loadIface = do
- let iface_path = msHiFilePath mod_summary
- read_result <- readIface (ms_mod mod_summary) iface_path
- case read_result of
- Failed err -> do
- traceIf (text "FYI: cannot read old interface file:" $$ nest 4 err)
- traceHiDiffs (text "Old interface file was invalid:" $$ nest 4 err)
- return Nothing
- Succeeded iface -> do
- traceIf (text "Read the interface file" <+> text iface_path)
- return $ Just iface
-
- src_changed
- | gopt Opt_ForceRecomp (hsc_dflags hsc_env) = True
- | SourceModified <- src_modified = True
- | otherwise = False
- in do
- when src_changed $
- traceHiDiffs (nest 4 $ text "Source file changed or recompilation check turned off")
-
- case src_changed of
- -- If the source has changed and we're in interactive mode,
- -- avoid reading an interface; just return the one we might
- -- have been supplied with.
- True | not (isObjectTarget $ hscTarget dflags) ->
- return (MustCompile, maybe_iface)
-
- -- Try and read the old interface for the current module
- -- from the .hi file left from the last time we compiled it
- True -> do
- maybe_iface' <- getIface
- return (MustCompile, maybe_iface')
-
- False -> do
- maybe_iface' <- getIface
- case maybe_iface' of
- -- We can't retrieve the iface
- Nothing -> return (MustCompile, Nothing)
-
- -- We have got the old iface; check its versions
- -- even in the SourceUnmodifiedAndStable case we
- -- should check versions because some packages
- -- might have changed or gone away.
- Just iface -> checkVersions hsc_env mod_summary iface
-
--- | Check if a module is still the same 'version'.
---
--- This function is called in the recompilation checker after we have
--- determined that the module M being checked hasn't had any changes
--- to its source file since we last compiled M. So at this point in general
--- two things may have changed that mean we should recompile M:
--- * The interface export by a dependency of M has changed.
--- * The compiler flags specified this time for M have changed
--- in a manner that is significant for recompilation.
--- We return not just if we should recompile the object file but also
--- if we should rebuild the interface file.
-checkVersions :: HscEnv
- -> ModSummary
- -> ModIface -- Old interface
- -> IfG (RecompileRequired, Maybe ModIface)
-checkVersions hsc_env mod_summary iface
- = do { traceHiDiffs (text "Considering whether compilation is required for" <+>
- ppr (mi_module iface) <> colon)
-
- -- readIface will have verified that the InstalledUnitId matches,
- -- but we ALSO must make sure the instantiation matches up. See
- -- test case bkpcabal04!
- ; if moduleUnitId (mi_module iface) /= thisPackage (hsc_dflags hsc_env)
- then return (RecompBecause "-this-unit-id changed", Nothing) else do {
- ; recomp <- checkFlagHash hsc_env iface
- ; if recompileRequired recomp then return (recomp, Nothing) else do {
- ; recomp <- checkOptimHash hsc_env iface
- ; if recompileRequired recomp then return (recomp, Nothing) else do {
- ; recomp <- checkHpcHash hsc_env iface
- ; if recompileRequired recomp then return (recomp, Nothing) else do {
- ; recomp <- checkMergedSignatures mod_summary iface
- ; if recompileRequired recomp then return (recomp, Nothing) else do {
- ; recomp <- checkHsig mod_summary iface
- ; if recompileRequired recomp then return (recomp, Nothing) else do {
- ; recomp <- checkHie mod_summary
- ; if recompileRequired recomp then return (recomp, Nothing) else do {
- ; recomp <- checkDependencies hsc_env mod_summary iface
- ; if recompileRequired recomp then return (recomp, Just iface) else do {
- ; recomp <- checkPlugins hsc_env iface
- ; if recompileRequired recomp then return (recomp, Nothing) else do {
-
-
- -- Source code unchanged and no errors yet... carry on
- --
- -- First put the dependent-module info, read from the old
- -- interface, into the envt, so that when we look for
- -- interfaces we look for the right one (.hi or .hi-boot)
- --
- -- It's just temporary because either the usage check will succeed
- -- (in which case we are done with this module) or it'll fail (in which
- -- case we'll compile the module from scratch anyhow).
- --
- -- We do this regardless of compilation mode, although in --make mode
- -- all the dependent modules should be in the HPT already, so it's
- -- quite redundant
- ; updateEps_ $ \eps -> eps { eps_is_boot = mod_deps }
- ; recomp <- checkList [checkModUsage this_pkg u | u <- mi_usages iface]
- ; return (recomp, Just iface)
- }}}}}}}}}}
- where
- this_pkg = thisPackage (hsc_dflags hsc_env)
- -- This is a bit of a hack really
- mod_deps :: ModuleNameEnv (ModuleName, IsBootInterface)
- mod_deps = mkModDeps (dep_mods (mi_deps iface))
-
--- | Check if any plugins are requesting recompilation
-checkPlugins :: HscEnv -> ModIface -> IfG RecompileRequired
-checkPlugins hsc iface = liftIO $ do
- new_fingerprint <- fingerprintPlugins hsc
- let old_fingerprint = mi_plugin_hash (mi_final_exts iface)
- pr <- mconcat <$> mapM pluginRecompile' (plugins (hsc_dflags hsc))
- return $
- pluginRecompileToRecompileRequired old_fingerprint new_fingerprint pr
-
-fingerprintPlugins :: HscEnv -> IO Fingerprint
-fingerprintPlugins hsc_env = do
- fingerprintPlugins' $ plugins (hsc_dflags hsc_env)
-
-fingerprintPlugins' :: [PluginWithArgs] -> IO Fingerprint
-fingerprintPlugins' plugins = do
- res <- mconcat <$> mapM pluginRecompile' plugins
- return $ case res of
- NoForceRecompile -> fingerprintString "NoForceRecompile"
- ForceRecompile -> fingerprintString "ForceRecompile"
- -- is the chance of collision worth worrying about?
- -- An alternative is to fingerprintFingerprints [fingerprintString
- -- "maybeRecompile", fp]
- (MaybeRecompile fp) -> fp
-
-
-pluginRecompileToRecompileRequired
- :: Fingerprint -> Fingerprint -> PluginRecompile -> RecompileRequired
-pluginRecompileToRecompileRequired old_fp new_fp pr
- | old_fp == new_fp =
- case pr of
- NoForceRecompile -> UpToDate
-
- -- we already checked the fingerprint above so a mismatch is not possible
- -- here, remember that: `fingerprint (MaybeRecomp x) == x`.
- MaybeRecompile _ -> UpToDate
-
- -- when we have an impure plugin in the stack we have to unconditionally
- -- recompile since it might integrate all sorts of crazy IO results into
- -- its compilation output.
- ForceRecompile -> RecompBecause "Impure plugin forced recompilation"
-
- | old_fp `elem` magic_fingerprints ||
- new_fp `elem` magic_fingerprints
- -- The fingerprints do not match either the old or new one is a magic
- -- fingerprint. This happens when non-pure plugins are added for the first
- -- time or when we go from one recompilation strategy to another: (force ->
- -- no-force, maybe-recomp -> no-force, no-force -> maybe-recomp etc.)
- --
- -- For example when we go from from ForceRecomp to NoForceRecomp
- -- recompilation is triggered since the old impure plugins could have
- -- changed the build output which is now back to normal.
- = RecompBecause "Plugins changed"
-
- | otherwise =
- let reason = "Plugin fingerprint changed" in
- case pr of
- -- even though a plugin is forcing recompilation the fingerprint changed
- -- which would cause recompilation anyways so we report the fingerprint
- -- change instead.
- ForceRecompile -> RecompBecause reason
-
- _ -> RecompBecause reason
-
- where
- magic_fingerprints =
- [ fingerprintString "NoForceRecompile"
- , fingerprintString "ForceRecompile"
- ]
-
-
--- | Check if an hsig file needs recompilation because its
--- implementing module has changed.
-checkHsig :: ModSummary -> ModIface -> IfG RecompileRequired
-checkHsig mod_summary iface = do
- dflags <- getDynFlags
- let outer_mod = ms_mod mod_summary
- inner_mod = canonicalizeHomeModule dflags (moduleName outer_mod)
- MASSERT( moduleUnitId outer_mod == thisPackage dflags )
- case inner_mod == mi_semantic_module iface of
- True -> up_to_date (text "implementing module unchanged")
- False -> return (RecompBecause "implementing module changed")
-
--- | Check if @.hie@ file is out of date or missing.
-checkHie :: ModSummary -> IfG RecompileRequired
-checkHie mod_summary = do
- dflags <- getDynFlags
- let hie_date_opt = ms_hie_date mod_summary
- hs_date = ms_hs_date mod_summary
- pure $ case gopt Opt_WriteHie dflags of
- False -> UpToDate
- True -> case hie_date_opt of
- Nothing -> RecompBecause "HIE file is missing"
- Just hie_date
- | hie_date < hs_date
- -> RecompBecause "HIE file is out of date"
- | otherwise
- -> UpToDate
-
--- | Check the flags haven't changed
-checkFlagHash :: HscEnv -> ModIface -> IfG RecompileRequired
-checkFlagHash hsc_env iface = do
- let old_hash = mi_flag_hash (mi_final_exts iface)
- new_hash <- liftIO $ fingerprintDynFlags (hsc_dflags hsc_env)
- (mi_module iface)
- putNameLiterally
- case old_hash == new_hash of
- True -> up_to_date (text "Module flags unchanged")
- False -> out_of_date_hash "flags changed"
- (text " Module flags have changed")
- old_hash new_hash
-
--- | Check the optimisation flags haven't changed
-checkOptimHash :: HscEnv -> ModIface -> IfG RecompileRequired
-checkOptimHash hsc_env iface = do
- let old_hash = mi_opt_hash (mi_final_exts iface)
- new_hash <- liftIO $ fingerprintOptFlags (hsc_dflags hsc_env)
- putNameLiterally
- if | old_hash == new_hash
- -> up_to_date (text "Optimisation flags unchanged")
- | gopt Opt_IgnoreOptimChanges (hsc_dflags hsc_env)
- -> up_to_date (text "Optimisation flags changed; ignoring")
- | otherwise
- -> out_of_date_hash "Optimisation flags changed"
- (text " Optimisation flags have changed")
- old_hash new_hash
-
--- | Check the HPC flags haven't changed
-checkHpcHash :: HscEnv -> ModIface -> IfG RecompileRequired
-checkHpcHash hsc_env iface = do
- let old_hash = mi_hpc_hash (mi_final_exts iface)
- new_hash <- liftIO $ fingerprintHpcFlags (hsc_dflags hsc_env)
- putNameLiterally
- if | old_hash == new_hash
- -> up_to_date (text "HPC flags unchanged")
- | gopt Opt_IgnoreHpcChanges (hsc_dflags hsc_env)
- -> up_to_date (text "HPC flags changed; ignoring")
- | otherwise
- -> out_of_date_hash "HPC flags changed"
- (text " HPC flags have changed")
- old_hash new_hash
-
--- Check that the set of signatures we are merging in match.
--- If the -unit-id flags change, this can change too.
-checkMergedSignatures :: ModSummary -> ModIface -> IfG RecompileRequired
-checkMergedSignatures mod_summary iface = do
- dflags <- getDynFlags
- let old_merged = sort [ mod | UsageMergedRequirement{ usg_mod = mod } <- mi_usages iface ]
- new_merged = case Map.lookup (ms_mod_name mod_summary)
- (requirementContext (pkgState dflags)) of
- Nothing -> []
- Just r -> sort $ map (indefModuleToModule dflags) r
- if old_merged == new_merged
- then up_to_date (text "signatures to merge in unchanged" $$ ppr new_merged)
- else return (RecompBecause "signatures to merge in changed")
-
--- If the direct imports of this module are resolved to targets that
--- are not among the dependencies of the previous interface file,
--- then we definitely need to recompile. This catches cases like
--- - an exposed package has been upgraded
--- - we are compiling with different package flags
--- - a home module that was shadowing a package module has been removed
--- - a new home module has been added that shadows a package module
--- See bug #1372.
---
--- In addition, we also check if the union of dependencies of the imported
--- modules has any difference to the previous set of dependencies. We would need
--- to recompile in that case also since the `mi_deps` field of ModIface needs
--- to be updated to match that information. This is one of the invariants
--- of interface files (see https://gitlab.haskell.org/ghc/ghc/wikis/commentary/compiler/recompilation-avoidance#interface-file-invariants).
--- See bug #16511.
---
--- Returns (RecompBecause <textual reason>) if recompilation is required.
-checkDependencies :: HscEnv -> ModSummary -> ModIface -> IfG RecompileRequired
-checkDependencies hsc_env summary iface
- = do
- checkList $
- [ checkList (map dep_missing (ms_imps summary ++ ms_srcimps summary))
- , do
- (recomp, mnames_seen) <- runUntilRecompRequired $ map
- checkForNewHomeDependency
- (ms_home_imps summary)
- case recomp of
- UpToDate -> do
- let
- seen_home_deps = Set.unions $ map Set.fromList mnames_seen
- checkIfAllOldHomeDependenciesAreSeen seen_home_deps
- _ -> return recomp]
- where
- prev_dep_mods = dep_mods (mi_deps iface)
- prev_dep_plgn = dep_plgins (mi_deps iface)
- prev_dep_pkgs = dep_pkgs (mi_deps iface)
-
- this_pkg = thisPackage (hsc_dflags hsc_env)
-
- dep_missing (mb_pkg, L _ mod) = do
- find_res <- liftIO $ findImportedModule hsc_env mod (mb_pkg)
- let reason = moduleNameString mod ++ " changed"
- case find_res of
- Found _ mod
- | pkg == this_pkg
- -> if moduleName mod `notElem` map fst prev_dep_mods ++ prev_dep_plgn
- then do traceHiDiffs $
- text "imported module " <> quotes (ppr mod) <>
- text " not among previous dependencies"
- return (RecompBecause reason)
- else
- return UpToDate
- | otherwise
- -> if toInstalledUnitId pkg `notElem` (map fst prev_dep_pkgs)
- then do traceHiDiffs $
- text "imported module " <> quotes (ppr mod) <>
- text " is from package " <> quotes (ppr pkg) <>
- text ", which is not among previous dependencies"
- return (RecompBecause reason)
- else
- return UpToDate
- where pkg = moduleUnitId mod
- _otherwise -> return (RecompBecause reason)
-
- old_deps = Set.fromList $ map fst $ filter (not . snd) prev_dep_mods
- isOldHomeDeps = flip Set.member old_deps
- checkForNewHomeDependency (L _ mname) = do
- let
- mod = mkModule this_pkg mname
- str_mname = moduleNameString mname
- reason = str_mname ++ " changed"
- -- We only want to look at home modules to check if any new home dependency
- -- pops in and thus here, skip modules that are not home. Checking
- -- membership in old home dependencies suffice because the `dep_missing`
- -- check already verified that all imported home modules are present there.
- if not (isOldHomeDeps mname)
- then return (UpToDate, [])
- else do
- mb_result <- getFromModIface "need mi_deps for" mod $ \imported_iface -> do
- let mnames = mname:(map fst $ filter (not . snd) $
- dep_mods $ mi_deps imported_iface)
- case find (not . isOldHomeDeps) mnames of
- Nothing -> return (UpToDate, mnames)
- Just new_dep_mname -> do
- traceHiDiffs $
- text "imported home module " <> quotes (ppr mod) <>
- text " has a new dependency " <> quotes (ppr new_dep_mname)
- return (RecompBecause reason, [])
- return $ fromMaybe (MustCompile, []) mb_result
-
- -- Performs all recompilation checks in the list until a check that yields
- -- recompile required is encountered. Returns the list of the results of
- -- all UpToDate checks.
- runUntilRecompRequired [] = return (UpToDate, [])
- runUntilRecompRequired (check:checks) = do
- (recompile, value) <- check
- if recompileRequired recompile
- then return (recompile, [])
- else do
- (recomp, values) <- runUntilRecompRequired checks
- return (recomp, value:values)
-
- checkIfAllOldHomeDependenciesAreSeen seen_deps = do
- let unseen_old_deps = Set.difference
- old_deps
- seen_deps
- if not (null unseen_old_deps)
- then do
- let missing_dep = Set.elemAt 0 unseen_old_deps
- traceHiDiffs $
- text "missing old home dependency " <> quotes (ppr missing_dep)
- return $ RecompBecause "missing old dependency"
- else return UpToDate
-
-needInterface :: Module -> (ModIface -> IfG RecompileRequired)
- -> IfG RecompileRequired
-needInterface mod continue
- = do
- mb_recomp <- getFromModIface
- "need version info for"
- mod
- continue
- case mb_recomp of
- Nothing -> return MustCompile
- Just recomp -> return recomp
-
-getFromModIface :: String -> Module -> (ModIface -> IfG a)
- -> IfG (Maybe a)
-getFromModIface doc_msg mod getter
- = do -- Load the imported interface if possible
- let doc_str = sep [text doc_msg, ppr mod]
- traceHiDiffs (text "Checking innterface for module" <+> ppr mod)
-
- mb_iface <- loadInterface doc_str mod ImportBySystem
- -- Load the interface, but don't complain on failure;
- -- Instead, get an Either back which we can test
-
- case mb_iface of
- Failed _ -> do
- traceHiDiffs (sep [text "Couldn't load interface for module",
- ppr mod])
- return Nothing
- -- Couldn't find or parse a module mentioned in the
- -- old interface file. Don't complain: it might
- -- just be that the current module doesn't need that
- -- import and it's been deleted
- Succeeded iface -> Just <$> getter iface
-
--- | Given the usage information extracted from the old
--- M.hi file for the module being compiled, figure out
--- whether M needs to be recompiled.
-checkModUsage :: UnitId -> Usage -> IfG RecompileRequired
-checkModUsage _this_pkg UsagePackageModule{
- usg_mod = mod,
- usg_mod_hash = old_mod_hash }
- = needInterface mod $ \iface -> do
- let reason = moduleNameString (moduleName mod) ++ " changed"
- checkModuleFingerprint reason old_mod_hash (mi_mod_hash (mi_final_exts iface))
- -- We only track the ABI hash of package modules, rather than
- -- individual entity usages, so if the ABI hash changes we must
- -- recompile. This is safe but may entail more recompilation when
- -- a dependent package has changed.
-
-checkModUsage _ UsageMergedRequirement{ usg_mod = mod, usg_mod_hash = old_mod_hash }
- = needInterface mod $ \iface -> do
- let reason = moduleNameString (moduleName mod) ++ " changed (raw)"
- checkModuleFingerprint reason old_mod_hash (mi_mod_hash (mi_final_exts iface))
-
-checkModUsage this_pkg UsageHomeModule{
- usg_mod_name = mod_name,
- usg_mod_hash = old_mod_hash,
- usg_exports = maybe_old_export_hash,
- usg_entities = old_decl_hash }
- = do
- let mod = mkModule this_pkg mod_name
- needInterface mod $ \iface -> do
-
- let
- new_mod_hash = mi_mod_hash (mi_final_exts iface)
- new_decl_hash = mi_hash_fn (mi_final_exts iface)
- new_export_hash = mi_exp_hash (mi_final_exts iface)
-
- reason = moduleNameString mod_name ++ " changed"
-
- -- CHECK MODULE
- recompile <- checkModuleFingerprint reason old_mod_hash new_mod_hash
- if not (recompileRequired recompile)
- then return UpToDate
- else do
-
- -- CHECK EXPORT LIST
- checkMaybeHash reason maybe_old_export_hash new_export_hash
- (text " Export list changed") $ do
-
- -- CHECK ITEMS ONE BY ONE
- recompile <- checkList [ checkEntityUsage reason new_decl_hash u
- | u <- old_decl_hash]
- if recompileRequired recompile
- then return recompile -- This one failed, so just bail out now
- else up_to_date (text " Great! The bits I use are up to date")
-
-
-checkModUsage _this_pkg UsageFile{ usg_file_path = file,
- usg_file_hash = old_hash } =
- liftIO $
- handleIO handle $ do
- new_hash <- getFileHash file
- if (old_hash /= new_hash)
- then return recomp
- else return UpToDate
- where
- recomp = RecompBecause (file ++ " changed")
- handle =
-#if defined(DEBUG)
- \e -> pprTrace "UsageFile" (text (show e)) $ return recomp
-#else
- \_ -> return recomp -- if we can't find the file, just recompile, don't fail
-#endif
-
-------------------------
-checkModuleFingerprint :: String -> Fingerprint -> Fingerprint
- -> IfG RecompileRequired
-checkModuleFingerprint reason old_mod_hash new_mod_hash
- | new_mod_hash == old_mod_hash
- = up_to_date (text "Module fingerprint unchanged")
-
- | otherwise
- = out_of_date_hash reason (text " Module fingerprint has changed")
- old_mod_hash new_mod_hash
-
-------------------------
-checkMaybeHash :: String -> Maybe Fingerprint -> Fingerprint -> SDoc
- -> IfG RecompileRequired -> IfG RecompileRequired
-checkMaybeHash reason maybe_old_hash new_hash doc continue
- | Just hash <- maybe_old_hash, hash /= new_hash
- = out_of_date_hash reason doc hash new_hash
- | otherwise
- = continue
-
-------------------------
-checkEntityUsage :: String
- -> (OccName -> Maybe (OccName, Fingerprint))
- -> (OccName, Fingerprint)
- -> IfG RecompileRequired
-checkEntityUsage reason new_hash (name,old_hash)
- = case new_hash name of
-
- Nothing -> -- We used it before, but it ain't there now
- out_of_date reason (sep [text "No longer exported:", ppr name])
-
- Just (_, new_hash) -- It's there, but is it up to date?
- | new_hash == old_hash -> do traceHiDiffs (text " Up to date" <+> ppr name <+> parens (ppr new_hash))
- return UpToDate
- | otherwise -> out_of_date_hash reason (text " Out of date:" <+> ppr name)
- old_hash new_hash
-
-up_to_date :: SDoc -> IfG RecompileRequired
-up_to_date msg = traceHiDiffs msg >> return UpToDate
-
-out_of_date :: String -> SDoc -> IfG RecompileRequired
-out_of_date reason msg = traceHiDiffs msg >> return (RecompBecause reason)
-
-out_of_date_hash :: String -> SDoc -> Fingerprint -> Fingerprint -> IfG RecompileRequired
-out_of_date_hash reason msg old_hash new_hash
- = out_of_date reason (hsep [msg, ppr old_hash, text "->", ppr new_hash])
-
-----------------------
-checkList :: [IfG RecompileRequired] -> IfG RecompileRequired
--- This helper is used in two places
-checkList [] = return UpToDate
-checkList (check:checks) = do recompile <- check
- if recompileRequired recompile
- then return recompile
- else checkList checks
-
-{-
-************************************************************************
-* *
- Converting things to their Iface equivalents
-* *
-************************************************************************
--}
-
-tyThingToIfaceDecl :: TyThing -> IfaceDecl
-tyThingToIfaceDecl (AnId id) = idToIfaceDecl id
-tyThingToIfaceDecl (ATyCon tycon) = snd (tyConToIfaceDecl emptyTidyEnv tycon)
-tyThingToIfaceDecl (ACoAxiom ax) = coAxiomToIfaceDecl ax
-tyThingToIfaceDecl (AConLike cl) = case cl of
- RealDataCon dc -> dataConToIfaceDecl dc -- for ppr purposes only
- PatSynCon ps -> patSynToIfaceDecl ps
-
---------------------------
-idToIfaceDecl :: Id -> IfaceDecl
--- The Id is already tidied, so that locally-bound names
--- (lambdas, for-alls) already have non-clashing OccNames
--- We can't tidy it here, locally, because it may have
--- free variables in its type or IdInfo
-idToIfaceDecl id
- = IfaceId { ifName = getName id,
- ifType = toIfaceType (idType id),
- ifIdDetails = toIfaceIdDetails (idDetails id),
- ifIdInfo = toIfaceIdInfo (idInfo id) }
-
---------------------------
-dataConToIfaceDecl :: DataCon -> IfaceDecl
-dataConToIfaceDecl dataCon
- = IfaceId { ifName = getName dataCon,
- ifType = toIfaceType (dataConUserType dataCon),
- ifIdDetails = IfVanillaId,
- ifIdInfo = NoInfo }
-
---------------------------
-coAxiomToIfaceDecl :: CoAxiom br -> IfaceDecl
--- We *do* tidy Axioms, because they are not (and cannot
--- conveniently be) built in tidy form
-coAxiomToIfaceDecl ax@(CoAxiom { co_ax_tc = tycon, co_ax_branches = branches
- , co_ax_role = role })
- = IfaceAxiom { ifName = getName ax
- , ifTyCon = toIfaceTyCon tycon
- , ifRole = role
- , ifAxBranches = map (coAxBranchToIfaceBranch tycon
- (map coAxBranchLHS branch_list))
- branch_list }
- where
- branch_list = fromBranches branches
-
--- 2nd parameter is the list of branch LHSs, in case of a closed type family,
--- for conversion from incompatible branches to incompatible indices.
--- For an open type family the list should be empty.
--- See Note [Storing compatibility] in CoAxiom
-coAxBranchToIfaceBranch :: TyCon -> [[Type]] -> CoAxBranch -> IfaceAxBranch
-coAxBranchToIfaceBranch tc lhs_s
- (CoAxBranch { cab_tvs = tvs, cab_cvs = cvs
- , cab_eta_tvs = eta_tvs
- , cab_lhs = lhs, cab_roles = roles
- , cab_rhs = rhs, cab_incomps = incomps })
-
- = IfaceAxBranch { ifaxbTyVars = toIfaceTvBndrs tvs
- , ifaxbCoVars = map toIfaceIdBndr cvs
- , ifaxbEtaTyVars = toIfaceTvBndrs eta_tvs
- , ifaxbLHS = toIfaceTcArgs tc lhs
- , ifaxbRoles = roles
- , ifaxbRHS = toIfaceType rhs
- , ifaxbIncomps = iface_incomps }
- where
- iface_incomps = map (expectJust "iface_incomps"
- . flip findIndex lhs_s
- . eqTypes
- . coAxBranchLHS) incomps
-
------------------
-tyConToIfaceDecl :: TidyEnv -> TyCon -> (TidyEnv, IfaceDecl)
--- We *do* tidy TyCons, because they are not (and cannot
--- conveniently be) built in tidy form
--- The returned TidyEnv is the one after tidying the tyConTyVars
-tyConToIfaceDecl env tycon
- | Just clas <- tyConClass_maybe tycon
- = classToIfaceDecl env clas
-
- | Just syn_rhs <- synTyConRhs_maybe tycon
- = ( tc_env1
- , IfaceSynonym { ifName = getName tycon,
- ifRoles = tyConRoles tycon,
- ifSynRhs = if_syn_type syn_rhs,
- ifBinders = if_binders,
- ifResKind = if_res_kind
- })
-
- | Just fam_flav <- famTyConFlav_maybe tycon
- = ( tc_env1
- , IfaceFamily { ifName = getName tycon,
- ifResVar = if_res_var,
- ifFamFlav = to_if_fam_flav fam_flav,
- ifBinders = if_binders,
- ifResKind = if_res_kind,
- ifFamInj = tyConInjectivityInfo tycon
- })
-
- | isAlgTyCon tycon
- = ( tc_env1
- , IfaceData { ifName = getName tycon,
- ifBinders = if_binders,
- ifResKind = if_res_kind,
- ifCType = tyConCType tycon,
- ifRoles = tyConRoles tycon,
- ifCtxt = tidyToIfaceContext tc_env1 (tyConStupidTheta tycon),
- ifCons = ifaceConDecls (algTyConRhs tycon),
- ifGadtSyntax = isGadtSyntaxTyCon tycon,
- ifParent = parent })
-
- | otherwise -- FunTyCon, PrimTyCon, promoted TyCon/DataCon
- -- We only convert these TyCons to IfaceTyCons when we are
- -- just about to pretty-print them, not because we are going
- -- to put them into interface files
- = ( env
- , IfaceData { ifName = getName tycon,
- ifBinders = if_binders,
- ifResKind = if_res_kind,
- ifCType = Nothing,
- ifRoles = tyConRoles tycon,
- ifCtxt = [],
- ifCons = IfDataTyCon [],
- ifGadtSyntax = False,
- ifParent = IfNoParent })
- where
- -- NOTE: Not all TyCons have `tyConTyVars` field. Forcing this when `tycon`
- -- is one of these TyCons (FunTyCon, PrimTyCon, PromotedDataCon) will cause
- -- an error.
- (tc_env1, tc_binders) = tidyTyConBinders env (tyConBinders tycon)
- tc_tyvars = binderVars tc_binders
- if_binders = toIfaceTyCoVarBinders tc_binders
- -- No tidying of the binders; they are already tidy
- if_res_kind = tidyToIfaceType tc_env1 (tyConResKind tycon)
- if_syn_type ty = tidyToIfaceType tc_env1 ty
- if_res_var = getOccFS `fmap` tyConFamilyResVar_maybe tycon
-
- parent = case tyConFamInstSig_maybe tycon of
- Just (tc, ty, ax) -> IfDataInstance (coAxiomName ax)
- (toIfaceTyCon tc)
- (tidyToIfaceTcArgs tc_env1 tc ty)
- Nothing -> IfNoParent
-
- to_if_fam_flav OpenSynFamilyTyCon = IfaceOpenSynFamilyTyCon
- to_if_fam_flav AbstractClosedSynFamilyTyCon = IfaceAbstractClosedSynFamilyTyCon
- to_if_fam_flav (DataFamilyTyCon {}) = IfaceDataFamilyTyCon
- to_if_fam_flav (BuiltInSynFamTyCon {}) = IfaceBuiltInSynFamTyCon
- to_if_fam_flav (ClosedSynFamilyTyCon Nothing) = IfaceClosedSynFamilyTyCon Nothing
- to_if_fam_flav (ClosedSynFamilyTyCon (Just ax))
- = IfaceClosedSynFamilyTyCon (Just (axn, ibr))
- where defs = fromBranches $ coAxiomBranches ax
- lhss = map coAxBranchLHS defs
- ibr = map (coAxBranchToIfaceBranch tycon lhss) defs
- axn = coAxiomName ax
-
- ifaceConDecls (NewTyCon { data_con = con }) = IfNewTyCon (ifaceConDecl con)
- ifaceConDecls (DataTyCon { data_cons = cons }) = IfDataTyCon (map ifaceConDecl cons)
- ifaceConDecls (TupleTyCon { data_con = con }) = IfDataTyCon [ifaceConDecl con]
- ifaceConDecls (SumTyCon { data_cons = cons }) = IfDataTyCon (map ifaceConDecl cons)
- ifaceConDecls AbstractTyCon = IfAbstractTyCon
- -- The AbstractTyCon case happens when a TyCon has been trimmed
- -- during tidying.
- -- Furthermore, tyThingToIfaceDecl is also used in TcRnDriver
- -- for GHCi, when browsing a module, in which case the
- -- AbstractTyCon and TupleTyCon cases are perfectly sensible.
- -- (Tuple declarations are not serialised into interface files.)
-
- ifaceConDecl data_con
- = IfCon { ifConName = dataConName data_con,
- ifConInfix = dataConIsInfix data_con,
- ifConWrapper = isJust (dataConWrapId_maybe data_con),
- ifConExTCvs = map toIfaceBndr ex_tvs',
- ifConUserTvBinders = map toIfaceForAllBndr user_bndrs',
- ifConEqSpec = map (to_eq_spec . eqSpecPair) eq_spec,
- ifConCtxt = tidyToIfaceContext con_env2 theta,
- ifConArgTys = map (tidyToIfaceType con_env2) arg_tys,
- ifConFields = dataConFieldLabels data_con,
- ifConStricts = map (toIfaceBang con_env2)
- (dataConImplBangs data_con),
- ifConSrcStricts = map toIfaceSrcBang
- (dataConSrcBangs data_con)}
- where
- (univ_tvs, ex_tvs, eq_spec, theta, arg_tys, _)
- = dataConFullSig data_con
- user_bndrs = dataConUserTyVarBinders data_con
-
- -- Tidy the univ_tvs of the data constructor to be identical
- -- to the tyConTyVars of the type constructor. This means
- -- (a) we don't need to redundantly put them into the interface file
- -- (b) when pretty-printing an Iface data declaration in H98-style syntax,
- -- we know that the type variables will line up
- -- The latter (b) is important because we pretty-print type constructors
- -- by converting to IfaceSyn and pretty-printing that
- con_env1 = (fst tc_env1, mkVarEnv (zipEqual "ifaceConDecl" univ_tvs tc_tyvars))
- -- A bit grimy, perhaps, but it's simple!
-
- (con_env2, ex_tvs') = tidyVarBndrs con_env1 ex_tvs
- user_bndrs' = map (tidyUserTyCoVarBinder con_env2) user_bndrs
- to_eq_spec (tv,ty) = (tidyTyVar con_env2 tv, tidyToIfaceType con_env2 ty)
-
- -- By this point, we have tidied every universal and existential
- -- tyvar. Because of the dcUserTyCoVarBinders invariant
- -- (see Note [DataCon user type variable binders]), *every*
- -- user-written tyvar must be contained in the substitution that
- -- tidying produced. Therefore, tidying the user-written tyvars is a
- -- simple matter of looking up each variable in the substitution,
- -- which tidyTyCoVarOcc accomplishes.
- tidyUserTyCoVarBinder :: TidyEnv -> TyCoVarBinder -> TyCoVarBinder
- tidyUserTyCoVarBinder env (Bndr tv vis) =
- Bndr (tidyTyCoVarOcc env tv) vis
-
-classToIfaceDecl :: TidyEnv -> Class -> (TidyEnv, IfaceDecl)
-classToIfaceDecl env clas
- = ( env1
- , IfaceClass { ifName = getName tycon,
- ifRoles = tyConRoles (classTyCon clas),
- ifBinders = toIfaceTyCoVarBinders tc_binders,
- ifBody = body,
- ifFDs = map toIfaceFD clas_fds })
- where
- (_, clas_fds, sc_theta, _, clas_ats, op_stuff)
- = classExtraBigSig clas
- tycon = classTyCon clas
-
- body | isAbstractTyCon tycon = IfAbstractClass
- | otherwise
- = IfConcreteClass {
- ifClassCtxt = tidyToIfaceContext env1 sc_theta,
- ifATs = map toIfaceAT clas_ats,
- ifSigs = map toIfaceClassOp op_stuff,
- ifMinDef = fmap getOccFS (classMinimalDef clas)
- }
-
- (env1, tc_binders) = tidyTyConBinders env (tyConBinders tycon)
-
- toIfaceAT :: ClassATItem -> IfaceAT
- toIfaceAT (ATI tc def)
- = IfaceAT if_decl (fmap (tidyToIfaceType env2 . fst) def)
- where
- (env2, if_decl) = tyConToIfaceDecl env1 tc
-
- toIfaceClassOp (sel_id, def_meth)
- = ASSERT( sel_tyvars == binderVars tc_binders )
- IfaceClassOp (getName sel_id)
- (tidyToIfaceType env1 op_ty)
- (fmap toDmSpec def_meth)
- where
- -- Be careful when splitting the type, because of things
- -- like class Foo a where
- -- op :: (?x :: String) => a -> a
- -- and class Baz a where
- -- op :: (Ord a) => a -> a
- (sel_tyvars, rho_ty) = splitForAllTys (idType sel_id)
- op_ty = funResultTy rho_ty
-
- toDmSpec :: (Name, DefMethSpec Type) -> DefMethSpec IfaceType
- toDmSpec (_, VanillaDM) = VanillaDM
- toDmSpec (_, GenericDM dm_ty) = GenericDM (tidyToIfaceType env1 dm_ty)
-
- toIfaceFD (tvs1, tvs2) = (map (tidyTyVar env1) tvs1
- ,map (tidyTyVar env1) tvs2)
-
---------------------------
-
-tidyTyConBinder :: TidyEnv -> TyConBinder -> (TidyEnv, TyConBinder)
--- If the type variable "binder" is in scope, don't re-bind it
--- In a class decl, for example, the ATD binders mention
--- (amd must mention) the class tyvars
-tidyTyConBinder env@(_, subst) tvb@(Bndr tv vis)
- = case lookupVarEnv subst tv of
- Just tv' -> (env, Bndr tv' vis)
- Nothing -> tidyTyCoVarBinder env tvb
-
-tidyTyConBinders :: TidyEnv -> [TyConBinder] -> (TidyEnv, [TyConBinder])
-tidyTyConBinders = mapAccumL tidyTyConBinder
-
-tidyTyVar :: TidyEnv -> TyVar -> FastString
-tidyTyVar (_, subst) tv = toIfaceTyVar (lookupVarEnv subst tv `orElse` tv)
-
---------------------------
-instanceToIfaceInst :: ClsInst -> IfaceClsInst
-instanceToIfaceInst (ClsInst { is_dfun = dfun_id, is_flag = oflag
- , is_cls_nm = cls_name, is_cls = cls
- , is_tcs = mb_tcs
- , is_orphan = orph })
- = ASSERT( cls_name == className cls )
- IfaceClsInst { ifDFun = dfun_name,
- ifOFlag = oflag,
- ifInstCls = cls_name,
- ifInstTys = map do_rough mb_tcs,
- ifInstOrph = orph }
- where
- do_rough Nothing = Nothing
- do_rough (Just n) = Just (toIfaceTyCon_name n)
-
- dfun_name = idName dfun_id
-
-
---------------------------
-famInstToIfaceFamInst :: FamInst -> IfaceFamInst
-famInstToIfaceFamInst (FamInst { fi_axiom = axiom,
- fi_fam = fam,
- fi_tcs = roughs })
- = IfaceFamInst { ifFamInstAxiom = coAxiomName axiom
- , ifFamInstFam = fam
- , ifFamInstTys = map do_rough roughs
- , ifFamInstOrph = orph }
- where
- do_rough Nothing = Nothing
- do_rough (Just n) = Just (toIfaceTyCon_name n)
-
- fam_decl = tyConName $ coAxiomTyCon axiom
- mod = ASSERT( isExternalName (coAxiomName axiom) )
- nameModule (coAxiomName axiom)
- is_local name = nameIsLocalOrFrom mod name
-
- lhs_names = filterNameSet is_local (orphNamesOfCoCon axiom)
-
- orph | is_local fam_decl
- = NotOrphan (nameOccName fam_decl)
- | otherwise
- = chooseOrphanAnchor lhs_names
-
---------------------------
-coreRuleToIfaceRule :: CoreRule -> IfaceRule
-coreRuleToIfaceRule (BuiltinRule { ru_fn = fn})
- = pprTrace "toHsRule: builtin" (ppr fn) $
- bogusIfaceRule fn
-
-coreRuleToIfaceRule (Rule { ru_name = name, ru_fn = fn,
- ru_act = act, ru_bndrs = bndrs,
- ru_args = args, ru_rhs = rhs,
- ru_orphan = orph, ru_auto = auto })
- = IfaceRule { ifRuleName = name, ifActivation = act,
- ifRuleBndrs = map toIfaceBndr bndrs,
- ifRuleHead = fn,
- ifRuleArgs = map do_arg args,
- ifRuleRhs = toIfaceExpr rhs,
- ifRuleAuto = auto,
- ifRuleOrph = orph }
- where
- -- For type args we must remove synonyms from the outermost
- -- level. Reason: so that when we read it back in we'll
- -- construct the same ru_rough field as we have right now;
- -- see tcIfaceRule
- do_arg (Type ty) = IfaceType (toIfaceType (deNoteType ty))
- do_arg (Coercion co) = IfaceCo (toIfaceCoercion co)
- do_arg arg = toIfaceExpr arg
-
-bogusIfaceRule :: Name -> IfaceRule
-bogusIfaceRule id_name
- = IfaceRule { ifRuleName = fsLit "bogus", ifActivation = NeverActive,
- ifRuleBndrs = [], ifRuleHead = id_name, ifRuleArgs = [],
- ifRuleRhs = IfaceExt id_name, ifRuleOrph = IsOrphan,
- ifRuleAuto = True }
diff --git a/compiler/iface/TcIface.hs b/compiler/iface/TcIface.hs
deleted file mode 100644
index 34cf2c247e..0000000000
--- a/compiler/iface/TcIface.hs
+++ /dev/null
@@ -1,1825 +0,0 @@
-{-
-(c) The University of Glasgow 2006
-(c) The GRASP/AQUA Project, Glasgow University, 1992-1998
-
-
-Type checking of type signatures in interface files
--}
-
-{-# LANGUAGE CPP #-}
-{-# LANGUAGE NondecreasingIndentation #-}
-
-module TcIface (
- tcLookupImported_maybe,
- importDecl, checkWiredInTyCon, tcHiBootIface, typecheckIface,
- typecheckIfacesForMerging,
- typecheckIfaceForInstantiate,
- tcIfaceDecl, tcIfaceInst, tcIfaceFamInst, tcIfaceRules,
- tcIfaceAnnotations, tcIfaceCompleteSigs,
- tcIfaceExpr, -- Desired by HERMIT (#7683)
- tcIfaceGlobal
- ) where
-
-#include "HsVersions.h"
-
-import GhcPrelude
-
-import TcTypeNats(typeNatCoAxiomRules)
-import IfaceSyn
-import LoadIface
-import IfaceEnv
-import BuildTyCl
-import TcRnMonad
-import TcType
-import Type
-import Coercion
-import CoAxiom
-import TyCoRep -- needs to build types & coercions in a knot
-import TyCoSubst ( substTyCoVars )
-import HscTypes
-import Annotations
-import InstEnv
-import FamInstEnv
-import CoreSyn
-import CoreUtils
-import CoreUnfold
-import CoreLint
-import MkCore
-import Id
-import MkId
-import IdInfo
-import Class
-import TyCon
-import ConLike
-import DataCon
-import PrelNames
-import TysWiredIn
-import Literal
-import Var
-import VarSet
-import Name
-import NameEnv
-import NameSet
-import OccurAnal ( occurAnalyseExpr )
-import Demand
-import Module
-import UniqFM
-import UniqSupply
-import Outputable
-import Maybes
-import SrcLoc
-import DynFlags
-import Util
-import FastString
-import BasicTypes hiding ( SuccessFlag(..) )
-import ListSetOps
-import GHC.Fingerprint
-import qualified BooleanFormula as BF
-
-import Control.Monad
-import qualified Data.Map as Map
-
-{-
-This module takes
-
- IfaceDecl -> TyThing
- IfaceType -> Type
- etc
-
-An IfaceDecl is populated with RdrNames, and these are not renamed to
-Names before typechecking, because there should be no scope errors etc.
-
- -- For (b) consider: f = \$(...h....)
- -- where h is imported, and calls f via an hi-boot file.
- -- This is bad! But it is not seen as a staging error, because h
- -- is indeed imported. We don't want the type-checker to black-hole
- -- when simplifying and compiling the splice!
- --
- -- Simple solution: discard any unfolding that mentions a variable
- -- bound in this module (and hence not yet processed).
- -- The discarding happens when forkM finds a type error.
-
-
-************************************************************************
-* *
- Type-checking a complete interface
-* *
-************************************************************************
-
-Suppose we discover we don't need to recompile. Then we must type
-check the old interface file. This is a bit different to the
-incremental type checking we do as we suck in interface files. Instead
-we do things similarly as when we are typechecking source decls: we
-bring into scope the type envt for the interface all at once, using a
-knot. Remember, the decls aren't necessarily in dependency order --
-and even if they were, the type decls might be mutually recursive.
-
-Note [Knot-tying typecheckIface]
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-Suppose we are typechecking an interface A.hi, and we come across
-a Name for another entity defined in A.hi. How do we get the
-'TyCon', in this case? There are three cases:
-
- 1) tcHiBootIface in TcIface: We're typechecking an hi-boot file in
- preparation of checking if the hs file we're building
- is compatible. In this case, we want all of the internal
- TyCons to MATCH the ones that we just constructed during
- typechecking: the knot is thus tied through if_rec_types.
-
- 2) retypecheckLoop in GhcMake: We are retypechecking a
- mutually recursive cluster of hi files, in order to ensure
- that all of the references refer to each other correctly.
- In this case, the knot is tied through the HPT passed in,
- which contains all of the interfaces we are in the process
- of typechecking.
-
- 3) genModDetails in HscMain: We are typechecking an
- old interface to generate the ModDetails. In this case,
- we do the same thing as (2) and pass in an HPT with
- the HomeModInfo being generated to tie knots.
-
-The upshot is that the CLIENT of this function is responsible
-for making sure that the knot is tied correctly. If you don't,
-then you'll get a message saying that we couldn't load the
-declaration you wanted.
-
-BTW, in one-shot mode we never call typecheckIface; instead,
-loadInterface handles type-checking interface. In that case,
-knots are tied through the EPS. No problem!
--}
-
--- Clients of this function be careful, see Note [Knot-tying typecheckIface]
-typecheckIface :: ModIface -- Get the decls from here
- -> IfG ModDetails
-typecheckIface iface
- = initIfaceLcl (mi_semantic_module iface) (text "typecheckIface") (mi_boot iface) $ do
- { -- Get the right set of decls and rules. If we are compiling without -O
- -- we discard pragmas before typechecking, so that we don't "see"
- -- information that we shouldn't. From a versioning point of view
- -- It's not actually *wrong* to do so, but in fact GHCi is unable
- -- to handle unboxed tuples, so it must not see unfoldings.
- ignore_prags <- goptM Opt_IgnoreInterfacePragmas
-
- -- Typecheck the decls. This is done lazily, so that the knot-tying
- -- within this single module works out right. It's the callers
- -- job to make sure the knot is tied.
- ; names_w_things <- loadDecls ignore_prags (mi_decls iface)
- ; let type_env = mkNameEnv names_w_things
-
- -- Now do those rules, instances and annotations
- ; insts <- mapM tcIfaceInst (mi_insts iface)
- ; fam_insts <- mapM tcIfaceFamInst (mi_fam_insts iface)
- ; rules <- tcIfaceRules ignore_prags (mi_rules iface)
- ; anns <- tcIfaceAnnotations (mi_anns iface)
-
- -- Exports
- ; exports <- ifaceExportNames (mi_exports iface)
-
- -- Complete Sigs
- ; complete_sigs <- tcIfaceCompleteSigs (mi_complete_sigs iface)
-
- -- Finished
- ; traceIf (vcat [text "Finished typechecking interface for" <+> ppr (mi_module iface),
- -- Careful! If we tug on the TyThing thunks too early
- -- we'll infinite loop with hs-boot. See #10083 for
- -- an example where this would cause non-termination.
- text "Type envt:" <+> ppr (map fst names_w_things)])
- ; return $ ModDetails { md_types = type_env
- , md_insts = insts
- , md_fam_insts = fam_insts
- , md_rules = rules
- , md_anns = anns
- , md_exports = exports
- , md_complete_sigs = complete_sigs
- }
- }
-
-{-
-************************************************************************
-* *
- Typechecking for merging
-* *
-************************************************************************
--}
-
--- | Returns true if an 'IfaceDecl' is for @data T@ (an abstract data type)
-isAbstractIfaceDecl :: IfaceDecl -> Bool
-isAbstractIfaceDecl IfaceData{ ifCons = IfAbstractTyCon } = True
-isAbstractIfaceDecl IfaceClass{ ifBody = IfAbstractClass } = True
-isAbstractIfaceDecl IfaceFamily{ ifFamFlav = IfaceAbstractClosedSynFamilyTyCon } = True
-isAbstractIfaceDecl _ = False
-
-ifMaybeRoles :: IfaceDecl -> Maybe [Role]
-ifMaybeRoles IfaceData { ifRoles = rs } = Just rs
-ifMaybeRoles IfaceSynonym { ifRoles = rs } = Just rs
-ifMaybeRoles IfaceClass { ifRoles = rs } = Just rs
-ifMaybeRoles _ = Nothing
-
--- | Merge two 'IfaceDecl's together, preferring a non-abstract one. If
--- both are non-abstract we pick one arbitrarily (and check for consistency
--- later.)
-mergeIfaceDecl :: IfaceDecl -> IfaceDecl -> IfaceDecl
-mergeIfaceDecl d1 d2
- | isAbstractIfaceDecl d1 = d2 `withRolesFrom` d1
- | isAbstractIfaceDecl d2 = d1 `withRolesFrom` d2
- | IfaceClass{ ifBody = IfConcreteClass { ifSigs = ops1, ifMinDef = bf1 } } <- d1
- , IfaceClass{ ifBody = IfConcreteClass { ifSigs = ops2, ifMinDef = bf2 } } <- d2
- = let ops = nameEnvElts $
- plusNameEnv_C mergeIfaceClassOp
- (mkNameEnv [ (n, op) | op@(IfaceClassOp n _ _) <- ops1 ])
- (mkNameEnv [ (n, op) | op@(IfaceClassOp n _ _) <- ops2 ])
- in d1 { ifBody = (ifBody d1) {
- ifSigs = ops,
- ifMinDef = BF.mkOr [noLoc bf1, noLoc bf2]
- }
- } `withRolesFrom` d2
- -- It doesn't matter; we'll check for consistency later when
- -- we merge, see 'mergeSignatures'
- | otherwise = d1 `withRolesFrom` d2
-
--- Note [Role merging]
--- ~~~~~~~~~~~~~~~~~~~
--- First, why might it be necessary to do a non-trivial role
--- merge? It may rescue a merge that might otherwise fail:
---
--- signature A where
--- type role T nominal representational
--- data T a b
---
--- signature A where
--- type role T representational nominal
--- data T a b
---
--- A module that defines T as representational in both arguments
--- would successfully fill both signatures, so it would be better
--- if we merged the roles of these types in some nontrivial
--- way.
---
--- However, we have to be very careful about how we go about
--- doing this, because role subtyping is *conditional* on
--- the supertype being NOT representationally injective, e.g.,
--- if we have instead:
---
--- signature A where
--- type role T nominal representational
--- data T a b = T a b
---
--- signature A where
--- type role T representational nominal
--- data T a b = T a b
---
--- Should we merge the definitions of T so that the roles are R/R (or N/N)?
--- Absolutely not: neither resulting type is a subtype of the original
--- types (see Note [Role subtyping]), because data is not representationally
--- injective.
---
--- Thus, merging only occurs when BOTH TyCons in question are
--- representationally injective. If they're not, no merge.
-
-withRolesFrom :: IfaceDecl -> IfaceDecl -> IfaceDecl
-d1 `withRolesFrom` d2
- | Just roles1 <- ifMaybeRoles d1
- , Just roles2 <- ifMaybeRoles d2
- , not (isRepInjectiveIfaceDecl d1 || isRepInjectiveIfaceDecl d2)
- = d1 { ifRoles = mergeRoles roles1 roles2 }
- | otherwise = d1
- where
- mergeRoles roles1 roles2 = zipWith max roles1 roles2
-
-isRepInjectiveIfaceDecl :: IfaceDecl -> Bool
-isRepInjectiveIfaceDecl IfaceData{ ifCons = IfDataTyCon _ } = True
-isRepInjectiveIfaceDecl IfaceFamily{ ifFamFlav = IfaceDataFamilyTyCon } = True
-isRepInjectiveIfaceDecl _ = False
-
-mergeIfaceClassOp :: IfaceClassOp -> IfaceClassOp -> IfaceClassOp
-mergeIfaceClassOp op1@(IfaceClassOp _ _ (Just _)) _ = op1
-mergeIfaceClassOp _ op2 = op2
-
--- | Merge two 'OccEnv's of 'IfaceDecl's by 'OccName'.
-mergeIfaceDecls :: OccEnv IfaceDecl -> OccEnv IfaceDecl -> OccEnv IfaceDecl
-mergeIfaceDecls = plusOccEnv_C mergeIfaceDecl
-
--- | This is a very interesting function. Like typecheckIface, we want
--- to type check an interface file into a ModDetails. However, the use-case
--- for these ModDetails is different: we want to compare all of the
--- ModDetails to ensure they define compatible declarations, and then
--- merge them together. So in particular, we have to take a different
--- strategy for knot-tying: we first speculatively merge the declarations
--- to get the "base" truth for what we believe the types will be
--- (this is "type computation.") Then we read everything in relative
--- to this truth and check for compatibility.
---
--- During the merge process, we may need to nondeterministically
--- pick a particular declaration to use, if multiple signatures define
--- the declaration ('mergeIfaceDecl'). If, for all choices, there
--- are no type synonym cycles in the resulting merged graph, then
--- we can show that our choice cannot matter. Consider the
--- set of entities which the declarations depend on: by assumption
--- of acyclicity, we can assume that these have already been shown to be equal
--- to each other (otherwise merging will fail). Then it must
--- be the case that all candidate declarations here are type-equal
--- (the choice doesn't matter) or there is an inequality (in which
--- case merging will fail.)
---
--- Unfortunately, the choice can matter if there is a cycle. Consider the
--- following merge:
---
--- signature H where { type A = C; type B = A; data C }
--- signature H where { type A = (); data B; type C = B }
---
--- If we pick @type A = C@ as our representative, there will be
--- a cycle and merging will fail. But if we pick @type A = ()@ as
--- our representative, no cycle occurs, and we instead conclude
--- that all of the types are unit. So it seems that we either
--- (a) need a stronger acyclicity check which considers *all*
--- possible choices from a merge, or (b) we must find a selection
--- of declarations which is acyclic, and show that this is always
--- the "best" choice we could have made (ezyang conjectures this
--- is the case but does not have a proof). For now this is
--- not implemented.
---
--- It's worth noting that at the moment, a data constructor and a
--- type synonym are never compatible. Consider:
---
--- signature H where { type Int=C; type B = Int; data C = Int}
--- signature H where { export Prelude.Int; data B; type C = B; }
---
--- This will be rejected, because the reexported Int in the second
--- signature (a proper data type) is never considered equal to a
--- type synonym. Perhaps this should be relaxed, where a type synonym
--- in a signature is considered implemented by a data type declaration
--- which matches the reference of the type synonym.
-typecheckIfacesForMerging :: Module -> [ModIface] -> IORef TypeEnv -> IfM lcl (TypeEnv, [ModDetails])
-typecheckIfacesForMerging mod ifaces tc_env_var =
- -- cannot be boot (False)
- initIfaceLcl mod (text "typecheckIfacesForMerging") False $ do
- ignore_prags <- goptM Opt_IgnoreInterfacePragmas
- -- Build the initial environment
- -- NB: Don't include dfuns here, because we don't want to
- -- serialize them out. See Note [rnIfaceNeverExported] in RnModIface
- -- NB: But coercions are OK, because they will have the right OccName.
- let mk_decl_env decls
- = mkOccEnv [ (getOccName decl, decl)
- | decl <- decls
- , case decl of
- IfaceId { ifIdDetails = IfDFunId } -> False -- exclude DFuns
- _ -> True ]
- decl_envs = map (mk_decl_env . map snd . mi_decls) ifaces
- :: [OccEnv IfaceDecl]
- decl_env = foldl' mergeIfaceDecls emptyOccEnv decl_envs
- :: OccEnv IfaceDecl
- -- TODO: change loadDecls to accept w/o Fingerprint
- names_w_things <- loadDecls ignore_prags (map (\x -> (fingerprint0, x))
- (occEnvElts decl_env))
- let global_type_env = mkNameEnv names_w_things
- writeMutVar tc_env_var global_type_env
-
- -- OK, now typecheck each ModIface using this environment
- details <- forM ifaces $ \iface -> do
- -- See Note [Resolving never-exported Names in TcIface]
- type_env <- fixM $ \type_env -> do
- setImplicitEnvM type_env $ do
- decls <- loadDecls ignore_prags (mi_decls iface)
- return (mkNameEnv decls)
- -- But note that we use this type_env to typecheck references to DFun
- -- in 'IfaceInst'
- setImplicitEnvM type_env $ do
- insts <- mapM tcIfaceInst (mi_insts iface)
- fam_insts <- mapM tcIfaceFamInst (mi_fam_insts iface)
- rules <- tcIfaceRules ignore_prags (mi_rules iface)
- anns <- tcIfaceAnnotations (mi_anns iface)
- exports <- ifaceExportNames (mi_exports iface)
- complete_sigs <- tcIfaceCompleteSigs (mi_complete_sigs iface)
- return $ ModDetails { md_types = type_env
- , md_insts = insts
- , md_fam_insts = fam_insts
- , md_rules = rules
- , md_anns = anns
- , md_exports = exports
- , md_complete_sigs = complete_sigs
- }
- return (global_type_env, details)
-
--- | Typecheck a signature 'ModIface' under the assumption that we have
--- instantiated it under some implementation (recorded in 'mi_semantic_module')
--- and want to check if the implementation fills the signature.
---
--- This needs to operate slightly differently than 'typecheckIface'
--- because (1) we have a 'NameShape', from the exports of the
--- implementing module, which we will use to give our top-level
--- declarations the correct 'Name's even when the implementor
--- provided them with a reexport, and (2) we have to deal with
--- DFun silliness (see Note [rnIfaceNeverExported])
-typecheckIfaceForInstantiate :: NameShape -> ModIface -> IfM lcl ModDetails
-typecheckIfaceForInstantiate nsubst iface =
- initIfaceLclWithSubst (mi_semantic_module iface)
- (text "typecheckIfaceForInstantiate")
- (mi_boot iface) nsubst $ do
- ignore_prags <- goptM Opt_IgnoreInterfacePragmas
- -- See Note [Resolving never-exported Names in TcIface]
- type_env <- fixM $ \type_env -> do
- setImplicitEnvM type_env $ do
- decls <- loadDecls ignore_prags (mi_decls iface)
- return (mkNameEnv decls)
- -- See Note [rnIfaceNeverExported]
- setImplicitEnvM type_env $ do
- insts <- mapM tcIfaceInst (mi_insts iface)
- fam_insts <- mapM tcIfaceFamInst (mi_fam_insts iface)
- rules <- tcIfaceRules ignore_prags (mi_rules iface)
- anns <- tcIfaceAnnotations (mi_anns iface)
- exports <- ifaceExportNames (mi_exports iface)
- complete_sigs <- tcIfaceCompleteSigs (mi_complete_sigs iface)
- return $ ModDetails { md_types = type_env
- , md_insts = insts
- , md_fam_insts = fam_insts
- , md_rules = rules
- , md_anns = anns
- , md_exports = exports
- , md_complete_sigs = complete_sigs
- }
-
--- Note [Resolving never-exported Names in TcIface]
--- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
--- For the high-level overview, see
--- Note [Handling never-exported TyThings under Backpack]
---
--- As described in 'typecheckIfacesForMerging', the splendid innovation
--- of signature merging is to rewrite all Names in each of the signatures
--- we are merging together to a pre-merged structure; this is the key
--- ingredient that lets us solve some problems when merging type
--- synonyms.
---
--- However, when a 'Name' refers to a NON-exported entity, as is the
--- case with the DFun of a ClsInst, or a CoAxiom of a type family,
--- this strategy causes problems: if we pick one and rewrite all
--- references to a shared 'Name', we will accidentally fail to check
--- if the DFun or CoAxioms are compatible, as they will never be
--- checked--only exported entities are checked for compatibility,
--- and a non-exported TyThing is checked WHEN we are checking the
--- ClsInst or type family for compatibility in checkBootDeclM.
--- By virtue of the fact that everything's been pointed to the merged
--- declaration, you'll never notice there's a difference even if there
--- is one.
---
--- Fortunately, there are only a few places in the interface declarations
--- where this can occur, so we replace those calls with 'tcIfaceImplicit',
--- which will consult a local TypeEnv that records any never-exported
--- TyThings which we should wire up with.
---
--- Note that we actually knot-tie this local TypeEnv (the 'fixM'), because a
--- type family can refer to a coercion axiom, all of which are done in one go
--- when we typecheck 'mi_decls'. An alternate strategy would be to typecheck
--- coercions first before type families, but that seemed more fragile.
---
-
-{-
-************************************************************************
-* *
- Type and class declarations
-* *
-************************************************************************
--}
-
-tcHiBootIface :: HscSource -> Module -> TcRn SelfBootInfo
--- Load the hi-boot iface for the module being compiled,
--- if it indeed exists in the transitive closure of imports
--- Return the ModDetails; Nothing if no hi-boot iface
-tcHiBootIface hsc_src mod
- | HsBootFile <- hsc_src -- Already compiling a hs-boot file
- = return NoSelfBoot
- | otherwise
- = do { traceIf (text "loadHiBootInterface" <+> ppr mod)
-
- ; mode <- getGhcMode
- ; if not (isOneShot mode)
- -- In --make and interactive mode, if this module has an hs-boot file
- -- we'll have compiled it already, and it'll be in the HPT
- --
- -- We check whether the interface is a *boot* interface.
- -- It can happen (when using GHC from Visual Studio) that we
- -- compile a module in TypecheckOnly mode, with a stable,
- -- fully-populated HPT. In that case the boot interface isn't there
- -- (it's been replaced by the mother module) so we can't check it.
- -- And that's fine, because if M's ModInfo is in the HPT, then
- -- it's been compiled once, and we don't need to check the boot iface
- then do { hpt <- getHpt
- ; case lookupHpt hpt (moduleName mod) of
- Just info | mi_boot (hm_iface info)
- -> mkSelfBootInfo (hm_iface info) (hm_details info)
- _ -> return NoSelfBoot }
- else do
-
- -- OK, so we're in one-shot mode.
- -- Re #9245, we always check if there is an hi-boot interface
- -- to check consistency against, rather than just when we notice
- -- that an hi-boot is necessary due to a circular import.
- { read_result <- findAndReadIface
- need (fst (splitModuleInsts mod)) mod
- True -- Hi-boot file
-
- ; case read_result of {
- Succeeded (iface, _path) -> do { tc_iface <- initIfaceTcRn $ typecheckIface iface
- ; mkSelfBootInfo iface tc_iface } ;
- Failed err ->
-
- -- There was no hi-boot file. But if there is circularity in
- -- the module graph, there really should have been one.
- -- Since we've read all the direct imports by now,
- -- eps_is_boot will record if any of our imports mention the
- -- current module, which either means a module loop (not
- -- a SOURCE import) or that our hi-boot file has mysteriously
- -- disappeared.
- do { eps <- getEps
- ; case lookupUFM (eps_is_boot eps) (moduleName mod) of
- Nothing -> return NoSelfBoot -- The typical case
-
- Just (_, False) -> failWithTc moduleLoop
- -- Someone below us imported us!
- -- This is a loop with no hi-boot in the way
-
- Just (_mod, True) -> failWithTc (elaborate err)
- -- The hi-boot file has mysteriously disappeared.
- }}}}
- where
- need = text "Need the hi-boot interface for" <+> ppr mod
- <+> text "to compare against the Real Thing"
-
- moduleLoop = text "Circular imports: module" <+> quotes (ppr mod)
- <+> text "depends on itself"
-
- elaborate err = hang (text "Could not find hi-boot interface for" <+>
- quotes (ppr mod) <> colon) 4 err
-
-
-mkSelfBootInfo :: ModIface -> ModDetails -> TcRn SelfBootInfo
-mkSelfBootInfo iface mds
- = do -- NB: This is computed DIRECTLY from the ModIface rather
- -- than from the ModDetails, so that we can query 'sb_tcs'
- -- WITHOUT forcing the contents of the interface.
- let tcs = map ifName
- . filter isIfaceTyCon
- . map snd
- $ mi_decls iface
- return $ SelfBoot { sb_mds = mds
- , sb_tcs = mkNameSet tcs }
- where
- -- | Retuerns @True@ if, when you call 'tcIfaceDecl' on
- -- this 'IfaceDecl', an ATyCon would be returned.
- -- NB: This code assumes that a TyCon cannot be implicit.
- isIfaceTyCon IfaceId{} = False
- isIfaceTyCon IfaceData{} = True
- isIfaceTyCon IfaceSynonym{} = True
- isIfaceTyCon IfaceFamily{} = True
- isIfaceTyCon IfaceClass{} = True
- isIfaceTyCon IfaceAxiom{} = False
- isIfaceTyCon IfacePatSyn{} = False
-
-{-
-************************************************************************
-* *
- Type and class declarations
-* *
-************************************************************************
-
-When typechecking a data type decl, we *lazily* (via forkM) typecheck
-the constructor argument types. This is in the hope that we may never
-poke on those argument types, and hence may never need to load the
-interface files for types mentioned in the arg types.
-
-E.g.
- data Foo.S = MkS Baz.T
-Maybe we can get away without even loading the interface for Baz!
-
-This is not just a performance thing. Suppose we have
- data Foo.S = MkS Baz.T
- data Baz.T = MkT Foo.S
-(in different interface files, of course).
-Now, first we load and typecheck Foo.S, and add it to the type envt.
-If we do explore MkS's argument, we'll load and typecheck Baz.T.
-If we explore MkT's argument we'll find Foo.S already in the envt.
-
-If we typechecked constructor args eagerly, when loading Foo.S we'd try to
-typecheck the type Baz.T. So we'd fault in Baz.T... and then need Foo.S...
-which isn't done yet.
-
-All very cunning. However, there is a rather subtle gotcha which bit
-me when developing this stuff. When we typecheck the decl for S, we
-extend the type envt with S, MkS, and all its implicit Ids. Suppose
-(a bug, but it happened) that the list of implicit Ids depended in
-turn on the constructor arg types. Then the following sequence of
-events takes place:
- * we build a thunk <t> for the constructor arg tys
- * we build a thunk for the extended type environment (depends on <t>)
- * we write the extended type envt into the global EPS mutvar
-
-Now we look something up in the type envt
- * that pulls on <t>
- * which reads the global type envt out of the global EPS mutvar
- * but that depends in turn on <t>
-
-It's subtle, because, it'd work fine if we typechecked the constructor args
-eagerly -- they don't need the extended type envt. They just get the extended
-type envt by accident, because they look at it later.
-
-What this means is that the implicitTyThings MUST NOT DEPEND on any of
-the forkM stuff.
--}
-
-tcIfaceDecl :: Bool -- ^ True <=> discard IdInfo on IfaceId bindings
- -> IfaceDecl
- -> IfL TyThing
-tcIfaceDecl = tc_iface_decl Nothing
-
-tc_iface_decl :: Maybe Class -- ^ For associated type/data family declarations
- -> Bool -- ^ True <=> discard IdInfo on IfaceId bindings
- -> IfaceDecl
- -> IfL TyThing
-tc_iface_decl _ ignore_prags (IfaceId {ifName = name, ifType = iface_type,
- ifIdDetails = details, ifIdInfo = info})
- = do { ty <- tcIfaceType iface_type
- ; details <- tcIdDetails ty details
- ; info <- tcIdInfo ignore_prags TopLevel name ty info
- ; return (AnId (mkGlobalId details name ty info)) }
-
-tc_iface_decl _ _ (IfaceData {ifName = tc_name,
- ifCType = cType,
- ifBinders = binders,
- ifResKind = res_kind,
- ifRoles = roles,
- ifCtxt = ctxt, ifGadtSyntax = gadt_syn,
- ifCons = rdr_cons,
- ifParent = mb_parent })
- = bindIfaceTyConBinders_AT binders $ \ binders' -> do
- { res_kind' <- tcIfaceType res_kind
-
- ; tycon <- fixM $ \ tycon -> do
- { stupid_theta <- tcIfaceCtxt ctxt
- ; parent' <- tc_parent tc_name mb_parent
- ; cons <- tcIfaceDataCons tc_name tycon binders' rdr_cons
- ; return (mkAlgTyCon tc_name binders' res_kind'
- roles cType stupid_theta
- cons parent' gadt_syn) }
- ; traceIf (text "tcIfaceDecl4" <+> ppr tycon)
- ; return (ATyCon tycon) }
- where
- tc_parent :: Name -> IfaceTyConParent -> IfL AlgTyConFlav
- tc_parent tc_name IfNoParent
- = do { tc_rep_name <- newTyConRepName tc_name
- ; return (VanillaAlgTyCon tc_rep_name) }
- tc_parent _ (IfDataInstance ax_name _ arg_tys)
- = do { ax <- tcIfaceCoAxiom ax_name
- ; let fam_tc = coAxiomTyCon ax
- ax_unbr = toUnbranchedAxiom ax
- ; lhs_tys <- tcIfaceAppArgs arg_tys
- ; return (DataFamInstTyCon ax_unbr fam_tc lhs_tys) }
-
-tc_iface_decl _ _ (IfaceSynonym {ifName = tc_name,
- ifRoles = roles,
- ifSynRhs = rhs_ty,
- ifBinders = binders,
- ifResKind = res_kind })
- = bindIfaceTyConBinders_AT binders $ \ binders' -> do
- { res_kind' <- tcIfaceType res_kind -- Note [Synonym kind loop]
- ; rhs <- forkM (mk_doc tc_name) $
- tcIfaceType rhs_ty
- ; let tycon = buildSynTyCon tc_name binders' res_kind' roles rhs
- ; return (ATyCon tycon) }
- where
- mk_doc n = text "Type synonym" <+> ppr n
-
-tc_iface_decl parent _ (IfaceFamily {ifName = tc_name,
- ifFamFlav = fam_flav,
- ifBinders = binders,
- ifResKind = res_kind,
- ifResVar = res, ifFamInj = inj })
- = bindIfaceTyConBinders_AT binders $ \ binders' -> do
- { res_kind' <- tcIfaceType res_kind -- Note [Synonym kind loop]
- ; rhs <- forkM (mk_doc tc_name) $
- tc_fam_flav tc_name fam_flav
- ; res_name <- traverse (newIfaceName . mkTyVarOccFS) res
- ; let tycon = mkFamilyTyCon tc_name binders' res_kind' res_name rhs parent inj
- ; return (ATyCon tycon) }
- where
- mk_doc n = text "Type synonym" <+> ppr n
-
- tc_fam_flav :: Name -> IfaceFamTyConFlav -> IfL FamTyConFlav
- tc_fam_flav tc_name IfaceDataFamilyTyCon
- = do { tc_rep_name <- newTyConRepName tc_name
- ; return (DataFamilyTyCon tc_rep_name) }
- tc_fam_flav _ IfaceOpenSynFamilyTyCon= return OpenSynFamilyTyCon
- tc_fam_flav _ (IfaceClosedSynFamilyTyCon mb_ax_name_branches)
- = do { ax <- traverse (tcIfaceCoAxiom . fst) mb_ax_name_branches
- ; return (ClosedSynFamilyTyCon ax) }
- tc_fam_flav _ IfaceAbstractClosedSynFamilyTyCon
- = return AbstractClosedSynFamilyTyCon
- tc_fam_flav _ IfaceBuiltInSynFamTyCon
- = pprPanic "tc_iface_decl"
- (text "IfaceBuiltInSynFamTyCon in interface file")
-
-tc_iface_decl _parent _ignore_prags
- (IfaceClass {ifName = tc_name,
- ifRoles = roles,
- ifBinders = binders,
- ifFDs = rdr_fds,
- ifBody = IfAbstractClass})
- = bindIfaceTyConBinders binders $ \ binders' -> do
- { fds <- mapM tc_fd rdr_fds
- ; cls <- buildClass tc_name binders' roles fds Nothing
- ; return (ATyCon (classTyCon cls)) }
-
-tc_iface_decl _parent ignore_prags
- (IfaceClass {ifName = tc_name,
- ifRoles = roles,
- ifBinders = binders,
- ifFDs = rdr_fds,
- ifBody = IfConcreteClass {
- ifClassCtxt = rdr_ctxt,
- ifATs = rdr_ats, ifSigs = rdr_sigs,
- ifMinDef = mindef_occ
- }})
- = bindIfaceTyConBinders binders $ \ binders' -> do
- { traceIf (text "tc-iface-class1" <+> ppr tc_name)
- ; ctxt <- mapM tc_sc rdr_ctxt
- ; traceIf (text "tc-iface-class2" <+> ppr tc_name)
- ; sigs <- mapM tc_sig rdr_sigs
- ; fds <- mapM tc_fd rdr_fds
- ; traceIf (text "tc-iface-class3" <+> ppr tc_name)
- ; mindef <- traverse (lookupIfaceTop . mkVarOccFS) mindef_occ
- ; cls <- fixM $ \ cls -> do
- { ats <- mapM (tc_at cls) rdr_ats
- ; traceIf (text "tc-iface-class4" <+> ppr tc_name)
- ; buildClass tc_name binders' roles fds (Just (ctxt, ats, sigs, mindef)) }
- ; return (ATyCon (classTyCon cls)) }
- where
- tc_sc pred = forkM (mk_sc_doc pred) (tcIfaceType pred)
- -- The *length* of the superclasses is used by buildClass, and hence must
- -- not be inside the thunk. But the *content* maybe recursive and hence
- -- must be lazy (via forkM). Example:
- -- class C (T a) => D a where
- -- data T a
- -- Here the associated type T is knot-tied with the class, and
- -- so we must not pull on T too eagerly. See #5970
-
- tc_sig :: IfaceClassOp -> IfL TcMethInfo
- tc_sig (IfaceClassOp op_name rdr_ty dm)
- = do { let doc = mk_op_doc op_name rdr_ty
- ; op_ty <- forkM (doc <+> text "ty") $ tcIfaceType rdr_ty
- -- Must be done lazily for just the same reason as the
- -- type of a data con; to avoid sucking in types that
- -- it mentions unless it's necessary to do so
- ; dm' <- tc_dm doc dm
- ; return (op_name, op_ty, dm') }
-
- tc_dm :: SDoc
- -> Maybe (DefMethSpec IfaceType)
- -> IfL (Maybe (DefMethSpec (SrcSpan, Type)))
- tc_dm _ Nothing = return Nothing
- tc_dm _ (Just VanillaDM) = return (Just VanillaDM)
- tc_dm doc (Just (GenericDM ty))
- = do { -- Must be done lazily to avoid sucking in types
- ; ty' <- forkM (doc <+> text "dm") $ tcIfaceType ty
- ; return (Just (GenericDM (noSrcSpan, ty'))) }
-
- tc_at cls (IfaceAT tc_decl if_def)
- = do ATyCon tc <- tc_iface_decl (Just cls) ignore_prags tc_decl
- mb_def <- case if_def of
- Nothing -> return Nothing
- Just def -> forkM (mk_at_doc tc) $
- extendIfaceTyVarEnv (tyConTyVars tc) $
- do { tc_def <- tcIfaceType def
- ; return (Just (tc_def, noSrcSpan)) }
- -- Must be done lazily in case the RHS of the defaults mention
- -- the type constructor being defined here
- -- e.g. type AT a; type AT b = AT [b] #8002
- return (ATI tc mb_def)
-
- mk_sc_doc pred = text "Superclass" <+> ppr pred
- mk_at_doc tc = text "Associated type" <+> ppr tc
- mk_op_doc op_name op_ty = text "Class op" <+> sep [ppr op_name, ppr op_ty]
-
-tc_iface_decl _ _ (IfaceAxiom { ifName = tc_name, ifTyCon = tc
- , ifAxBranches = branches, ifRole = role })
- = do { tc_tycon <- tcIfaceTyCon tc
- -- Must be done lazily, because axioms are forced when checking
- -- for family instance consistency, and the RHS may mention
- -- a hs-boot declared type constructor that is going to be
- -- defined by this module.
- -- e.g. type instance F Int = ToBeDefined
- -- See #13803
- ; tc_branches <- forkM (text "Axiom branches" <+> ppr tc_name)
- $ tc_ax_branches branches
- ; let axiom = CoAxiom { co_ax_unique = nameUnique tc_name
- , co_ax_name = tc_name
- , co_ax_tc = tc_tycon
- , co_ax_role = role
- , co_ax_branches = manyBranches tc_branches
- , co_ax_implicit = False }
- ; return (ACoAxiom axiom) }
-
-tc_iface_decl _ _ (IfacePatSyn{ ifName = name
- , ifPatMatcher = if_matcher
- , ifPatBuilder = if_builder
- , ifPatIsInfix = is_infix
- , ifPatUnivBndrs = univ_bndrs
- , ifPatExBndrs = ex_bndrs
- , ifPatProvCtxt = prov_ctxt
- , ifPatReqCtxt = req_ctxt
- , ifPatArgs = args
- , ifPatTy = pat_ty
- , ifFieldLabels = field_labels })
- = do { traceIf (text "tc_iface_decl" <+> ppr name)
- ; matcher <- tc_pr if_matcher
- ; builder <- fmapMaybeM tc_pr if_builder
- ; bindIfaceForAllBndrs univ_bndrs $ \univ_tvs -> do
- { bindIfaceForAllBndrs ex_bndrs $ \ex_tvs -> do
- { patsyn <- forkM (mk_doc name) $
- do { prov_theta <- tcIfaceCtxt prov_ctxt
- ; req_theta <- tcIfaceCtxt req_ctxt
- ; pat_ty <- tcIfaceType pat_ty
- ; arg_tys <- mapM tcIfaceType args
- ; return $ buildPatSyn name is_infix matcher builder
- (univ_tvs, req_theta)
- (ex_tvs, prov_theta)
- arg_tys pat_ty field_labels }
- ; return $ AConLike . PatSynCon $ patsyn }}}
- where
- mk_doc n = text "Pattern synonym" <+> ppr n
- tc_pr :: (IfExtName, Bool) -> IfL (Id, Bool)
- tc_pr (nm, b) = do { id <- forkM (ppr nm) (tcIfaceExtId nm)
- ; return (id, b) }
-
-tc_fd :: FunDep IfLclName -> IfL (FunDep TyVar)
-tc_fd (tvs1, tvs2) = do { tvs1' <- mapM tcIfaceTyVar tvs1
- ; tvs2' <- mapM tcIfaceTyVar tvs2
- ; return (tvs1', tvs2') }
-
-tc_ax_branches :: [IfaceAxBranch] -> IfL [CoAxBranch]
-tc_ax_branches if_branches = foldlM tc_ax_branch [] if_branches
-
-tc_ax_branch :: [CoAxBranch] -> IfaceAxBranch -> IfL [CoAxBranch]
-tc_ax_branch prev_branches
- (IfaceAxBranch { ifaxbTyVars = tv_bndrs
- , ifaxbEtaTyVars = eta_tv_bndrs
- , ifaxbCoVars = cv_bndrs
- , ifaxbLHS = lhs, ifaxbRHS = rhs
- , ifaxbRoles = roles, ifaxbIncomps = incomps })
- = bindIfaceTyConBinders_AT
- (map (\b -> Bndr (IfaceTvBndr b) (NamedTCB Inferred)) tv_bndrs) $ \ tvs ->
- -- The _AT variant is needed here; see Note [CoAxBranch type variables] in CoAxiom
- bindIfaceIds cv_bndrs $ \ cvs -> do
- { tc_lhs <- tcIfaceAppArgs lhs
- ; tc_rhs <- tcIfaceType rhs
- ; eta_tvs <- bindIfaceTyVars eta_tv_bndrs return
- ; this_mod <- getIfModule
- ; let loc = mkGeneralSrcSpan (fsLit "module " `appendFS`
- moduleNameFS (moduleName this_mod))
- br = CoAxBranch { cab_loc = loc
- , cab_tvs = binderVars tvs
- , cab_eta_tvs = eta_tvs
- , cab_cvs = cvs
- , cab_lhs = tc_lhs
- , cab_roles = roles
- , cab_rhs = tc_rhs
- , cab_incomps = map (prev_branches `getNth`) incomps }
- ; return (prev_branches ++ [br]) }
-
-tcIfaceDataCons :: Name -> TyCon -> [TyConBinder] -> IfaceConDecls -> IfL AlgTyConRhs
-tcIfaceDataCons tycon_name tycon tc_tybinders if_cons
- = case if_cons of
- IfAbstractTyCon -> return AbstractTyCon
- IfDataTyCon cons -> do { data_cons <- mapM tc_con_decl cons
- ; return (mkDataTyConRhs data_cons) }
- IfNewTyCon con -> do { data_con <- tc_con_decl con
- ; mkNewTyConRhs tycon_name tycon data_con }
- where
- univ_tvs :: [TyVar]
- univ_tvs = binderVars (tyConTyVarBinders tc_tybinders)
-
- tag_map :: NameEnv ConTag
- tag_map = mkTyConTagMap tycon
-
- tc_con_decl (IfCon { ifConInfix = is_infix,
- ifConExTCvs = ex_bndrs,
- ifConUserTvBinders = user_bndrs,
- ifConName = dc_name,
- ifConCtxt = ctxt, ifConEqSpec = spec,
- ifConArgTys = args, ifConFields = lbl_names,
- ifConStricts = if_stricts,
- ifConSrcStricts = if_src_stricts})
- = -- Universally-quantified tyvars are shared with
- -- parent TyCon, and are already in scope
- bindIfaceBndrs ex_bndrs $ \ ex_tvs -> do
- { traceIf (text "Start interface-file tc_con_decl" <+> ppr dc_name)
-
- -- By this point, we have bound every universal and existential
- -- tyvar. Because of the dcUserTyVarBinders invariant
- -- (see Note [DataCon user type variable binders]), *every* tyvar in
- -- ifConUserTvBinders has a matching counterpart somewhere in the
- -- bound universals/existentials. As a result, calling tcIfaceTyVar
- -- below is always guaranteed to succeed.
- ; user_tv_bndrs <- mapM (\(Bndr bd vis) ->
- case bd of
- IfaceIdBndr (name, _) ->
- Bndr <$> tcIfaceLclId name <*> pure vis
- IfaceTvBndr (name, _) ->
- Bndr <$> tcIfaceTyVar name <*> pure vis)
- user_bndrs
-
- -- Read the context and argument types, but lazily for two reasons
- -- (a) to avoid looking tugging on a recursive use of
- -- the type itself, which is knot-tied
- -- (b) to avoid faulting in the component types unless
- -- they are really needed
- ; ~(eq_spec, theta, arg_tys, stricts) <- forkM (mk_doc dc_name) $
- do { eq_spec <- tcIfaceEqSpec spec
- ; theta <- tcIfaceCtxt ctxt
- -- This fixes #13710. The enclosing lazy thunk gets
- -- forced when typechecking record wildcard pattern
- -- matching (it's not completely clear why this
- -- tuple is needed), which causes trouble if one of
- -- the argument types was recursively defined.
- -- See also Note [Tying the knot]
- ; arg_tys <- forkM (mk_doc dc_name <+> text "arg_tys")
- $ mapM tcIfaceType args
- ; stricts <- mapM tc_strict if_stricts
- -- The IfBang field can mention
- -- the type itself; hence inside forkM
- ; return (eq_spec, theta, arg_tys, stricts) }
-
- -- Remember, tycon is the representation tycon
- ; let orig_res_ty = mkFamilyTyConApp tycon
- (substTyCoVars (mkTvSubstPrs (map eqSpecPair eq_spec))
- (binderVars tc_tybinders))
-
- ; prom_rep_name <- newTyConRepName dc_name
-
- ; con <- buildDataCon (pprPanic "tcIfaceDataCons: FamInstEnvs" (ppr dc_name))
- dc_name is_infix prom_rep_name
- (map src_strict if_src_stricts)
- (Just stricts)
- -- Pass the HsImplBangs (i.e. final
- -- decisions) to buildDataCon; it'll use
- -- these to guide the construction of a
- -- worker.
- -- See Note [Bangs on imported data constructors] in MkId
- lbl_names
- univ_tvs ex_tvs user_tv_bndrs
- eq_spec theta
- arg_tys orig_res_ty tycon tag_map
- ; traceIf (text "Done interface-file tc_con_decl" <+> ppr dc_name)
- ; return con }
- mk_doc con_name = text "Constructor" <+> ppr con_name
-
- tc_strict :: IfaceBang -> IfL HsImplBang
- tc_strict IfNoBang = return (HsLazy)
- tc_strict IfStrict = return (HsStrict)
- tc_strict IfUnpack = return (HsUnpack Nothing)
- tc_strict (IfUnpackCo if_co) = do { co <- tcIfaceCo if_co
- ; return (HsUnpack (Just co)) }
-
- src_strict :: IfaceSrcBang -> HsSrcBang
- src_strict (IfSrcBang unpk bang) = HsSrcBang NoSourceText unpk bang
-
-tcIfaceEqSpec :: IfaceEqSpec -> IfL [EqSpec]
-tcIfaceEqSpec spec
- = mapM do_item spec
- where
- do_item (occ, if_ty) = do { tv <- tcIfaceTyVar occ
- ; ty <- tcIfaceType if_ty
- ; return (mkEqSpec tv ty) }
-
-{-
-Note [Synonym kind loop]
-~~~~~~~~~~~~~~~~~~~~~~~~
-Notice that we eagerly grab the *kind* from the interface file, but
-build a forkM thunk for the *rhs* (and family stuff). To see why,
-consider this (#2412)
-
-M.hs: module M where { import X; data T = MkT S }
-X.hs: module X where { import {-# SOURCE #-} M; type S = T }
-M.hs-boot: module M where { data T }
-
-When kind-checking M.hs we need S's kind. But we do not want to
-find S's kind from (typeKind S-rhs), because we don't want to look at
-S-rhs yet! Since S is imported from X.hi, S gets just one chance to
-be defined, and we must not do that until we've finished with M.T.
-
-Solution: record S's kind in the interface file; now we can safely
-look at it.
-
-************************************************************************
-* *
- Instances
-* *
-************************************************************************
--}
-
-tcIfaceInst :: IfaceClsInst -> IfL ClsInst
-tcIfaceInst (IfaceClsInst { ifDFun = dfun_name, ifOFlag = oflag
- , ifInstCls = cls, ifInstTys = mb_tcs
- , ifInstOrph = orph })
- = do { dfun <- forkM (text "Dict fun" <+> ppr dfun_name) $
- fmap tyThingId (tcIfaceImplicit dfun_name)
- ; let mb_tcs' = map (fmap ifaceTyConName) mb_tcs
- ; return (mkImportedInstance cls mb_tcs' dfun_name dfun oflag orph) }
-
-tcIfaceFamInst :: IfaceFamInst -> IfL FamInst
-tcIfaceFamInst (IfaceFamInst { ifFamInstFam = fam, ifFamInstTys = mb_tcs
- , ifFamInstAxiom = axiom_name } )
- = do { axiom' <- forkM (text "Axiom" <+> ppr axiom_name) $
- tcIfaceCoAxiom axiom_name
- -- will panic if branched, but that's OK
- ; let axiom'' = toUnbranchedAxiom axiom'
- mb_tcs' = map (fmap ifaceTyConName) mb_tcs
- ; return (mkImportedFamInst fam mb_tcs' axiom'') }
-
-{-
-************************************************************************
-* *
- Rules
-* *
-************************************************************************
-
-We move a IfaceRule from eps_rules to eps_rule_base when all its LHS free vars
-are in the type environment. However, remember that typechecking a Rule may
-(as a side effect) augment the type envt, and so we may need to iterate the process.
--}
-
-tcIfaceRules :: Bool -- True <=> ignore rules
- -> [IfaceRule]
- -> IfL [CoreRule]
-tcIfaceRules ignore_prags if_rules
- | ignore_prags = return []
- | otherwise = mapM tcIfaceRule if_rules
-
-tcIfaceRule :: IfaceRule -> IfL CoreRule
-tcIfaceRule (IfaceRule {ifRuleName = name, ifActivation = act, ifRuleBndrs = bndrs,
- ifRuleHead = fn, ifRuleArgs = args, ifRuleRhs = rhs,
- ifRuleAuto = auto, ifRuleOrph = orph })
- = do { ~(bndrs', args', rhs') <-
- -- Typecheck the payload lazily, in the hope it'll never be looked at
- forkM (text "Rule" <+> pprRuleName name) $
- bindIfaceBndrs bndrs $ \ bndrs' ->
- do { args' <- mapM tcIfaceExpr args
- ; rhs' <- tcIfaceExpr rhs
- ; return (bndrs', args', rhs') }
- ; let mb_tcs = map ifTopFreeName args
- ; this_mod <- getIfModule
- ; return (Rule { ru_name = name, ru_fn = fn, ru_act = act,
- ru_bndrs = bndrs', ru_args = args',
- ru_rhs = occurAnalyseExpr rhs',
- ru_rough = mb_tcs,
- ru_origin = this_mod,
- ru_orphan = orph,
- ru_auto = auto,
- ru_local = False }) } -- An imported RULE is never for a local Id
- -- or, even if it is (module loop, perhaps)
- -- we'll just leave it in the non-local set
- where
- -- This function *must* mirror exactly what Rules.roughTopNames does
- -- We could have stored the ru_rough field in the iface file
- -- but that would be redundant, I think.
- -- The only wrinkle is that we must not be deceived by
- -- type synonyms at the top of a type arg. Since
- -- we can't tell at this point, we are careful not
- -- to write them out in coreRuleToIfaceRule
- ifTopFreeName :: IfaceExpr -> Maybe Name
- ifTopFreeName (IfaceType (IfaceTyConApp tc _ )) = Just (ifaceTyConName tc)
- ifTopFreeName (IfaceType (IfaceTupleTy s _ ts)) = Just (tupleTyConName s (length (appArgsIfaceTypes ts)))
- ifTopFreeName (IfaceApp f _) = ifTopFreeName f
- ifTopFreeName (IfaceExt n) = Just n
- ifTopFreeName _ = Nothing
-
-{-
-************************************************************************
-* *
- Annotations
-* *
-************************************************************************
--}
-
-tcIfaceAnnotations :: [IfaceAnnotation] -> IfL [Annotation]
-tcIfaceAnnotations = mapM tcIfaceAnnotation
-
-tcIfaceAnnotation :: IfaceAnnotation -> IfL Annotation
-tcIfaceAnnotation (IfaceAnnotation target serialized) = do
- target' <- tcIfaceAnnTarget target
- return $ Annotation {
- ann_target = target',
- ann_value = serialized
- }
-
-tcIfaceAnnTarget :: IfaceAnnTarget -> IfL (AnnTarget Name)
-tcIfaceAnnTarget (NamedTarget occ) = do
- name <- lookupIfaceTop occ
- return $ NamedTarget name
-tcIfaceAnnTarget (ModuleTarget mod) = do
- return $ ModuleTarget mod
-
-{-
-************************************************************************
-* *
- Complete Match Pragmas
-* *
-************************************************************************
--}
-
-tcIfaceCompleteSigs :: [IfaceCompleteMatch] -> IfL [CompleteMatch]
-tcIfaceCompleteSigs = mapM tcIfaceCompleteSig
-
-tcIfaceCompleteSig :: IfaceCompleteMatch -> IfL CompleteMatch
-tcIfaceCompleteSig (IfaceCompleteMatch ms t) = return (CompleteMatch ms t)
-
-{-
-************************************************************************
-* *
- Types
-* *
-************************************************************************
--}
-
-tcIfaceType :: IfaceType -> IfL Type
-tcIfaceType = go
- where
- go (IfaceTyVar n) = TyVarTy <$> tcIfaceTyVar n
- go (IfaceFreeTyVar n) = pprPanic "tcIfaceType:IfaceFreeTyVar" (ppr n)
- go (IfaceLitTy l) = LitTy <$> tcIfaceTyLit l
- go (IfaceFunTy flag t1 t2) = FunTy flag <$> go t1 <*> go t2
- go (IfaceTupleTy s i tks) = tcIfaceTupleTy s i tks
- go (IfaceAppTy t ts)
- = do { t' <- go t
- ; ts' <- traverse go (appArgsIfaceTypes ts)
- ; pure (foldl' AppTy t' ts') }
- go (IfaceTyConApp tc tks)
- = do { tc' <- tcIfaceTyCon tc
- ; tks' <- mapM go (appArgsIfaceTypes tks)
- ; return (mkTyConApp tc' tks') }
- go (IfaceForAllTy bndr t)
- = bindIfaceForAllBndr bndr $ \ tv' vis ->
- ForAllTy (Bndr tv' vis) <$> go t
- go (IfaceCastTy ty co) = CastTy <$> go ty <*> tcIfaceCo co
- go (IfaceCoercionTy co) = CoercionTy <$> tcIfaceCo co
-
-tcIfaceTupleTy :: TupleSort -> PromotionFlag -> IfaceAppArgs -> IfL Type
-tcIfaceTupleTy sort is_promoted args
- = do { args' <- tcIfaceAppArgs args
- ; let arity = length args'
- ; base_tc <- tcTupleTyCon True sort arity
- ; case is_promoted of
- NotPromoted
- -> return (mkTyConApp base_tc args')
-
- IsPromoted
- -> do { let tc = promoteDataCon (tyConSingleDataCon base_tc)
- kind_args = map typeKind args'
- ; return (mkTyConApp tc (kind_args ++ args')) } }
-
--- See Note [Unboxed tuple RuntimeRep vars] in TyCon
-tcTupleTyCon :: Bool -- True <=> typechecking a *type* (vs. an expr)
- -> TupleSort
- -> Arity -- the number of args. *not* the tuple arity.
- -> IfL TyCon
-tcTupleTyCon in_type sort arity
- = case sort of
- ConstraintTuple -> do { thing <- tcIfaceGlobal (cTupleTyConName arity)
- ; return (tyThingTyCon thing) }
- BoxedTuple -> return (tupleTyCon Boxed arity)
- UnboxedTuple -> return (tupleTyCon Unboxed arity')
- where arity' | in_type = arity `div` 2
- | otherwise = arity
- -- in expressions, we only have term args
-
-tcIfaceAppArgs :: IfaceAppArgs -> IfL [Type]
-tcIfaceAppArgs = mapM tcIfaceType . appArgsIfaceTypes
-
------------------------------------------
-tcIfaceCtxt :: IfaceContext -> IfL ThetaType
-tcIfaceCtxt sts = mapM tcIfaceType sts
-
------------------------------------------
-tcIfaceTyLit :: IfaceTyLit -> IfL TyLit
-tcIfaceTyLit (IfaceNumTyLit n) = return (NumTyLit n)
-tcIfaceTyLit (IfaceStrTyLit n) = return (StrTyLit n)
-
-{-
-%************************************************************************
-%* *
- Coercions
-* *
-************************************************************************
--}
-
-tcIfaceCo :: IfaceCoercion -> IfL Coercion
-tcIfaceCo = go
- where
- go_mco IfaceMRefl = pure MRefl
- go_mco (IfaceMCo co) = MCo <$> (go co)
-
- go (IfaceReflCo t) = Refl <$> tcIfaceType t
- go (IfaceGReflCo r t mco) = GRefl r <$> tcIfaceType t <*> go_mco mco
- go (IfaceFunCo r c1 c2) = mkFunCo r <$> go c1 <*> go c2
- go (IfaceTyConAppCo r tc cs)
- = TyConAppCo r <$> tcIfaceTyCon tc <*> mapM go cs
- go (IfaceAppCo c1 c2) = AppCo <$> go c1 <*> go c2
- go (IfaceForAllCo tv k c) = do { k' <- go k
- ; bindIfaceBndr tv $ \ tv' ->
- ForAllCo tv' k' <$> go c }
- go (IfaceCoVarCo n) = CoVarCo <$> go_var n
- go (IfaceAxiomInstCo n i cs) = AxiomInstCo <$> tcIfaceCoAxiom n <*> pure i <*> mapM go cs
- go (IfaceUnivCo p r t1 t2) = UnivCo <$> tcIfaceUnivCoProv p <*> pure r
- <*> tcIfaceType t1 <*> tcIfaceType t2
- go (IfaceSymCo c) = SymCo <$> go c
- go (IfaceTransCo c1 c2) = TransCo <$> go c1
- <*> go c2
- go (IfaceInstCo c1 t2) = InstCo <$> go c1
- <*> go t2
- go (IfaceNthCo d c) = do { c' <- go c
- ; return $ mkNthCo (nthCoRole d c') d c' }
- go (IfaceLRCo lr c) = LRCo lr <$> go c
- go (IfaceKindCo c) = KindCo <$> go c
- go (IfaceSubCo c) = SubCo <$> go c
- go (IfaceAxiomRuleCo ax cos) = AxiomRuleCo <$> tcIfaceCoAxiomRule ax
- <*> mapM go cos
- go (IfaceFreeCoVar c) = pprPanic "tcIfaceCo:IfaceFreeCoVar" (ppr c)
- go (IfaceHoleCo c) = pprPanic "tcIfaceCo:IfaceHoleCo" (ppr c)
-
- go_var :: FastString -> IfL CoVar
- go_var = tcIfaceLclId
-
-tcIfaceUnivCoProv :: IfaceUnivCoProv -> IfL UnivCoProvenance
-tcIfaceUnivCoProv IfaceUnsafeCoerceProv = return UnsafeCoerceProv
-tcIfaceUnivCoProv (IfacePhantomProv kco) = PhantomProv <$> tcIfaceCo kco
-tcIfaceUnivCoProv (IfaceProofIrrelProv kco) = ProofIrrelProv <$> tcIfaceCo kco
-tcIfaceUnivCoProv (IfacePluginProv str) = return $ PluginProv str
-
-{-
-************************************************************************
-* *
- Core
-* *
-************************************************************************
--}
-
-tcIfaceExpr :: IfaceExpr -> IfL CoreExpr
-tcIfaceExpr (IfaceType ty)
- = Type <$> tcIfaceType ty
-
-tcIfaceExpr (IfaceCo co)
- = Coercion <$> tcIfaceCo co
-
-tcIfaceExpr (IfaceCast expr co)
- = Cast <$> tcIfaceExpr expr <*> tcIfaceCo co
-
-tcIfaceExpr (IfaceLcl name)
- = Var <$> tcIfaceLclId name
-
-tcIfaceExpr (IfaceExt gbl)
- = Var <$> tcIfaceExtId gbl
-
-tcIfaceExpr (IfaceLit lit)
- = do lit' <- tcIfaceLit lit
- return (Lit lit')
-
-tcIfaceExpr (IfaceFCall cc ty) = do
- ty' <- tcIfaceType ty
- u <- newUnique
- dflags <- getDynFlags
- return (Var (mkFCallId dflags u cc ty'))
-
-tcIfaceExpr (IfaceTuple sort args)
- = do { args' <- mapM tcIfaceExpr args
- ; tc <- tcTupleTyCon False sort arity
- ; let con_tys = map exprType args'
- some_con_args = map Type con_tys ++ args'
- con_args = case sort of
- UnboxedTuple -> map (Type . getRuntimeRep) con_tys ++ some_con_args
- _ -> some_con_args
- -- Put the missing type arguments back in
- con_id = dataConWorkId (tyConSingleDataCon tc)
- ; return (mkApps (Var con_id) con_args) }
- where
- arity = length args
-
-tcIfaceExpr (IfaceLam (bndr, os) body)
- = bindIfaceBndr bndr $ \bndr' ->
- Lam (tcIfaceOneShot os bndr') <$> tcIfaceExpr body
- where
- tcIfaceOneShot IfaceOneShot b = setOneShotLambda b
- tcIfaceOneShot _ b = b
-
-tcIfaceExpr (IfaceApp fun arg)
- = App <$> tcIfaceExpr fun <*> tcIfaceExpr arg
-
-tcIfaceExpr (IfaceECase scrut ty)
- = do { scrut' <- tcIfaceExpr scrut
- ; ty' <- tcIfaceType ty
- ; return (castBottomExpr scrut' ty') }
-
-tcIfaceExpr (IfaceCase scrut case_bndr alts) = do
- scrut' <- tcIfaceExpr scrut
- case_bndr_name <- newIfaceName (mkVarOccFS case_bndr)
- let
- scrut_ty = exprType scrut'
- case_bndr' = mkLocalIdOrCoVar case_bndr_name scrut_ty
- -- "OrCoVar" since a coercion can be a scrutinee with -fdefer-type-errors
- -- (e.g. see test T15695). Ticket #17291 covers fixing this problem.
- tc_app = splitTyConApp scrut_ty
- -- NB: Won't always succeed (polymorphic case)
- -- but won't be demanded in those cases
- -- NB: not tcSplitTyConApp; we are looking at Core here
- -- look through non-rec newtypes to find the tycon that
- -- corresponds to the datacon in this case alternative
-
- extendIfaceIdEnv [case_bndr'] $ do
- alts' <- mapM (tcIfaceAlt scrut' tc_app) alts
- return (Case scrut' case_bndr' (coreAltsType alts') alts')
-
-tcIfaceExpr (IfaceLet (IfaceNonRec (IfLetBndr fs ty info ji) rhs) body)
- = do { name <- newIfaceName (mkVarOccFS fs)
- ; ty' <- tcIfaceType ty
- ; id_info <- tcIdInfo False {- Don't ignore prags; we are inside one! -}
- NotTopLevel name ty' info
- ; let id = mkLocalIdWithInfo name ty' id_info
- `asJoinId_maybe` tcJoinInfo ji
- ; rhs' <- tcIfaceExpr rhs
- ; body' <- extendIfaceIdEnv [id] (tcIfaceExpr body)
- ; return (Let (NonRec id rhs') body') }
-
-tcIfaceExpr (IfaceLet (IfaceRec pairs) body)
- = do { ids <- mapM tc_rec_bndr (map fst pairs)
- ; extendIfaceIdEnv ids $ do
- { pairs' <- zipWithM tc_pair pairs ids
- ; body' <- tcIfaceExpr body
- ; return (Let (Rec pairs') body') } }
- where
- tc_rec_bndr (IfLetBndr fs ty _ ji)
- = do { name <- newIfaceName (mkVarOccFS fs)
- ; ty' <- tcIfaceType ty
- ; return (mkLocalId name ty' `asJoinId_maybe` tcJoinInfo ji) }
- tc_pair (IfLetBndr _ _ info _, rhs) id
- = do { rhs' <- tcIfaceExpr rhs
- ; id_info <- tcIdInfo False {- Don't ignore prags; we are inside one! -}
- NotTopLevel (idName id) (idType id) info
- ; return (setIdInfo id id_info, rhs') }
-
-tcIfaceExpr (IfaceTick tickish expr) = do
- expr' <- tcIfaceExpr expr
- -- If debug flag is not set: Ignore source notes
- dbgLvl <- fmap debugLevel getDynFlags
- case tickish of
- IfaceSource{} | dbgLvl == 0
- -> return expr'
- _otherwise -> do
- tickish' <- tcIfaceTickish tickish
- return (Tick tickish' expr')
-
--------------------------
-tcIfaceTickish :: IfaceTickish -> IfM lcl (Tickish Id)
-tcIfaceTickish (IfaceHpcTick modl ix) = return (HpcTick modl ix)
-tcIfaceTickish (IfaceSCC cc tick push) = return (ProfNote cc tick push)
-tcIfaceTickish (IfaceSource src name) = return (SourceNote src name)
-
--------------------------
-tcIfaceLit :: Literal -> IfL Literal
--- Integer literals deserialise to (LitInteger i <error thunk>)
--- so tcIfaceLit just fills in the type.
--- See Note [Integer literals] in Literal
-tcIfaceLit (LitNumber LitNumInteger i _)
- = do t <- tcIfaceTyConByName integerTyConName
- return (mkLitInteger i (mkTyConTy t))
--- Natural literals deserialise to (LitNatural i <error thunk>)
--- so tcIfaceLit just fills in the type.
--- See Note [Natural literals] in Literal
-tcIfaceLit (LitNumber LitNumNatural i _)
- = do t <- tcIfaceTyConByName naturalTyConName
- return (mkLitNatural i (mkTyConTy t))
-tcIfaceLit lit = return lit
-
--------------------------
-tcIfaceAlt :: CoreExpr -> (TyCon, [Type])
- -> (IfaceConAlt, [FastString], IfaceExpr)
- -> IfL (AltCon, [TyVar], CoreExpr)
-tcIfaceAlt _ _ (IfaceDefault, names, rhs)
- = ASSERT( null names ) do
- rhs' <- tcIfaceExpr rhs
- return (DEFAULT, [], rhs')
-
-tcIfaceAlt _ _ (IfaceLitAlt lit, names, rhs)
- = ASSERT( null names ) do
- lit' <- tcIfaceLit lit
- rhs' <- tcIfaceExpr rhs
- return (LitAlt lit', [], rhs')
-
--- A case alternative is made quite a bit more complicated
--- by the fact that we omit type annotations because we can
--- work them out. True enough, but its not that easy!
-tcIfaceAlt scrut (tycon, inst_tys) (IfaceDataAlt data_occ, arg_strs, rhs)
- = do { con <- tcIfaceDataCon data_occ
- ; when (debugIsOn && not (con `elem` tyConDataCons tycon))
- (failIfM (ppr scrut $$ ppr con $$ ppr tycon $$ ppr (tyConDataCons tycon)))
- ; tcIfaceDataAlt con inst_tys arg_strs rhs }
-
-tcIfaceDataAlt :: DataCon -> [Type] -> [FastString] -> IfaceExpr
- -> IfL (AltCon, [TyVar], CoreExpr)
-tcIfaceDataAlt con inst_tys arg_strs rhs
- = do { us <- newUniqueSupply
- ; let uniqs = uniqsFromSupply us
- ; let (ex_tvs, arg_ids)
- = dataConRepFSInstPat arg_strs uniqs con inst_tys
-
- ; rhs' <- extendIfaceEnvs ex_tvs $
- extendIfaceIdEnv arg_ids $
- tcIfaceExpr rhs
- ; return (DataAlt con, ex_tvs ++ arg_ids, rhs') }
-
-{-
-************************************************************************
-* *
- IdInfo
-* *
-************************************************************************
--}
-
-tcIdDetails :: Type -> IfaceIdDetails -> IfL IdDetails
-tcIdDetails _ IfVanillaId = return VanillaId
-tcIdDetails ty IfDFunId
- = return (DFunId (isNewTyCon (classTyCon cls)))
- where
- (_, _, cls, _) = tcSplitDFunTy ty
-
-tcIdDetails _ (IfRecSelId tc naughty)
- = do { tc' <- either (fmap RecSelData . tcIfaceTyCon)
- (fmap (RecSelPatSyn . tyThingPatSyn) . tcIfaceDecl False)
- tc
- ; return (RecSelId { sel_tycon = tc', sel_naughty = naughty }) }
- where
- tyThingPatSyn (AConLike (PatSynCon ps)) = ps
- tyThingPatSyn _ = panic "tcIdDetails: expecting patsyn"
-
-tcIdInfo :: Bool -> TopLevelFlag -> Name -> Type -> IfaceIdInfo -> IfL IdInfo
-tcIdInfo ignore_prags toplvl name ty info = do
- lcl_env <- getLclEnv
- -- Set the CgInfo to something sensible but uninformative before
- -- we start; default assumption is that it has CAFs
- let init_info | if_boot lcl_env = vanillaIdInfo `setUnfoldingInfo` BootUnfolding
- | otherwise = vanillaIdInfo
- if ignore_prags
- then return init_info
- else case info of
- NoInfo -> return init_info
- HasInfo info -> foldlM tcPrag init_info info
- where
- tcPrag :: IdInfo -> IfaceInfoItem -> IfL IdInfo
- tcPrag info HsNoCafRefs = return (info `setCafInfo` NoCafRefs)
- tcPrag info (HsArity arity) = return (info `setArityInfo` arity)
- tcPrag info (HsStrictness str) = return (info `setStrictnessInfo` str)
- tcPrag info (HsInline prag) = return (info `setInlinePragInfo` prag)
- tcPrag info HsLevity = return (info `setNeverLevPoly` ty)
-
- -- The next two are lazy, so they don't transitively suck stuff in
- tcPrag info (HsUnfold lb if_unf)
- = do { unf <- tcUnfolding toplvl name ty info if_unf
- ; let info1 | lb = info `setOccInfo` strongLoopBreaker
- | otherwise = info
- ; return (info1 `setUnfoldingInfo` unf) }
-
-tcJoinInfo :: IfaceJoinInfo -> Maybe JoinArity
-tcJoinInfo (IfaceJoinPoint ar) = Just ar
-tcJoinInfo IfaceNotJoinPoint = Nothing
-
-tcUnfolding :: TopLevelFlag -> Name -> Type -> IdInfo -> IfaceUnfolding -> IfL Unfolding
-tcUnfolding toplvl name _ info (IfCoreUnfold stable if_expr)
- = do { dflags <- getDynFlags
- ; mb_expr <- tcPragExpr toplvl name if_expr
- ; let unf_src | stable = InlineStable
- | otherwise = InlineRhs
- ; return $ case mb_expr of
- Nothing -> NoUnfolding
- Just expr -> mkUnfolding dflags unf_src
- True {- Top level -}
- (isBottomingSig strict_sig)
- expr
- }
- where
- -- Strictness should occur before unfolding!
- strict_sig = strictnessInfo info
-tcUnfolding toplvl name _ _ (IfCompulsory if_expr)
- = do { mb_expr <- tcPragExpr toplvl name if_expr
- ; return (case mb_expr of
- Nothing -> NoUnfolding
- Just expr -> mkCompulsoryUnfolding expr) }
-
-tcUnfolding toplvl name _ _ (IfInlineRule arity unsat_ok boring_ok if_expr)
- = do { mb_expr <- tcPragExpr toplvl name if_expr
- ; return (case mb_expr of
- Nothing -> NoUnfolding
- Just expr -> mkCoreUnfolding InlineStable True expr guidance )}
- where
- guidance = UnfWhen { ug_arity = arity, ug_unsat_ok = unsat_ok, ug_boring_ok = boring_ok }
-
-tcUnfolding _toplvl name dfun_ty _ (IfDFunUnfold bs ops)
- = bindIfaceBndrs bs $ \ bs' ->
- do { mb_ops1 <- forkM_maybe doc $ mapM tcIfaceExpr ops
- ; return (case mb_ops1 of
- Nothing -> noUnfolding
- Just ops1 -> mkDFunUnfolding bs' (classDataCon cls) ops1) }
- where
- doc = text "Class ops for dfun" <+> ppr name
- (_, _, cls, _) = tcSplitDFunTy dfun_ty
-
-{-
-For unfoldings we try to do the job lazily, so that we never type check
-an unfolding that isn't going to be looked at.
--}
-
-tcPragExpr :: TopLevelFlag -> Name -> IfaceExpr -> IfL (Maybe CoreExpr)
-tcPragExpr toplvl name expr
- = forkM_maybe doc $ do
- core_expr' <- tcIfaceExpr expr
-
- -- Check for type consistency in the unfolding
- -- See Note [Linting Unfoldings from Interfaces]
- when (isTopLevel toplvl) $ whenGOptM Opt_DoCoreLinting $ do
- in_scope <- get_in_scope
- dflags <- getDynFlags
- case lintUnfolding dflags noSrcLoc in_scope core_expr' of
- Nothing -> return ()
- Just fail_msg -> do { mod <- getIfModule
- ; pprPanic "Iface Lint failure"
- (vcat [ text "In interface for" <+> ppr mod
- , hang doc 2 fail_msg
- , ppr name <+> equals <+> ppr core_expr'
- , text "Iface expr =" <+> ppr expr ]) }
- return core_expr'
- where
- doc = text "Unfolding of" <+> ppr name
-
- get_in_scope :: IfL VarSet -- Totally disgusting; but just for linting
- get_in_scope
- = do { (gbl_env, lcl_env) <- getEnvs
- ; rec_ids <- case if_rec_types gbl_env of
- Nothing -> return []
- Just (_, get_env) -> do
- { type_env <- setLclEnv () get_env
- ; return (typeEnvIds type_env) }
- ; return (bindingsVars (if_tv_env lcl_env) `unionVarSet`
- bindingsVars (if_id_env lcl_env) `unionVarSet`
- mkVarSet rec_ids) }
-
- bindingsVars :: FastStringEnv Var -> VarSet
- bindingsVars ufm = mkVarSet $ nonDetEltsUFM ufm
- -- It's OK to use nonDetEltsUFM here because we immediately forget
- -- the ordering by creating a set
-
-{-
-************************************************************************
-* *
- Getting from Names to TyThings
-* *
-************************************************************************
--}
-
-tcIfaceGlobal :: Name -> IfL TyThing
-tcIfaceGlobal name
- | Just thing <- wiredInNameTyThing_maybe name
- -- Wired-in things include TyCons, DataCons, and Ids
- -- Even though we are in an interface file, we want to make
- -- sure the instances and RULES of this thing (particularly TyCon) are loaded
- -- Imagine: f :: Double -> Double
- = do { ifCheckWiredInThing thing; return thing }
-
- | otherwise
- = do { env <- getGblEnv
- ; case if_rec_types env of { -- Note [Tying the knot]
- Just (mod, get_type_env)
- | nameIsLocalOrFrom mod name
- -> do -- It's defined in the module being compiled
- { type_env <- setLclEnv () get_type_env -- yuk
- ; case lookupNameEnv type_env name of
- Just thing -> return thing
- -- See Note [Knot-tying fallback on boot]
- Nothing -> via_external
- }
-
- ; _ -> via_external }}
- where
- via_external = do
- { hsc_env <- getTopEnv
- ; mb_thing <- liftIO (lookupTypeHscEnv hsc_env name)
- ; case mb_thing of {
- Just thing -> return thing ;
- Nothing -> do
-
- { mb_thing <- importDecl name -- It's imported; go get it
- ; case mb_thing of
- Failed err -> failIfM err
- Succeeded thing -> return thing
- }}}
-
--- Note [Tying the knot]
--- ~~~~~~~~~~~~~~~~~~~~~
--- The if_rec_types field is used when we are compiling M.hs, which indirectly
--- imports Foo.hi, which mentions M.T Then we look up M.T in M's type
--- environment, which is splatted into if_rec_types after we've built M's type
--- envt.
---
--- This is a dark and complicated part of GHC type checking, with a lot
--- of moving parts. Interested readers should also look at:
---
--- * Note [Knot-tying typecheckIface]
--- * Note [DFun knot-tying]
--- * Note [hsc_type_env_var hack]
--- * Note [Knot-tying fallback on boot]
---
--- There is also a wiki page on the subject, see:
---
--- https://gitlab.haskell.org/ghc/ghc/wikis/commentary/compiler/tying-the-knot
-
--- Note [Knot-tying fallback on boot]
--- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
--- Suppose that you are typechecking A.hs, which transitively imports,
--- via B.hs, A.hs-boot. When we poke on B.hs and discover that it
--- has a reference to a type T from A, what TyThing should we wire
--- it up with? Clearly, if we have already typechecked T and
--- added it into the type environment, we should go ahead and use that
--- type. But what if we haven't typechecked it yet?
---
--- For the longest time, GHC adopted the policy that this was
--- *an error condition*; that you MUST NEVER poke on B.hs's reference
--- to a T defined in A.hs until A.hs has gotten around to kind-checking
--- T and adding it to the env. However, actually ensuring this is the
--- case has proven to be a bug farm, because it's really difficult to
--- actually ensure this never happens. The problem was especially poignant
--- with type family consistency checks, which eagerly happen before any
--- typechecking takes place.
---
--- Today, we take a different strategy: if we ever try to access
--- an entity from A which doesn't exist, we just fall back on the
--- definition of A from the hs-boot file. This is complicated in
--- its own way: it means that you may end up with a mix of A.hs and
--- A.hs-boot TyThings during the course of typechecking. We don't
--- think (and have not observed) any cases where this would cause
--- problems, but the hypothetical situation one might worry about
--- is something along these lines in Core:
---
--- case x of
--- A -> e1
--- B -> e2
---
--- If, when typechecking this, we find x :: T, and the T we are hooked
--- up with is the abstract one from the hs-boot file, rather than the
--- one defined in this module with constructors A and B. But it's hard
--- to see how this could happen, especially because the reference to
--- the constructor (A and B) means that GHC will always typecheck
--- this expression *after* typechecking T.
-
-tcIfaceTyConByName :: IfExtName -> IfL TyCon
-tcIfaceTyConByName name
- = do { thing <- tcIfaceGlobal name
- ; return (tyThingTyCon thing) }
-
-tcIfaceTyCon :: IfaceTyCon -> IfL TyCon
-tcIfaceTyCon (IfaceTyCon name info)
- = do { thing <- tcIfaceGlobal name
- ; return $ case ifaceTyConIsPromoted info of
- NotPromoted -> tyThingTyCon thing
- IsPromoted -> promoteDataCon $ tyThingDataCon thing }
-
-tcIfaceCoAxiom :: Name -> IfL (CoAxiom Branched)
-tcIfaceCoAxiom name = do { thing <- tcIfaceImplicit name
- ; return (tyThingCoAxiom thing) }
-
-
-tcIfaceCoAxiomRule :: IfLclName -> IfL CoAxiomRule
--- Unlike CoAxioms, which arise form user 'type instance' declarations,
--- there are a fixed set of CoAxiomRules,
--- currently enumerated in typeNatCoAxiomRules
-tcIfaceCoAxiomRule n
- = case Map.lookup n typeNatCoAxiomRules of
- Just ax -> return ax
- _ -> pprPanic "tcIfaceCoAxiomRule" (ppr n)
-
-tcIfaceDataCon :: Name -> IfL DataCon
-tcIfaceDataCon name = do { thing <- tcIfaceGlobal name
- ; case thing of
- AConLike (RealDataCon dc) -> return dc
- _ -> pprPanic "tcIfaceExtDC" (ppr name$$ ppr thing) }
-
-tcIfaceExtId :: Name -> IfL Id
-tcIfaceExtId name = do { thing <- tcIfaceGlobal name
- ; case thing of
- AnId id -> return id
- _ -> pprPanic "tcIfaceExtId" (ppr name$$ ppr thing) }
-
--- See Note [Resolving never-exported Names in TcIface]
-tcIfaceImplicit :: Name -> IfL TyThing
-tcIfaceImplicit n = do
- lcl_env <- getLclEnv
- case if_implicits_env lcl_env of
- Nothing -> tcIfaceGlobal n
- Just tenv ->
- case lookupTypeEnv tenv n of
- Nothing -> pprPanic "tcIfaceInst" (ppr n $$ ppr tenv)
- Just tything -> return tything
-
-{-
-************************************************************************
-* *
- Bindings
-* *
-************************************************************************
--}
-
-bindIfaceId :: IfaceIdBndr -> (Id -> IfL a) -> IfL a
-bindIfaceId (fs, ty) thing_inside
- = do { name <- newIfaceName (mkVarOccFS fs)
- ; ty' <- tcIfaceType ty
- ; let id = mkLocalIdOrCoVar name ty'
- -- We should not have "OrCoVar" here, this is a bug (#17545)
- ; extendIfaceIdEnv [id] (thing_inside id) }
-
-bindIfaceIds :: [IfaceIdBndr] -> ([Id] -> IfL a) -> IfL a
-bindIfaceIds [] thing_inside = thing_inside []
-bindIfaceIds (b:bs) thing_inside
- = bindIfaceId b $ \b' ->
- bindIfaceIds bs $ \bs' ->
- thing_inside (b':bs')
-
-bindIfaceBndr :: IfaceBndr -> (CoreBndr -> IfL a) -> IfL a
-bindIfaceBndr (IfaceIdBndr bndr) thing_inside
- = bindIfaceId bndr thing_inside
-bindIfaceBndr (IfaceTvBndr bndr) thing_inside
- = bindIfaceTyVar bndr thing_inside
-
-bindIfaceBndrs :: [IfaceBndr] -> ([CoreBndr] -> IfL a) -> IfL a
-bindIfaceBndrs [] thing_inside = thing_inside []
-bindIfaceBndrs (b:bs) thing_inside
- = bindIfaceBndr b $ \ b' ->
- bindIfaceBndrs bs $ \ bs' ->
- thing_inside (b':bs')
-
------------------------
-bindIfaceForAllBndrs :: [IfaceForAllBndr] -> ([TyCoVarBinder] -> IfL a) -> IfL a
-bindIfaceForAllBndrs [] thing_inside = thing_inside []
-bindIfaceForAllBndrs (bndr:bndrs) thing_inside
- = bindIfaceForAllBndr bndr $ \tv vis ->
- bindIfaceForAllBndrs bndrs $ \bndrs' ->
- thing_inside (mkTyCoVarBinder vis tv : bndrs')
-
-bindIfaceForAllBndr :: IfaceForAllBndr -> (TyCoVar -> ArgFlag -> IfL a) -> IfL a
-bindIfaceForAllBndr (Bndr (IfaceTvBndr tv) vis) thing_inside
- = bindIfaceTyVar tv $ \tv' -> thing_inside tv' vis
-bindIfaceForAllBndr (Bndr (IfaceIdBndr tv) vis) thing_inside
- = bindIfaceId tv $ \tv' -> thing_inside tv' vis
-
-bindIfaceTyVar :: IfaceTvBndr -> (TyVar -> IfL a) -> IfL a
-bindIfaceTyVar (occ,kind) thing_inside
- = do { name <- newIfaceName (mkTyVarOccFS occ)
- ; tyvar <- mk_iface_tyvar name kind
- ; extendIfaceTyVarEnv [tyvar] (thing_inside tyvar) }
-
-bindIfaceTyVars :: [IfaceTvBndr] -> ([TyVar] -> IfL a) -> IfL a
-bindIfaceTyVars [] thing_inside = thing_inside []
-bindIfaceTyVars (bndr:bndrs) thing_inside
- = bindIfaceTyVar bndr $ \tv ->
- bindIfaceTyVars bndrs $ \tvs ->
- thing_inside (tv : tvs)
-
-mk_iface_tyvar :: Name -> IfaceKind -> IfL TyVar
-mk_iface_tyvar name ifKind
- = do { kind <- tcIfaceType ifKind
- ; return (Var.mkTyVar name kind) }
-
-bindIfaceTyConBinders :: [IfaceTyConBinder]
- -> ([TyConBinder] -> IfL a) -> IfL a
-bindIfaceTyConBinders [] thing_inside = thing_inside []
-bindIfaceTyConBinders (b:bs) thing_inside
- = bindIfaceTyConBinderX bindIfaceBndr b $ \ b' ->
- bindIfaceTyConBinders bs $ \ bs' ->
- thing_inside (b':bs')
-
-bindIfaceTyConBinders_AT :: [IfaceTyConBinder]
- -> ([TyConBinder] -> IfL a) -> IfL a
--- Used for type variable in nested associated data/type declarations
--- where some of the type variables are already in scope
--- class C a where { data T a b }
--- Here 'a' is in scope when we look at the 'data T'
-bindIfaceTyConBinders_AT [] thing_inside
- = thing_inside []
-bindIfaceTyConBinders_AT (b : bs) thing_inside
- = bindIfaceTyConBinderX bind_tv b $ \b' ->
- bindIfaceTyConBinders_AT bs $ \bs' ->
- thing_inside (b':bs')
- where
- bind_tv tv thing
- = do { mb_tv <- lookupIfaceVar tv
- ; case mb_tv of
- Just b' -> thing b'
- Nothing -> bindIfaceBndr tv thing }
-
-bindIfaceTyConBinderX :: (IfaceBndr -> (TyCoVar -> IfL a) -> IfL a)
- -> IfaceTyConBinder
- -> (TyConBinder -> IfL a) -> IfL a
-bindIfaceTyConBinderX bind_tv (Bndr tv vis) thing_inside
- = bind_tv tv $ \tv' ->
- thing_inside (Bndr tv' vis)
diff --git a/compiler/iface/TcIface.hs-boot b/compiler/iface/TcIface.hs-boot
deleted file mode 100644
index f137f13305..0000000000
--- a/compiler/iface/TcIface.hs-boot
+++ /dev/null
@@ -1,19 +0,0 @@
-module TcIface where
-
-import GhcPrelude
-import IfaceSyn ( IfaceDecl, IfaceClsInst, IfaceFamInst, IfaceRule,
- IfaceAnnotation, IfaceCompleteMatch )
-import TyCoRep ( TyThing )
-import TcRnTypes ( IfL )
-import InstEnv ( ClsInst )
-import FamInstEnv ( FamInst )
-import CoreSyn ( CoreRule )
-import HscTypes ( CompleteMatch )
-import Annotations ( Annotation )
-
-tcIfaceDecl :: Bool -> IfaceDecl -> IfL TyThing
-tcIfaceRules :: Bool -> [IfaceRule] -> IfL [CoreRule]
-tcIfaceInst :: IfaceClsInst -> IfL ClsInst
-tcIfaceFamInst :: IfaceFamInst -> IfL FamInst
-tcIfaceAnnotations :: [IfaceAnnotation] -> IfL [Annotation]
-tcIfaceCompleteSigs :: [IfaceCompleteMatch] -> IfL [CompleteMatch]
diff --git a/compiler/iface/ToIface.hs b/compiler/iface/ToIface.hs
deleted file mode 100644
index d32a0529af..0000000000
--- a/compiler/iface/ToIface.hs
+++ /dev/null
@@ -1,684 +0,0 @@
-{-# LANGUAGE CPP #-}
-{-# LANGUAGE Strict #-} -- See Note [Avoiding space leaks in toIface*]
-
--- | Functions for converting Core things to interface file things.
-module ToIface
- ( -- * Binders
- toIfaceTvBndr
- , toIfaceTvBndrs
- , toIfaceIdBndr
- , toIfaceBndr
- , toIfaceForAllBndr
- , toIfaceTyCoVarBinders
- , toIfaceTyVar
- -- * Types
- , toIfaceType, toIfaceTypeX
- , toIfaceKind
- , toIfaceTcArgs
- , toIfaceTyCon
- , toIfaceTyCon_name
- , toIfaceTyLit
- -- * Tidying types
- , tidyToIfaceType
- , tidyToIfaceContext
- , tidyToIfaceTcArgs
- -- * Coercions
- , toIfaceCoercion, toIfaceCoercionX
- -- * Pattern synonyms
- , patSynToIfaceDecl
- -- * Expressions
- , toIfaceExpr
- , toIfaceBang
- , toIfaceSrcBang
- , toIfaceLetBndr
- , toIfaceIdDetails
- , toIfaceIdInfo
- , toIfUnfolding
- , toIfaceOneShot
- , toIfaceTickish
- , toIfaceBind
- , toIfaceAlt
- , toIfaceCon
- , toIfaceApp
- , toIfaceVar
- ) where
-
-#include "HsVersions.h"
-
-import GhcPrelude
-
-import IfaceSyn
-import DataCon
-import Id
-import IdInfo
-import CoreSyn
-import TyCon hiding ( pprPromotionQuote )
-import CoAxiom
-import TysPrim ( eqPrimTyCon, eqReprPrimTyCon )
-import TysWiredIn ( heqTyCon )
-import MkId ( noinlineIdName )
-import PrelNames
-import Name
-import BasicTypes
-import Type
-import PatSyn
-import Outputable
-import FastString
-import Util
-import Var
-import VarEnv
-import VarSet
-import TyCoRep
-import TyCoTidy ( tidyCo )
-import Demand ( isTopSig )
-
-import Data.Maybe ( catMaybes )
-
-{- Note [Avoiding space leaks in toIface*]
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Building a interface file depends on the output of the simplifier.
-If we build these lazily this would mean keeping the Core AST alive
-much longer than necessary causing a space "leak".
-
-This happens for example when we only write the interface file to disk
-after code gen has run, in which case we might carry megabytes of core
-AST in the heap which is no longer needed.
-
-We avoid this in two ways.
-* First we use -XStrict in ToIface which avoids many thunks to begin with.
-* Second we define NFData instance for IFaceSyn and use them to
- force any remaining thunks.
-
--XStrict is not sufficient as patterns of the form `f (g x)` would still
-result in a thunk being allocated for `g x`.
-
-NFData is sufficient for the space leak, but using -XStrict reduces allocation
-by ~0.1% when compiling with -O. (nofib/spectral/simple, T10370).
-It's essentially free performance hence we use -XStrict on top of NFData.
-
-MR !1633 on gitlab, has more discussion on the topic.
--}
-
-----------------
-toIfaceTvBndr :: TyVar -> IfaceTvBndr
-toIfaceTvBndr = toIfaceTvBndrX emptyVarSet
-
-toIfaceTvBndrX :: VarSet -> TyVar -> IfaceTvBndr
-toIfaceTvBndrX fr tyvar = ( occNameFS (getOccName tyvar)
- , toIfaceTypeX fr (tyVarKind tyvar)
- )
-
-toIfaceTvBndrs :: [TyVar] -> [IfaceTvBndr]
-toIfaceTvBndrs = map toIfaceTvBndr
-
-toIfaceIdBndr :: Id -> IfaceIdBndr
-toIfaceIdBndr = toIfaceIdBndrX emptyVarSet
-
-toIfaceIdBndrX :: VarSet -> CoVar -> IfaceIdBndr
-toIfaceIdBndrX fr covar = ( occNameFS (getOccName covar)
- , toIfaceTypeX fr (varType covar)
- )
-
-toIfaceBndr :: Var -> IfaceBndr
-toIfaceBndr var
- | isId var = IfaceIdBndr (toIfaceIdBndr var)
- | otherwise = IfaceTvBndr (toIfaceTvBndr var)
-
-toIfaceBndrX :: VarSet -> Var -> IfaceBndr
-toIfaceBndrX fr var
- | isId var = IfaceIdBndr (toIfaceIdBndrX fr var)
- | otherwise = IfaceTvBndr (toIfaceTvBndrX fr var)
-
-toIfaceTyCoVarBinder :: VarBndr Var vis -> VarBndr IfaceBndr vis
-toIfaceTyCoVarBinder (Bndr tv vis) = Bndr (toIfaceBndr tv) vis
-
-toIfaceTyCoVarBinders :: [VarBndr Var vis] -> [VarBndr IfaceBndr vis]
-toIfaceTyCoVarBinders = map toIfaceTyCoVarBinder
-
-{-
-************************************************************************
-* *
- Conversion from Type to IfaceType
-* *
-************************************************************************
--}
-
-toIfaceKind :: Type -> IfaceType
-toIfaceKind = toIfaceType
-
----------------------
-toIfaceType :: Type -> IfaceType
-toIfaceType = toIfaceTypeX emptyVarSet
-
-toIfaceTypeX :: VarSet -> Type -> IfaceType
--- (toIfaceTypeX free ty)
--- translates the tyvars in 'free' as IfaceFreeTyVars
---
--- Synonyms are retained in the interface type
-toIfaceTypeX fr (TyVarTy tv) -- See Note [TcTyVars in IfaceType] in IfaceType
- | tv `elemVarSet` fr = IfaceFreeTyVar tv
- | otherwise = IfaceTyVar (toIfaceTyVar tv)
-toIfaceTypeX fr ty@(AppTy {}) =
- -- Flatten as many argument AppTys as possible, then turn them into an
- -- IfaceAppArgs list.
- -- See Note [Suppressing invisible arguments] in IfaceType.
- let (head, args) = splitAppTys ty
- in IfaceAppTy (toIfaceTypeX fr head) (toIfaceAppTyArgsX fr head args)
-toIfaceTypeX _ (LitTy n) = IfaceLitTy (toIfaceTyLit n)
-toIfaceTypeX fr (ForAllTy b t) = IfaceForAllTy (toIfaceForAllBndrX fr b)
- (toIfaceTypeX (fr `delVarSet` binderVar b) t)
-toIfaceTypeX fr (FunTy { ft_arg = t1, ft_res = t2, ft_af = af })
- = IfaceFunTy af (toIfaceTypeX fr t1) (toIfaceTypeX fr t2)
-toIfaceTypeX fr (CastTy ty co) = IfaceCastTy (toIfaceTypeX fr ty) (toIfaceCoercionX fr co)
-toIfaceTypeX fr (CoercionTy co) = IfaceCoercionTy (toIfaceCoercionX fr co)
-
-toIfaceTypeX fr (TyConApp tc tys)
- -- tuples
- | Just sort <- tyConTuple_maybe tc
- , n_tys == arity
- = IfaceTupleTy sort NotPromoted (toIfaceTcArgsX fr tc tys)
-
- | Just dc <- isPromotedDataCon_maybe tc
- , isTupleDataCon dc
- , n_tys == 2*arity
- = IfaceTupleTy BoxedTuple IsPromoted (toIfaceTcArgsX fr tc (drop arity tys))
-
- | tc `elem` [ eqPrimTyCon, eqReprPrimTyCon, heqTyCon ]
- , (k1:k2:_) <- tys
- = let info = IfaceTyConInfo NotPromoted sort
- sort | k1 `eqType` k2 = IfaceEqualityTyCon
- | otherwise = IfaceNormalTyCon
- in IfaceTyConApp (IfaceTyCon (tyConName tc) info) (toIfaceTcArgsX fr tc tys)
-
- -- other applications
- | otherwise
- = IfaceTyConApp (toIfaceTyCon tc) (toIfaceTcArgsX fr tc tys)
- where
- arity = tyConArity tc
- n_tys = length tys
-
-toIfaceTyVar :: TyVar -> FastString
-toIfaceTyVar = occNameFS . getOccName
-
-toIfaceCoVar :: CoVar -> FastString
-toIfaceCoVar = occNameFS . getOccName
-
-toIfaceForAllBndr :: TyCoVarBinder -> IfaceForAllBndr
-toIfaceForAllBndr = toIfaceForAllBndrX emptyVarSet
-
-toIfaceForAllBndrX :: VarSet -> TyCoVarBinder -> IfaceForAllBndr
-toIfaceForAllBndrX fr (Bndr v vis) = Bndr (toIfaceBndrX fr v) vis
-
-----------------
-toIfaceTyCon :: TyCon -> IfaceTyCon
-toIfaceTyCon tc
- = IfaceTyCon tc_name info
- where
- tc_name = tyConName tc
- info = IfaceTyConInfo promoted sort
- promoted | isPromotedDataCon tc = IsPromoted
- | otherwise = NotPromoted
-
- tupleSort :: TyCon -> Maybe IfaceTyConSort
- tupleSort tc' =
- case tyConTuple_maybe tc' of
- Just UnboxedTuple -> let arity = tyConArity tc' `div` 2
- in Just $ IfaceTupleTyCon arity UnboxedTuple
- Just sort -> let arity = tyConArity tc'
- in Just $ IfaceTupleTyCon arity sort
- Nothing -> Nothing
-
- sort
- | Just tsort <- tupleSort tc = tsort
-
- | Just dcon <- isPromotedDataCon_maybe tc
- , let tc' = dataConTyCon dcon
- , Just tsort <- tupleSort tc' = tsort
-
- | isUnboxedSumTyCon tc
- , Just cons <- isDataSumTyCon_maybe tc = IfaceSumTyCon (length cons)
-
- | otherwise = IfaceNormalTyCon
-
-
-toIfaceTyCon_name :: Name -> IfaceTyCon
-toIfaceTyCon_name n = IfaceTyCon n info
- where info = IfaceTyConInfo NotPromoted IfaceNormalTyCon
- -- Used for the "rough-match" tycon stuff,
- -- where pretty-printing is not an issue
-
-toIfaceTyLit :: TyLit -> IfaceTyLit
-toIfaceTyLit (NumTyLit x) = IfaceNumTyLit x
-toIfaceTyLit (StrTyLit x) = IfaceStrTyLit x
-
-----------------
-toIfaceCoercion :: Coercion -> IfaceCoercion
-toIfaceCoercion = toIfaceCoercionX emptyVarSet
-
-toIfaceCoercionX :: VarSet -> Coercion -> IfaceCoercion
--- (toIfaceCoercionX free ty)
--- translates the tyvars in 'free' as IfaceFreeTyVars
-toIfaceCoercionX fr co
- = go co
- where
- go_mco MRefl = IfaceMRefl
- go_mco (MCo co) = IfaceMCo $ go co
-
- go (Refl ty) = IfaceReflCo (toIfaceTypeX fr ty)
- go (GRefl r ty mco) = IfaceGReflCo r (toIfaceTypeX fr ty) (go_mco mco)
- go (CoVarCo cv)
- -- See [TcTyVars in IfaceType] in IfaceType
- | cv `elemVarSet` fr = IfaceFreeCoVar cv
- | otherwise = IfaceCoVarCo (toIfaceCoVar cv)
- go (HoleCo h) = IfaceHoleCo (coHoleCoVar h)
-
- go (AppCo co1 co2) = IfaceAppCo (go co1) (go co2)
- go (SymCo co) = IfaceSymCo (go co)
- go (TransCo co1 co2) = IfaceTransCo (go co1) (go co2)
- go (NthCo _r d co) = IfaceNthCo d (go co)
- go (LRCo lr co) = IfaceLRCo lr (go co)
- go (InstCo co arg) = IfaceInstCo (go co) (go arg)
- go (KindCo c) = IfaceKindCo (go c)
- go (SubCo co) = IfaceSubCo (go co)
- go (AxiomRuleCo co cs) = IfaceAxiomRuleCo (coaxrName co) (map go cs)
- go (AxiomInstCo c i cs) = IfaceAxiomInstCo (coAxiomName c) i (map go cs)
- go (UnivCo p r t1 t2) = IfaceUnivCo (go_prov p) r
- (toIfaceTypeX fr t1)
- (toIfaceTypeX fr t2)
- go (TyConAppCo r tc cos)
- | tc `hasKey` funTyConKey
- , [_,_,_,_] <- cos = pprPanic "toIfaceCoercion" (ppr co)
- | otherwise = IfaceTyConAppCo r (toIfaceTyCon tc) (map go cos)
- go (FunCo r co1 co2) = IfaceFunCo r (go co1) (go co2)
-
- go (ForAllCo tv k co) = IfaceForAllCo (toIfaceBndr tv)
- (toIfaceCoercionX fr' k)
- (toIfaceCoercionX fr' co)
- where
- fr' = fr `delVarSet` tv
-
- go_prov :: UnivCoProvenance -> IfaceUnivCoProv
- go_prov UnsafeCoerceProv = IfaceUnsafeCoerceProv
- go_prov (PhantomProv co) = IfacePhantomProv (go co)
- go_prov (ProofIrrelProv co) = IfaceProofIrrelProv (go co)
- go_prov (PluginProv str) = IfacePluginProv str
-
-toIfaceTcArgs :: TyCon -> [Type] -> IfaceAppArgs
-toIfaceTcArgs = toIfaceTcArgsX emptyVarSet
-
-toIfaceTcArgsX :: VarSet -> TyCon -> [Type] -> IfaceAppArgs
-toIfaceTcArgsX fr tc ty_args = toIfaceAppArgsX fr (tyConKind tc) ty_args
-
-toIfaceAppTyArgsX :: VarSet -> Type -> [Type] -> IfaceAppArgs
-toIfaceAppTyArgsX fr ty ty_args = toIfaceAppArgsX fr (typeKind ty) ty_args
-
-toIfaceAppArgsX :: VarSet -> Kind -> [Type] -> IfaceAppArgs
--- See Note [Suppressing invisible arguments] in IfaceType
--- We produce a result list of args describing visibility
--- The awkward case is
--- T :: forall k. * -> k
--- And consider
--- T (forall j. blah) * blib
--- Is 'blib' visible? It depends on the visibility flag on j,
--- so we have to substitute for k. Annoying!
-toIfaceAppArgsX fr kind ty_args
- = go (mkEmptyTCvSubst in_scope) kind ty_args
- where
- in_scope = mkInScopeSet (tyCoVarsOfTypes ty_args)
-
- go _ _ [] = IA_Nil
- go env ty ts
- | Just ty' <- coreView ty
- = go env ty' ts
- go env (ForAllTy (Bndr tv vis) res) (t:ts)
- = IA_Arg t' vis ts'
- where
- t' = toIfaceTypeX fr t
- ts' = go (extendTCvSubst env tv t) res ts
-
- go env (FunTy { ft_af = af, ft_res = res }) (t:ts)
- = IA_Arg (toIfaceTypeX fr t) argf (go env res ts)
- where
- argf = case af of
- VisArg -> Required
- InvisArg -> Inferred
- -- It's rare for a kind to have a constraint argument, but
- -- it can happen. See Note [AnonTCB InvisArg] in TyCon.
-
- go env ty ts@(t1:ts1)
- | not (isEmptyTCvSubst env)
- = go (zapTCvSubst env) (substTy env ty) ts
- -- See Note [Care with kind instantiation] in Type.hs
-
- | otherwise
- = -- There's a kind error in the type we are trying to print
- -- e.g. kind = k, ty_args = [Int]
- -- This is probably a compiler bug, so we print a trace and
- -- carry on as if it were FunTy. Without the test for
- -- isEmptyTCvSubst we'd get an infinite loop (#15473)
- WARN( True, ppr kind $$ ppr ty_args )
- IA_Arg (toIfaceTypeX fr t1) Required (go env ty ts1)
-
-tidyToIfaceType :: TidyEnv -> Type -> IfaceType
-tidyToIfaceType env ty = toIfaceType (tidyType env ty)
-
-tidyToIfaceTcArgs :: TidyEnv -> TyCon -> [Type] -> IfaceAppArgs
-tidyToIfaceTcArgs env tc tys = toIfaceTcArgs tc (tidyTypes env tys)
-
-tidyToIfaceContext :: TidyEnv -> ThetaType -> IfaceContext
-tidyToIfaceContext env theta = map (tidyToIfaceType env) theta
-
-{-
-************************************************************************
-* *
- Conversion of pattern synonyms
-* *
-************************************************************************
--}
-
-patSynToIfaceDecl :: PatSyn -> IfaceDecl
-patSynToIfaceDecl ps
- = IfacePatSyn { ifName = getName $ ps
- , ifPatMatcher = to_if_pr (patSynMatcher ps)
- , ifPatBuilder = fmap to_if_pr (patSynBuilder ps)
- , ifPatIsInfix = patSynIsInfix ps
- , ifPatUnivBndrs = map toIfaceForAllBndr univ_bndrs'
- , ifPatExBndrs = map toIfaceForAllBndr ex_bndrs'
- , ifPatProvCtxt = tidyToIfaceContext env2 prov_theta
- , ifPatReqCtxt = tidyToIfaceContext env2 req_theta
- , ifPatArgs = map (tidyToIfaceType env2) args
- , ifPatTy = tidyToIfaceType env2 rhs_ty
- , ifFieldLabels = (patSynFieldLabels ps)
- }
- where
- (_univ_tvs, req_theta, _ex_tvs, prov_theta, args, rhs_ty) = patSynSig ps
- univ_bndrs = patSynUnivTyVarBinders ps
- ex_bndrs = patSynExTyVarBinders ps
- (env1, univ_bndrs') = tidyTyCoVarBinders emptyTidyEnv univ_bndrs
- (env2, ex_bndrs') = tidyTyCoVarBinders env1 ex_bndrs
- to_if_pr (id, needs_dummy) = (idName id, needs_dummy)
-
-{-
-************************************************************************
-* *
- Conversion of other things
-* *
-************************************************************************
--}
-
-toIfaceBang :: TidyEnv -> HsImplBang -> IfaceBang
-toIfaceBang _ HsLazy = IfNoBang
-toIfaceBang _ (HsUnpack Nothing) = IfUnpack
-toIfaceBang env (HsUnpack (Just co)) = IfUnpackCo (toIfaceCoercion (tidyCo env co))
-toIfaceBang _ HsStrict = IfStrict
-
-toIfaceSrcBang :: HsSrcBang -> IfaceSrcBang
-toIfaceSrcBang (HsSrcBang _ unpk bang) = IfSrcBang unpk bang
-
-toIfaceLetBndr :: Id -> IfaceLetBndr
-toIfaceLetBndr id = IfLetBndr (occNameFS (getOccName id))
- (toIfaceType (idType id))
- (toIfaceIdInfo (idInfo id))
- (toIfaceJoinInfo (isJoinId_maybe id))
- -- Put into the interface file any IdInfo that CoreTidy.tidyLetBndr
- -- has left on the Id. See Note [IdInfo on nested let-bindings] in IfaceSyn
-
-toIfaceIdDetails :: IdDetails -> IfaceIdDetails
-toIfaceIdDetails VanillaId = IfVanillaId
-toIfaceIdDetails (DFunId {}) = IfDFunId
-toIfaceIdDetails (RecSelId { sel_naughty = n
- , sel_tycon = tc }) =
- let iface = case tc of
- RecSelData ty_con -> Left (toIfaceTyCon ty_con)
- RecSelPatSyn pat_syn -> Right (patSynToIfaceDecl pat_syn)
- in IfRecSelId iface n
-
- -- The remaining cases are all "implicit Ids" which don't
- -- appear in interface files at all
-toIfaceIdDetails other = pprTrace "toIfaceIdDetails" (ppr other)
- IfVanillaId -- Unexpected; the other
-
-toIfaceIdInfo :: IdInfo -> IfaceIdInfo
-toIfaceIdInfo id_info
- = case catMaybes [arity_hsinfo, caf_hsinfo, strict_hsinfo,
- inline_hsinfo, unfold_hsinfo, levity_hsinfo] of
- [] -> NoInfo
- infos -> HasInfo infos
- -- NB: strictness and arity must appear in the list before unfolding
- -- See TcIface.tcUnfolding
- where
- ------------ Arity --------------
- arity_info = arityInfo id_info
- arity_hsinfo | arity_info == 0 = Nothing
- | otherwise = Just (HsArity arity_info)
-
- ------------ Caf Info --------------
- caf_info = cafInfo id_info
- caf_hsinfo = case caf_info of
- NoCafRefs -> Just HsNoCafRefs
- _other -> Nothing
-
- ------------ Strictness --------------
- -- No point in explicitly exporting TopSig
- sig_info = strictnessInfo id_info
- strict_hsinfo | not (isTopSig sig_info) = Just (HsStrictness sig_info)
- | otherwise = Nothing
-
- ------------ Unfolding --------------
- unfold_hsinfo = toIfUnfolding loop_breaker (unfoldingInfo id_info)
- loop_breaker = isStrongLoopBreaker (occInfo id_info)
-
- ------------ Inline prag --------------
- inline_prag = inlinePragInfo id_info
- inline_hsinfo | isDefaultInlinePragma inline_prag = Nothing
- | otherwise = Just (HsInline inline_prag)
-
- ------------ Levity polymorphism ----------
- levity_hsinfo | isNeverLevPolyIdInfo id_info = Just HsLevity
- | otherwise = Nothing
-
-toIfaceJoinInfo :: Maybe JoinArity -> IfaceJoinInfo
-toIfaceJoinInfo (Just ar) = IfaceJoinPoint ar
-toIfaceJoinInfo Nothing = IfaceNotJoinPoint
-
---------------------------
-toIfUnfolding :: Bool -> Unfolding -> Maybe IfaceInfoItem
-toIfUnfolding lb (CoreUnfolding { uf_tmpl = rhs
- , uf_src = src
- , uf_guidance = guidance })
- = Just $ HsUnfold lb $
- case src of
- InlineStable
- -> case guidance of
- UnfWhen {ug_arity = arity, ug_unsat_ok = unsat_ok, ug_boring_ok = boring_ok }
- -> IfInlineRule arity unsat_ok boring_ok if_rhs
- _other -> IfCoreUnfold True if_rhs
- InlineCompulsory -> IfCompulsory if_rhs
- InlineRhs -> IfCoreUnfold False if_rhs
- -- Yes, even if guidance is UnfNever, expose the unfolding
- -- If we didn't want to expose the unfolding, TidyPgm would
- -- have stuck in NoUnfolding. For supercompilation we want
- -- to see that unfolding!
- where
- if_rhs = toIfaceExpr rhs
-
-toIfUnfolding lb (DFunUnfolding { df_bndrs = bndrs, df_args = args })
- = Just (HsUnfold lb (IfDFunUnfold (map toIfaceBndr bndrs) (map toIfaceExpr args)))
- -- No need to serialise the data constructor;
- -- we can recover it from the type of the dfun
-
-toIfUnfolding _ (OtherCon {}) = Nothing
- -- The binding site of an Id doesn't have OtherCon, except perhaps
- -- where we have called zapUnfolding; and that evald'ness info is
- -- not needed by importing modules
-
-toIfUnfolding _ BootUnfolding = Nothing
- -- Can't happen; we only have BootUnfolding for imported binders
-
-toIfUnfolding _ NoUnfolding = Nothing
-
-{-
-************************************************************************
-* *
- Conversion of expressions
-* *
-************************************************************************
--}
-
-toIfaceExpr :: CoreExpr -> IfaceExpr
-toIfaceExpr (Var v) = toIfaceVar v
-toIfaceExpr (Lit l) = IfaceLit l
-toIfaceExpr (Type ty) = IfaceType (toIfaceType ty)
-toIfaceExpr (Coercion co) = IfaceCo (toIfaceCoercion co)
-toIfaceExpr (Lam x b) = IfaceLam (toIfaceBndr x, toIfaceOneShot x) (toIfaceExpr b)
-toIfaceExpr (App f a) = toIfaceApp f [a]
-toIfaceExpr (Case s x ty as)
- | null as = IfaceECase (toIfaceExpr s) (toIfaceType ty)
- | otherwise = IfaceCase (toIfaceExpr s) (getOccFS x) (map toIfaceAlt as)
-toIfaceExpr (Let b e) = IfaceLet (toIfaceBind b) (toIfaceExpr e)
-toIfaceExpr (Cast e co) = IfaceCast (toIfaceExpr e) (toIfaceCoercion co)
-toIfaceExpr (Tick t e)
- | Just t' <- toIfaceTickish t = IfaceTick t' (toIfaceExpr e)
- | otherwise = toIfaceExpr e
-
-toIfaceOneShot :: Id -> IfaceOneShot
-toIfaceOneShot id | isId id
- , OneShotLam <- oneShotInfo (idInfo id)
- = IfaceOneShot
- | otherwise
- = IfaceNoOneShot
-
----------------------
-toIfaceTickish :: Tickish Id -> Maybe IfaceTickish
-toIfaceTickish (ProfNote cc tick push) = Just (IfaceSCC cc tick push)
-toIfaceTickish (HpcTick modl ix) = Just (IfaceHpcTick modl ix)
-toIfaceTickish (SourceNote src names) = Just (IfaceSource src names)
-toIfaceTickish (Breakpoint {}) = Nothing
- -- Ignore breakpoints, since they are relevant only to GHCi, and
- -- should not be serialised (#8333)
-
----------------------
-toIfaceBind :: Bind Id -> IfaceBinding
-toIfaceBind (NonRec b r) = IfaceNonRec (toIfaceLetBndr b) (toIfaceExpr r)
-toIfaceBind (Rec prs) = IfaceRec [(toIfaceLetBndr b, toIfaceExpr r) | (b,r) <- prs]
-
----------------------
-toIfaceAlt :: (AltCon, [Var], CoreExpr)
- -> (IfaceConAlt, [FastString], IfaceExpr)
-toIfaceAlt (c,bs,r) = (toIfaceCon c, map getOccFS bs, toIfaceExpr r)
-
----------------------
-toIfaceCon :: AltCon -> IfaceConAlt
-toIfaceCon (DataAlt dc) = IfaceDataAlt (getName dc)
-toIfaceCon (LitAlt l) = IfaceLitAlt l
-toIfaceCon DEFAULT = IfaceDefault
-
----------------------
-toIfaceApp :: Expr CoreBndr -> [Arg CoreBndr] -> IfaceExpr
-toIfaceApp (App f a) as = toIfaceApp f (a:as)
-toIfaceApp (Var v) as
- = case isDataConWorkId_maybe v of
- -- We convert the *worker* for tuples into IfaceTuples
- Just dc | saturated
- , Just tup_sort <- tyConTuple_maybe tc
- -> IfaceTuple tup_sort tup_args
- where
- val_args = dropWhile isTypeArg as
- saturated = val_args `lengthIs` idArity v
- tup_args = map toIfaceExpr val_args
- tc = dataConTyCon dc
-
- _ -> mkIfaceApps (toIfaceVar v) as
-
-toIfaceApp e as = mkIfaceApps (toIfaceExpr e) as
-
-mkIfaceApps :: IfaceExpr -> [CoreExpr] -> IfaceExpr
-mkIfaceApps f as = foldl' (\f a -> IfaceApp f (toIfaceExpr a)) f as
-
----------------------
-toIfaceVar :: Id -> IfaceExpr
-toIfaceVar v
- | isBootUnfolding (idUnfolding v)
- = -- See Note [Inlining and hs-boot files]
- IfaceApp (IfaceApp (IfaceExt noinlineIdName)
- (IfaceType (toIfaceType (idType v))))
- (IfaceExt name) -- don't use mkIfaceApps, or infinite loop
-
- | Just fcall <- isFCallId_maybe v = IfaceFCall fcall (toIfaceType (idType v))
- -- Foreign calls have special syntax
-
- | isExternalName name = IfaceExt name
- | otherwise = IfaceLcl (getOccFS name)
- where name = idName v
-
-
-{- Note [Inlining and hs-boot files]
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-Consider this example (#10083, #12789):
-
- ---------- RSR.hs-boot ------------
- module RSR where
- data RSR
- eqRSR :: RSR -> RSR -> Bool
-
- ---------- SR.hs ------------
- module SR where
- import {-# SOURCE #-} RSR
- data SR = MkSR RSR
- eqSR (MkSR r1) (MkSR r2) = eqRSR r1 r2
-
- ---------- RSR.hs ------------
- module RSR where
- import SR
- data RSR = MkRSR SR -- deriving( Eq )
- eqRSR (MkRSR s1) (MkRSR s2) = (eqSR s1 s2)
- foo x y = not (eqRSR x y)
-
-When compiling RSR we get this code
-
- RSR.eqRSR :: RSR -> RSR -> Bool
- RSR.eqRSR = \ (ds1 :: RSR.RSR) (ds2 :: RSR.RSR) ->
- case ds1 of _ { RSR.MkRSR s1 ->
- case ds2 of _ { RSR.MkRSR s2 ->
- SR.eqSR s1 s2 }}
-
- RSR.foo :: RSR -> RSR -> Bool
- RSR.foo = \ (x :: RSR) (y :: RSR) -> not (RSR.eqRSR x y)
-
-Now, when optimising foo:
- Inline eqRSR (small, non-rec)
- Inline eqSR (small, non-rec)
-but the result of inlining eqSR from SR is another call to eqRSR, so
-everything repeats. Neither eqSR nor eqRSR are (apparently) loop
-breakers.
-
-Solution: in the unfolding of eqSR in SR.hi, replace `eqRSR` in SR
-with `noinline eqRSR`, so that eqRSR doesn't get inlined. This means
-that when GHC inlines `eqSR`, it will not also inline `eqRSR`, exactly
-as would have been the case if `foo` had been defined in SR.hs (and
-marked as a loop-breaker).
-
-But how do we arrange for this to happen? There are two ingredients:
-
- 1. When we serialize out unfoldings to IfaceExprs (toIfaceVar),
- for every variable reference we see if we are referring to an
- 'Id' that came from an hs-boot file. If so, we add a `noinline`
- to the reference.
-
- 2. But how do we know if a reference came from an hs-boot file
- or not? We could record this directly in the 'IdInfo', but
- actually we deduce this by looking at the unfolding: 'Id's
- that come from boot files are given a special unfolding
- (upon typechecking) 'BootUnfolding' which say that there is
- no unfolding, and the reason is because the 'Id' came from
- a boot file.
-
-Here is a solution that doesn't work: when compiling RSR,
-add a NOINLINE pragma to every function exported by the boot-file
-for RSR (if it exists). Doing so makes the bootstrapped GHC itself
-slower by 8% overall (on #9872a-d, and T1969: the reason
-is that these NOINLINE'd functions now can't be profitably inlined
-outside of the hs-boot loop.
-
--}
diff --git a/compiler/iface/ToIface.hs-boot b/compiler/iface/ToIface.hs-boot
deleted file mode 100644
index 38b6dbcd15..0000000000
--- a/compiler/iface/ToIface.hs-boot
+++ /dev/null
@@ -1,18 +0,0 @@
-module ToIface where
-
-import {-# SOURCE #-} TyCoRep ( Type, TyLit, Coercion )
-import {-# SOURCE #-} IfaceType( IfaceType, IfaceTyCon, IfaceForAllBndr
- , IfaceCoercion, IfaceTyLit, IfaceAppArgs )
-import Var ( TyCoVarBinder )
-import VarEnv ( TidyEnv )
-import TyCon ( TyCon )
-import VarSet( VarSet )
-
--- For TyCoRep
-toIfaceTypeX :: VarSet -> Type -> IfaceType
-toIfaceTyLit :: TyLit -> IfaceTyLit
-toIfaceForAllBndr :: TyCoVarBinder -> IfaceForAllBndr
-toIfaceTyCon :: TyCon -> IfaceTyCon
-toIfaceTcArgs :: TyCon -> [Type] -> IfaceAppArgs
-toIfaceCoercionX :: VarSet -> Coercion -> IfaceCoercion
-tidyToIfaceTcArgs :: TidyEnv -> TyCon -> [Type] -> IfaceAppArgs