summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Vainsencher <daniel.vainsencher@gmail.com>2012-11-26 11:18:50 +0000
committerSimon Peyton Jones <simonpj@microsoft.com>2012-12-05 16:41:28 +0000
commit57d6798353f53850943e361f4707db76c76dc38f (patch)
tree8456d2fe24b1c88118231de04164ce0d72fa6491
parentf971e75e66fc549e52a0a3d7ed1e6ba0109e6697 (diff)
downloadhaskell-57d6798353f53850943e361f4707db76c76dc38f.tar.gz
When using a GHC plugin, load its interface file very partially: just enough that it can be used, without its rules and instances affecting (and being linked from!) the module being compiled.
-rw-r--r--compiler/iface/LoadIface.lhs92
-rw-r--r--compiler/main/DynamicLoading.hs7
-rw-r--r--compiler/typecheck/TcRnTypes.lhs3
3 files changed, 62 insertions, 40 deletions
diff --git a/compiler/iface/LoadIface.lhs b/compiler/iface/LoadIface.lhs
index 85c8a7848d..c573020450 100644
--- a/compiler/iface/LoadIface.lhs
+++ b/compiler/iface/LoadIface.lhs
@@ -14,7 +14,7 @@ module LoadIface (
-- IfM functions
loadInterface, loadWiredInHomeIface,
- loadSysInterface, loadUserInterface,
+ loadSysInterface, loadUserInterface, loadPluginInterface,
findAndReadIface, readIface, -- Used when reading the module's old interface
loadDecls, -- Should move to TcIface and be renamed
initExternalPackageState,
@@ -159,6 +159,10 @@ 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
@@ -267,32 +271,36 @@ loadInterface doc_str mod from
; updateEps_ $ \ eps ->
if elemModuleEnv mod (eps_PIT eps) then eps 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_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_vect_info = plusVectInfo (eps_vect_info eps)
- new_eps_vect_info,
- 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) }
+ case from of -- See Note [Care with plugin imports]
+ ImportByPlugin -> eps {
+ eps_PIT = extendModuleEnv (eps_PIT eps) mod final_iface,
+ eps_PTE = addDeclsToPTE (eps_PTE eps) new_eps_decls}
+ _ -> 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_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_vect_info = plusVectInfo (eps_vect_info eps)
+ new_eps_vect_info,
+ 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) }
; return (Succeeded final_iface)
}}}}
@@ -307,6 +315,9 @@ wantHiBootFile dflags eps mod from
-> 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
@@ -329,16 +340,25 @@ badSourceImport mod
<+> quotes (ppr (modulePackageId mod)))
\end{code}
-{-
-Used to be used for the loadInterface sanity check on system imports. That has been removed, but I'm leaving this in pending
-review of this decision by SPJ - MCB 10/2008
+Note [Care with plugin imports]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+When dynamically loading a plugin (via loadPluginInterface) we
+populate the same External Package State (EPS), even though plugin
+modules are to link with the compiler itself, and not with the
+compiled program. That's fine: mostly the EPS is just a cache for
+the interace files on disk.
+
+But it's NOT ok for the RULES or instance environment. We do not want
+to fire a RULE from the plugin on the code we are compiling, otherwise
+the code we are compiling will have a reference to a RHS of the rule
+that exists only in the compiler! This actually happened to Daniel,
+via a RULE arising from a specialisation of (^) in the plugin.
+
+Solution: when loading plugins, do not extend the rule and instance
+environments. We are only interested in the type environment, so that
+we can check that the plugin exports a function with the type that the
+compiler expects.
-badDepMsg :: Module -> SDoc
-badDepMsg mod
- = hang (ptext (sLit "Interface file inconsistency:"))
- 2 (sep [ptext (sLit "home-package module") <+> quotes (ppr mod) <+> ptext (sLit "is needed,"),
- ptext (sLit "but is not listed in the dependencies of the interfaces directly imported by the module being compiled")])
--}
\begin{code}
-----------------------------------------------------
diff --git a/compiler/main/DynamicLoading.hs b/compiler/main/DynamicLoading.hs
index 84eb2612e0..adcb0eb3b3 100644
--- a/compiler/main/DynamicLoading.hs
+++ b/compiler/main/DynamicLoading.hs
@@ -20,9 +20,8 @@ import Linker ( linkModule, getHValue )
import SrcLoc ( noSrcSpan )
import Finder ( findImportedModule, cannotFindModule )
import DriverPhases ( HscSource(HsSrcFile) )
-import TcRnDriver ( getModuleInterface )
import TcRnMonad ( initTc, initIfaceTcRn )
-import LoadIface ( loadUserInterface )
+import LoadIface ( loadPluginInterface )
import RdrName ( RdrName, Provenance(..), ImportSpec(..), ImpDeclSpec(..)
, ImpItemSpec(..), mkGlobalRdrEnv, lookupGRE_RdrName, gre_name )
import RnNames ( gresFromAvails )
@@ -50,7 +49,7 @@ import GHC.Exts ( unsafeCoerce# )
-- for debugging (@-ddump-if-trace@) only: it is shown as the reason why the module is being loaded.
forceLoadModuleInterfaces :: HscEnv -> SDoc -> [Module] -> IO ()
forceLoadModuleInterfaces hsc_env doc modules
- = (initTc hsc_env HsSrcFile False iNTERACTIVE $ initIfaceTcRn $ mapM_ (loadUserInterface False doc) modules) >> return ()
+ = (initTc hsc_env HsSrcFile False iNTERACTIVE $ initIfaceTcRn $ mapM_ (loadPluginInterface doc) modules) >> return ()
-- | Force the interface for the module containing the name to be loaded. The 'SDoc' parameter is used
-- for debugging (@-ddump-if-trace@) only: it is shown as the reason why the module is being loaded.
@@ -138,7 +137,7 @@ lookupRdrNameInModule hsc_env mod_name rdr_name = do
case found_module of
Found _ mod -> do
-- Find the exports of the module
- (_, mb_iface) <- getModuleInterface hsc_env mod
+ (_, mb_iface) <- initTc hsc_env HsSrcFile False iNTERACTIVE $ initIfaceTcRn $ loadPluginInterface (ptext (sLit "contains a name used in an invocation of lookupRdrNameInModule")) mod
case mb_iface of
Just iface -> do
-- Try and find the required name in the exports
diff --git a/compiler/typecheck/TcRnTypes.lhs b/compiler/typecheck/TcRnTypes.lhs
index 952628d8b3..0aff832135 100644
--- a/compiler/typecheck/TcRnTypes.lhs
+++ b/compiler/typecheck/TcRnTypes.lhs
@@ -836,11 +836,14 @@ The @WhereFrom@ type controls where the renamer looks for an interface file
data WhereFrom
= ImportByUser IsBootInterface -- Ordinary user import (perhaps {-# SOURCE #-})
| ImportBySystem -- Non user import.
+ | ImportByPlugin -- Importing a plugin;
+ -- See Note [Care with plugin imports] in LoadIface
instance Outputable WhereFrom where
ppr (ImportByUser is_boot) | is_boot = ptext (sLit "{- SOURCE -}")
| otherwise = empty
ppr ImportBySystem = ptext (sLit "{- SYSTEM -}")
+ ppr ImportByPlugin = ptext (sLit "{- PLUGIN -}")
\end{code}
%************************************************************************