Attempt to fix the problems with missing instances once more.
The current problem is that in the case where a ModDetails is being
constructed from its interface (in compilation manager modes) we
weren't getting any instances because the instances are gotten from
the [InstInfo] returned from tcInstDecls1, which only contains
*source* instance declarations. Fix: return a list of DFuns defined
in the current module from tcInstDecls1, to be plugged into the
ModDetails later.
Also: revert the previous change to the isLocalThing predicate,
because now we really want to know which dfuns come from the current
module. The comment about the iface_dfuns containing only package and
local instances is incorrect in batch-compile mode, because we also
demand-load stuff from home package interfaces, so I deleted this
comment and fixed up some of the other commentary.
newLocalName, newDFunName,
-- Misc
- isLocalThing, isHomePackageThing, tcSetEnv
+ isLocalThing, tcSetEnv
) where
#include "HsVersions.h"
import TyCon ( TyCon )
import Class ( Class, ClassOpItem )
import Name ( Name, NamedThing(..),
- getSrcLoc, mkLocalName, isLocalName, nameIsLocalOrFrom,
- isHomePackageName
+ getSrcLoc, mkLocalName, isLocalName, nameIsLocalOrFrom
)
import NameEnv ( NameEnv, lookupNameEnv, nameEnvElts, elemNameEnv,
extendNameEnvList, emptyNameEnv, plusNameEnv )
\begin{code}
isLocalThing :: NamedThing a => Module -> a -> Bool
isLocalThing mod thing = nameIsLocalOrFrom mod (getName thing)
-
-isHomePackageThing :: NamedThing a => a -> Bool
-isHomePackageThing thing = isHomePackageName (getName thing)
\end{code}
%************************************************************************
import Inst ( InstOrigin(..), newDicts, instToId,
LIE, mkLIE, emptyLIE, plusLIE, plusLIEs )
import TcDeriv ( tcDeriving )
-import TcEnv ( TcEnv, tcExtendGlobalValEnv, isHomePackageThing,
+import TcEnv ( TcEnv, tcExtendGlobalValEnv, isLocalThing,
tcExtendTyVarEnvForMeths, tcLookupId, tcLookupClass,
InstInfo(..), pprInstInfo, simpleInstInfoTyCon,
simpleInstInfoTy, newDFunName
Gather up the instance declarations from their various sources
\begin{code}
-tcInstDecls1 :: PackageInstEnv
- -> PersistentRenamerState
- -> HomeSymbolTable -- Contains instances
- -> TcEnv -- Contains IdInfo for dfun ids
- -> (Name -> Maybe Fixity) -- for deriving Show and Read
- -> Module -- Module for deriving
- -> [RenamedHsDecl]
- -> TcM (PackageInstEnv, InstEnv, [InstInfo], RenamedHsBinds)
+tcInstDecls1
+ :: PackageInstEnv
+ -> PersistentRenamerState
+ -> HomeSymbolTable -- Contains instances
+ -> TcEnv -- Contains IdInfo for dfun ids
+ -> (Name -> Maybe Fixity) -- for deriving Show and Read
+ -> Module -- Module for deriving
+ -> [RenamedHsDecl]
+ -> TcM (PackageInstEnv, -- cached package inst env
+ InstEnv, -- the full inst env
+ [InstInfo], -- instance decls to process
+ [DFunId], -- instances from this module, for its iface
+ RenamedHsBinds) -- derived instances
tcInstDecls1 inst_env0 prs hst unf_env get_fixity this_mod decls
= let
(iface_inst_ds, local_inst_ds) = partition isIfaceInstDecl inst_decls
in
-- (1) Do the ordinary instance declarations
- mapNF_Tc tcLocalInstDecl1 local_inst_ds `thenNF_Tc` \ local_inst_infos ->
- mapNF_Tc tcImportedInstDecl1 iface_inst_ds `thenNF_Tc` \ iface_dfuns ->
+ mapNF_Tc tcLocalInstDecl1 local_inst_ds `thenNF_Tc` \ local_inst_infos ->
+ mapNF_Tc tcImportedInstDecl1 iface_inst_ds `thenNF_Tc` \ iface_dfuns ->
-- (2) Instances from generic class declarations
- getGenericInstances clas_decls `thenTc` \ generic_inst_info ->
+ getGenericInstances clas_decls `thenTc` \ generic_inst_info ->
-- Next, construct the instance environment so far, consisting of
- -- a) cached non-home-package InstEnv (gotten from pcs) inst_env0
- -- b) imported instance decls (not in the home package) inst_env1
- -- c) imported instance decls (from this module) inst_env2
- -- c) other modules in this package (gotten from hst) inst_env3
- -- d) local instance decls inst_env4
- -- e) generic instances inst_env5
+ -- a) cached non-home-package InstEnv (gotten from pcs) inst_env0
+ -- b) imported instance decls (not in the home package) inst_env1
+ -- c) other modules in this package (gotten from hst) inst_env2
+ -- d) imported instance decls (from this module) inst_env3
+ -- e) local instance decls inst_env4
+ -- f) generic instances inst_env5
-- The result of (b) replaces the cached InstEnv in the PCS
--
- -- Note that iface_dfuns may contain not only insts that we demand-loaded
- -- from package interface files, but also instances from the current module
- -- in the case where we are loading this module's interface file in GHCi,
- -- so we partition the iface_dfuns into package instances and local instances
- -- below so that we don't end up with home package instances in the PCS.
+ -- Note that iface_dfuns may contain not only insts that we
+ -- demand-loaded from interface files, but also instances from
+ -- the current module in the case where we are loading this
+ -- module's interface file in GHCi, so we partition the
+ -- iface_dfuns into non-local and local instances so that we
+ -- don't end up with home package instances in the PCS.
--
-- There can't be any instance declarations from the home
-- package other than from the current module (with the
-- compilation manager) because they are loaded explicitly by
- -- the compilation manager. The partition is really only
- -- necessary when we're under control of the compilation
- -- manager.
+ -- the compilation manager.
let
local_inst_info = catMaybes local_inst_infos
- (local_iface_dfuns, pkg_iface_dfuns) = partition isHomePackageThing iface_dfuns
- hst_dfuns = foldModuleEnv ((++) . md_insts) [] hst
+ (local_iface_dfuns, pkg_iface_dfuns)
+ = partition (isLocalThing this_mod) iface_dfuns
+ hst_dfuns = foldModuleEnv ((++) . md_insts) [] hst
in
-- pprTrace "tcInstDecls" (vcat [ppr imported_dfuns, ppr hst_dfuns]) $
-- note that we only do derivings for things in this module;
-- we ignore deriving decls from interfaces!
-- This stuff computes a context for the derived instance decl, so it
- -- needs to know about all the instances possible; hence inst_env4
- tcDeriving prs this_mod inst_env4 get_fixity tycl_decls
- `thenTc` \ (deriv_inst_info, deriv_binds) ->
- addInstInfos inst_env4 deriv_inst_info `thenNF_Tc` \ final_inst_env ->
+ -- needs to know about all the instances possible; hence inst_env5
+ tcDeriving prs this_mod inst_env5 get_fixity tycl_decls
+ `thenTc` \ (deriv_inst_info, deriv_binds) ->
+ addInstInfos inst_env5 deriv_inst_info `thenNF_Tc` \ final_inst_env ->
+ let inst_info = generic_inst_info ++ deriv_inst_info ++ local_inst_info in
returnTc (inst_env1,
final_inst_env,
- generic_inst_info ++ deriv_inst_info ++ local_inst_info,
+ inst_info,
+ local_iface_dfuns ++ map iDFunId inst_info,
deriv_binds)
addInstInfos :: InstEnv -> [InstInfo] -> NF_TcM InstEnv
tcSetDefaultTys defaultDefaultTys $
-- Typecheck the extra declarations
- fixTc (\ ~(unf_env, _, _, _, _) ->
- tcImports unf_env pcs hst get_fixity this_mod iface_decls
- ) `thenTc` \ (env, new_pcs, local_inst_info, deriv_binds, local_rules) ->
- ASSERT( null local_inst_info && nullBinds deriv_binds && null local_rules )
+ tcExtraDecls pcs hst get_fixity this_mod iface_decls `thenTc` \ (new_pcs, env) ->
tcSetEnv env $
tcExtendGlobalTypeEnv ic_type_env $
tcSetDefaultTys defaultDefaultTys $
-- Typecheck the extra declarations
- fixTc (\ ~(unf_env, _, _, _, _) ->
- tcImports unf_env pcs hst get_fixity this_mod decls
- ) `thenTc` \ (env, new_pcs, local_inst_info, deriv_binds, local_rules) ->
- ASSERT( null local_inst_info && nullBinds deriv_binds && null local_rules )
+ tcExtraDecls pcs hst get_fixity this_mod decls `thenTc` \ (new_pcs, env) ->
-- Now typecheck the expression
tcSetEnv env $
typecheckExtraDecls dflags pcs hst unqual this_mod decls
= typecheck dflags pcs hst unqual $
- fixTc (\ ~(unf_env, _, _, _, _) ->
- tcImports unf_env pcs hst get_fixity this_mod decls
- ) `thenTc` \ (env, new_pcs, local_inst_info, deriv_binds, local_rules) ->
- ASSERT( null local_inst_info && nullBinds deriv_binds && null local_rules )
+ tcExtraDecls pcs hst get_fixity this_mod decls
+ `thenTc` \ (new_pcs, env) ->
returnTc new_pcs
where
get_fixity n = pprPanic "typecheckExpr" (ppr n)
+
+tcExtraDecls pcs hst get_fixity this_mod decls =
+ fixTc (\ ~(unf_env, _, _, _, _, _) ->
+ tcImports unf_env pcs hst get_fixity this_mod decls
+ ) `thenTc` \ (env, new_pcs, local_inst_info, local_inst_dfuns,
+ deriv_binds, local_rules) ->
+ ASSERT( null local_inst_info && nullBinds deriv_binds && null local_rules
+ && null local_inst_dfuns )
+ returnTc (new_pcs, env)
\end{code}
%************************************************************************
-- Type-check the type and class decls, and all imported decls
tcImports unf_env pcs hst get_fixity this_mod decls
- `thenTc` \ (env, new_pcs, local_insts, deriv_binds, local_rules) ->
+ `thenTc` \ (env, new_pcs, local_inst_info, local_inst_dfuns, deriv_binds, local_rules) ->
tcSetEnv env $
tcSetEnv env $
tcClassDecls2 this_mod tycl_decls `thenNF_Tc` \ (lie_clasdecls, cls_dm_binds, dm_ids) ->
tcExtendGlobalValEnv dm_ids $
- tcInstDecls2 local_insts `thenNF_Tc` \ (lie_instdecls, inst_binds) ->
+ tcInstDecls2 local_inst_info `thenNF_Tc` \ (lie_instdecls, inst_binds) ->
tcForeignExports decls `thenTc` \ (lie_fodecls, foe_binds, foe_decls) ->
tcSourceRules source_rules `thenNF_Tc` \ (lie_rules, more_local_rules) ->
returnTc (final_env,
new_pcs,
TcResults { tc_env = local_type_env,
- tc_insts = map iDFunId local_insts,
+ tc_insts = local_inst_dfuns,
tc_binds = all_binds',
tc_fords = foi_decls ++ foe_decls',
tc_rules = all_local_rules
get_fixity nm = lookupNameEnv fixity_env nm
tcIfaceImports pcs hst get_fixity this_mod decls
- = fixTc (\ ~(unf_env, _, _, _, _) ->
+ = fixTc (\ ~(unf_env, _, _, _, _, _) ->
tcImports unf_env pcs hst get_fixity this_mod decls
- ) `thenTc` \ (env, new_pcs, local_inst_info,
+ ) `thenTc` \ (env, new_pcs, local_inst_info, local_inst_dfuns,
deriv_binds, local_rules) ->
- ASSERT(nullBinds deriv_binds)
+ ASSERT(nullBinds deriv_binds && null local_inst_info)
let
local_things = filter (isLocalThing this_mod) (typeEnvElts (getTcGEnv env))
mod_details = ModDetails { md_types = mkTypeEnv local_things,
- md_insts = map iDFunId local_inst_info,
+ md_insts = local_inst_dfuns,
md_rules = [(id,rule) | IfaceRuleOut id rule <- local_rules],
md_binds = [] }
-- All the rules from an interface are of the IfaceRuleOut form
-> (Name -> Maybe Fixity)
-> Module
-> [RenamedHsDecl]
- -> TcM (TcEnv, PersistentCompilerState, [InstInfo],
+ -> TcM (TcEnv, PersistentCompilerState, [InstInfo], [DFunId],
RenamedHsBinds, [TypecheckedRuleDecl])
-- tcImports is a slight mis-nomer.
-- Note that imported dictionary functions are already
-- in scope from the preceding tcInterfaceSigs
traceTc (text "Tc3") `thenNF_Tc_`
- tcInstDecls1 (pcs_insts pcs) (pcs_PRS pcs)
- hst unf_env get_fixity this_mod
- decls `thenTc` \ (new_pcs_insts, inst_env, local_insts, deriv_binds) ->
+ tcInstDecls1 (pcs_insts pcs) (pcs_PRS pcs) hst unf_env get_fixity this_mod decls
+ `thenTc` \ (new_pcs_insts, inst_env, local_inst_info, local_inst_dfuns, deriv_binds) ->
tcSetInstEnv inst_env $
tcIfaceRules unf_env (pcs_rules pcs) this_mod iface_rules `thenNF_Tc` \ (new_pcs_rules, local_rules) ->
pcs_rules = new_pcs_rules
}
in
- returnTc (unf_env, new_pcs, local_insts, deriv_binds, local_rules)
+ returnTc (unf_env, new_pcs, local_inst_info, local_inst_dfuns, deriv_binds, local_rules)
where
tycl_decls = [d | TyClD d <- decls]
iface_rules = [d | RuleD d <- decls, isIfaceRuleDecl d]