-%
+
% (c) The GRASP/AQUA Project, Glasgow University, 1992-1998
%
\section{Dealing with interface files}
loadSrcInterface, loadSysInterface, loadOrphanModules,
findAndReadIface, readIface, -- Used when reading the module's old interface
loadDecls, ifaceStats, discardDeclPrags,
- initExternalPackageState
+ initExternalPackageState,
+
+ pprModIface, showIface -- Print the iface in Foo.hi
) where
#include "HsVersions.h"
import IfaceSyn ( IfaceDecl(..), IfaceConDecl(..), IfaceClassOp(..),
IfaceConDecls(..), IfaceIdInfo(..) )
import IfaceEnv ( newGlobalBinder )
-import HscTypes ( ModIface(..), TyThing, emptyModIface, EpsStats(..),
+import HscTypes ( ModIface(..), TyThing, IfaceExport, Usage(..),
+ Deprecs(..), Dependencies(..),
+ emptyModIface, EpsStats(..), GenAvailInfo(..),
addEpsInStats, ExternalPackageState(..),
PackageTypeEnv, emptyTypeEnv, HscEnv(..),
lookupIfaceByModule, emptyPackageIfaceTable,
implicitTyThings
)
-import BasicTypes ( Version, Fixity(..), FixityDirection(..),
- isMarkedStrict )
+import BasicTypes ( Version, initialVersion,
+ Fixity(..), FixityDirection(..), isMarkedStrict )
import TcRnMonad
+import Type ( TyThing(..) )
+import Class ( classATs )
import PrelNames ( gHC_PRIM )
import PrelInfo ( ghcPrimExports )
import NameEnv
import MkId ( seqId )
import Module
-import OccName ( OccName, mkOccEnv, lookupOccEnv, mkClassTyConOcc, mkClassDataConOcc,
- mkSuperDictSelOcc, mkDataConWrapperOcc, mkDataConWorkerOcc )
+import OccName ( OccName, mkOccEnv, lookupOccEnv, mkClassTyConOcc,
+ mkClassDataConOcc, mkSuperDictSelOcc,
+ mkDataConWrapperOcc, mkDataConWorkerOcc,
+ mkNewTyCoOcc, mkInstTyTcOcc, mkInstTyCoOcc )
import SrcLoc ( importedSrcLoc )
import Maybes ( MaybeErr(..) )
import ErrUtils ( Message )
import Finder ( findImportedModule, findExactModule,
- FindResult(..), cantFindError )
+ FindResult(..), cannotFindInterface )
import UniqFM
+import StaticFlags ( opt_HiVersion )
import Outputable
-import BinIface ( readBinIface )
+import BinIface ( readBinIface, v_IgnoreHiWay )
+import Binary ( getBinFileWithDict )
import Panic ( ghcError, tryMost, showException, GhcException(..) )
import List ( nub )
+import Maybe ( isJust )
+import DATA_IOREF ( writeIORef )
\end{code}
Found _ mod -> do
mb_iface <- initIfaceTcRn $ loadInterface doc mod (ImportByUser want_boot)
case mb_iface of
- Failed err -> failWithTc (elaborate err)
+ Failed err -> failWithTc err
Succeeded iface -> return iface
err ->
let dflags = hsc_dflags hsc_env in
- failWithTc (elaborate (cantFindError dflags mod err))
- where
- elaborate err = hang (ptext SLIT("Failed to load interface for") <+>
- quotes (ppr mod) <> colon) 4 err
+ failWithTc (cannotFindInterface dflags mod err)
-- | Load interfaces for a collection of orphan modules.
loadOrphanModules :: [Module] -> TcM ()
-- 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
+-- implict things (in particular, adding them to `implicitTyThings' would mess
+-- things up in the renaming/type checking of source programs).
-----------------------------------------------------
addDeclsToPTE :: PackageTypeEnv -> [(Name,TyThing)] -> PackageTypeEnv
= do { -- Populate the name cache with final versions of all
-- the names associated with the decl
main_name <- mk_new_bndr mod Nothing (ifName decl)
- ; implicit_names <- mapM (mk_new_bndr mod (Just main_name)) (ifaceDeclSubBndrs decl)
+ ; implicit_names <- mapM (mk_new_bndr mod (Just main_name))
+ (ifaceDeclSubBndrs decl)
-- Typecheck the thing, lazily
-- NB. firstly, the laziness is there in case we never need the
; 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)
+ Nothing ->
+ pprPanic "loadDecl" (ppr main_name <+>
+ ppr n $$ ppr (stripped_decl))
- ; returnM ((main_name, thing) : [(n, lookup n) | n <- implicit_names]) }
+ ; returnM $ (main_name, thing) : [(n, lookup n) | n <- implicit_names]
+ }
-- We build a list from the *known* names, with (lookup n) thunks
-- as the TyThings. That way we can extend the PTE without poking the
-- thunks
-- imported name, to fix the module correctly in the cache
mk_new_bndr mod mb_parent occ
= newGlobalBinder mod occ mb_parent
- (importedSrcLoc (showSDoc (pprModule mod)))
+ (importedSrcLoc (showSDoc (ppr (moduleName mod))))
+ -- ToDo: qualify with the package name if necessary
doc = ptext SLIT("Declaration for") <+> ppr (ifName decl)
-- *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
-
-ifaceDeclSubBndrs (IfaceClass {ifCtxt = sc_ctxt, ifName = cls_occ, ifSigs = sigs })
- = [tc_occ, dc_occ, dcww_occ] ++
- [op | IfaceClassOp op _ _ <- sigs] ++
+--
+-- If you change this, make sure you change HscTypes.implicitTyThings in sync
+
+ifaceDeclSubBndrs (IfaceClass {ifCtxt = sc_ctxt, ifName = cls_occ,
+ ifSigs = sigs, ifATs = ats })
+ = co_occs ++
+ [tc_occ, dc_occ, dcww_occ] ++
+ [op | IfaceClassOp op _ _ <- sigs] ++
+ [ifName at | at <- ats ] ++
[mkSuperDictSelOcc n cls_occ | n <- [1..n_ctxt]]
where
n_ctxt = length sc_ctxt
n_sigs = length sigs
tc_occ = mkClassTyConOcc cls_occ
dc_occ = mkClassDataConOcc cls_occ
- dcww_occ | is_newtype = mkDataConWrapperOcc dc_occ -- Newtypes have wrapper but no worker
+ co_occs | is_newtype = [mkNewTyCoOcc tc_occ]
+ | otherwise = []
+ dcww_occ -- | is_newtype = mkDataConWrapperOcc dc_occ -- Newtypes have wrapper but no worker
| otherwise = mkDataConWorkerOcc dc_occ -- Otherwise worker but no wrapper
is_newtype = n_sigs + n_ctxt == 1 -- Sigh
-ifaceDeclSubBndrs (IfaceData {ifCons = IfAbstractTyCon})
+ifaceDeclSubBndrs IfaceData {ifCons = IfAbstractTyCon}
= []
-- Newtype
-ifaceDeclSubBndrs (IfaceData {ifCons = IfNewTyCon (IfVanillaCon { ifConOcc = con_occ,
- ifConFields = fields})})
- = fields ++ [con_occ, mkDataConWrapperOcc con_occ]
- -- Wrapper, no worker; see MkId.mkDataConIds
-
-ifaceDeclSubBndrs (IfaceData {ifCons = IfDataTyCon cons})
- = nub (concatMap fld_occs cons) -- Eliminate duplicate fields
+ifaceDeclSubBndrs (IfaceData {ifName = tc_occ,
+ ifCons = IfNewTyCon (
+ IfCon { ifConOcc = con_occ,
+ ifConFields = fields
+ }),
+ ifFamInst = famInst})
+ = fields ++ [con_occ, mkDataConWorkerOcc con_occ, mkNewTyCoOcc tc_occ]
+ ++ famInstCo famInst tc_occ
+
+ifaceDeclSubBndrs (IfaceData {ifName = tc_occ,
+ ifCons = IfDataTyCon cons,
+ ifFamInst = famInst})
+ = nub (concatMap ifConFields cons) -- Eliminate duplicate fields
++ concatMap dc_occs cons
+ ++ famInstCo famInst tc_occ
where
- fld_occs (IfVanillaCon { ifConFields = fields }) = fields
- fld_occs (IfGadtCon {}) = []
dc_occs con_decl
| has_wrapper = [con_occ, work_occ, wrap_occ]
| otherwise = [con_occ, work_occ]
wrap_occ = mkDataConWrapperOcc con_occ
work_occ = mkDataConWorkerOcc con_occ
has_wrapper = any isMarkedStrict strs -- See MkId.mkDataConIds (sigh)
+ || not (null . ifConEqSpec $ con_decl)
+ || isJust famInst
-- ToDo: may miss strictness in existential dicts
-ifaceDeclSubBndrs _other = []
+ifaceDeclSubBndrs _other = []
+-- coercion for data/newtype family instances
+famInstCo Nothing baseOcc = []
+famInstCo (Just _) baseOcc = [mkInstTyCoOcc baseOcc]
\end{code}
Failed err -> do
{ traceIf (ptext SLIT("...not found"))
; dflags <- getDOpts
- ; returnM (Failed (cantFindError dflags (moduleName mod) err)) } ;
+ ; returnM (Failed (cannotFindInterface dflags
+ (moduleName mod) err)) } ;
Succeeded file_path -> do
\end{code}
+%************************************************************************
+%* *
+ Printing interfaces
+%* *
+%************************************************************************
+
+\begin{code}
+showIface :: FilePath -> IO ()
+-- Read binary interface, and print it out
+showIface filename = do
+ -- skip the version check; we don't want to worry about profiled vs.
+ -- non-profiled interfaces, for example.
+ writeIORef v_IgnoreHiWay True
+ iface <- Binary.getBinFileWithDict filename
+ printDump (pprModIface iface)
+ where
+\end{code}
+
+
+\begin{code}
+pprModIface :: ModIface -> SDoc
+-- Show a ModIface
+pprModIface iface
+ = vcat [ ptext SLIT("interface")
+ <+> ppr (mi_module iface) <+> pp_boot
+ <+> ppr (mi_mod_vers iface) <+> pp_sub_vers
+ <+> (if mi_orphan iface then ptext SLIT("[orphan module]") else empty)
+ <+> int opt_HiVersion
+ <+> ptext SLIT("where")
+ , vcat (map pprExport (mi_exports iface))
+ , pprDeps (mi_deps iface)
+ , vcat (map pprUsage (mi_usages iface))
+ , pprFixities (mi_fixities iface)
+ , vcat (map pprIfaceDecl (mi_decls iface))
+ , vcat (map ppr (mi_insts iface))
+ , vcat (map ppr (mi_rules iface))
+ , pprDeprecs (mi_deprecs iface)
+ ]
+ where
+ pp_boot | mi_boot iface = ptext SLIT("[boot]")
+ | otherwise = empty
+
+ exp_vers = mi_exp_vers iface
+ rule_vers = mi_rule_vers iface
+
+ pp_sub_vers | exp_vers == initialVersion && rule_vers == initialVersion = empty
+ | otherwise = brackets (ppr exp_vers <+> ppr rule_vers)
+\end{code}
+
+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
+
+\begin{code}
+pprExport :: IfaceExport -> SDoc
+pprExport (mod, items)
+ = hsep [ ptext SLIT("export"), ppr mod, hsep (map pp_avail items) ]
+ where
+ pp_avail :: GenAvailInfo OccName -> SDoc
+ pp_avail (Avail occ) = ppr occ
+ pp_avail (AvailTC _ []) = empty
+ pp_avail (AvailTC n (n':ns))
+ | n==n' = ppr n <> pp_export ns
+ | otherwise = ppr n <> char '|' <> pp_export (n':ns)
+
+ pp_export [] = empty
+ pp_export names = braces (hsep (map ppr names))
+
+pprUsage :: Usage -> SDoc
+pprUsage usage
+ = hsep [ptext SLIT("import"), ppr (usg_name usage),
+ int (usg_mod usage),
+ pp_export_version (usg_exports usage),
+ int (usg_rules usage),
+ pp_versions (usg_entities usage) ]
+ where
+ pp_versions nvs = hsep [ ppr n <+> int v | (n,v) <- nvs ]
+ pp_export_version Nothing = empty
+ pp_export_version (Just v) = int v
+
+pprDeps :: Dependencies -> SDoc
+pprDeps (Deps { dep_mods = mods, dep_pkgs = pkgs, dep_orphs = orphs})
+ = vcat [ptext SLIT("module dependencies:") <+> fsep (map ppr_mod mods),
+ ptext SLIT("package dependencies:") <+> fsep (map ppr pkgs),
+ ptext SLIT("orphans:") <+> fsep (map ppr orphs)
+ ]
+ where
+ ppr_mod (mod_name, boot) = ppr mod_name <+> ppr_boot boot
+ ppr_boot True = text "[boot]"
+ ppr_boot False = empty
+
+pprIfaceDecl :: (Version, IfaceDecl) -> SDoc
+pprIfaceDecl (ver, decl)
+ = ppr_vers ver <+> ppr decl
+ where
+ -- Print the version for the decl
+ ppr_vers v | v == initialVersion = empty
+ | otherwise = int v
+
+pprFixities :: [(OccName, Fixity)] -> SDoc
+pprFixities [] = empty
+pprFixities fixes = ptext SLIT("fixities") <+> pprWithCommas pprFix fixes
+ where
+ pprFix (occ,fix) = ppr fix <+> ppr occ
+
+pprDeprecs NoDeprecs = empty
+pprDeprecs (DeprecAll txt) = ptext SLIT("Deprecate all") <+> doubleQuotes (ftext txt)
+pprDeprecs (DeprecSome prs) = ptext SLIT("Deprecate") <+> vcat (map pprDeprec prs)
+ where
+ pprDeprec (name, txt) = ppr name <+> doubleQuotes (ftext txt)
+\end{code}
+
+
%*********************************************************
%* *
\subsection{Errors}
]
where iface_file = doubleQuotes (text file_path)
\end{code}
+