A variant of `runTcInteractive` that takes a list of orphan modules
Motivation
The concat plugin uses BuildDictionary.hs to find or construct a CoreExpr
of the given predicate type. To do so it uses runTcInteractive
. The problem is that the way it treats orphan instances is fairly awkward:
-- From BuildDictionary.hs
moduleIsOkay :: HscEnv -> ModuleName -> IO Bool
moduleIsOkay env mname = isFound <$> findExposedPackageModule env mname Nothing
runTcM :: HscEnv -> DynFlags -> ModGuts -> TcM a -> IO a
runTcM env0 dflags guts m = do
-- Remove hidden modules from dep_orphans
orphans <- filterM (moduleIsOkay env0) (moduleName <$> dep_orphs (mg_deps guts))
(msgs, mr) <- runTcInteractive (env orphans) m
let showMsgs (warns, errs) = showSDoc dflags $ vcat $
text "Errors:" : pprErrMsgBagWithLoc errs
++ text "Warnings:" : pprErrMsgBagWithLoc warns
maybe (fail $ showMsgs msgs) return mr
where
imports0 = ic_imports (hsc_IC env0)
env :: [ModuleName] -> HscEnv
env extraModuleNames =
env0 { hsc_IC = (hsc_IC env0)
{ ic_imports = map IIModule extraModuleNames ++ imports0
, ic_rn_gbl_env = mg_rdr_env guts
, ic_instances = (mg_insts guts, mg_fam_insts guts)
} }
Given the ModGuts
it is dealing with, it extracts the ModuleName
s of its dep_orphs
, and prepends it to ic_imports
, only so that these ModuleName
s will be loaded and turned back into Module
s in runTcInteractive
. This is wasted work.
What's worse, in order to do so it needs to filter out the hidden orphan modules (i.e., the filterM
, because loading a hidden module results in an error). This means BuildDictionary
cannot find any orphan instances in hidden packages.
Proposal
What would be pretty useful is a variant of runTcInteractive
that takes orphan modules as input, and concatenate it with the orphan modules it computes:
runTcInteractive :: HscEnv -> TcRn a -> IO (Messages TcRnMessage, Maybe a)
runTcInteractive = runTcInteractive' []
runTcInteractive' :: [Module] -> HscEnv -> TcRn a -> IO (Messages TcRnMessage, Maybe a)
runTcInteractive' orphs0 hsc_env thing_inside =
...
; !orphs <- fmap (force . concat . (orphs0 :)) . forM (ic_imports icxt) $ \i ->
...
This way BuildDictionary.hs
will be both simpler and able to find orphan instances from hidden packages.