import DataCon
import Type
import TcType
-import TysPrim
import InstEnv
import FamInstEnv
import TcRnMonad
; let { entities = typeEnvElts type_env ;
decls = [ tyThingToIfaceDecl entity
| entity <- entities,
- not (isImplicitTyThing entity
- || isWiredInName (getName entity)) ]
- -- Don't put implicit Ids and class tycons in
- -- the interface file, Nor wired-in things; the
- -- compiler knows about them anyhow
+ 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 this_mod name ]
+ -- Sigh: see Note [Root-main Id] in TcRnDriver
; fixities = [(occ,fix) | FixItem occ fix _ <- nameEnvElts fix_env]
; deprecs = mkIfaceDeprec src_deprecs
mi_deps = deps,
mi_usages = usages,
mi_exports = mkIfaceExports exports,
+
+ -- Sort these lexicographically, so that
+ -- the result is stable across compilations
mi_insts = sortLe le_inst iface_insts,
mi_fam_insts= sortLe le_fam_inst iface_fam_insts,
mi_rules = sortLe le_rule iface_rules,
+
mi_fixities = fixities,
mi_deprecs = deprecs,
mi_globals = Just rdr_env,
mi_rule_vers = initialVersion,
mi_orphan = False, -- Always set by addVersionInfo, but
-- it's a strict field, so we can't omit it.
+ mi_finsts = False, -- Ditto
mi_decls = deliberatelyOmitted "decls",
mi_ver_fn = deliberatelyOmitted "ver_fn",
; return (new_iface, no_change_at_all) }
where
- r1 `le_rule` r2 = ifRuleName r1 <= ifRuleName r2
- i1 `le_inst` i2 = ifDFun i1 <= ifDFun i2
- i1 `le_fam_inst` i2 = ifFamInstTyConOcc i1 <= ifFamInstTyConOcc i2
+ r1 `le_rule` r2 = ifRuleName r1 <= ifRuleName r2
+ i1 `le_inst` i2 = ifDFun i1 `le_occ` ifDFun i2
+ i1 `le_fam_inst` i2 = ifFamInstTcName i1 `le_occ` ifFamInstTcName i2
+
+ le_occ :: Name -> Name -> Bool
+ -- Compare lexicographically by OccName, *not* by unique, because
+ -- the latter is not stable across compilations
+ le_occ n1 n2 = nameOccName n1 <= nameOccName n2
dflags = hsc_dflags hsc_env
deliberatelyOmitted x = panic ("Deliberately omitted: " ++ x)
- ifFamInstTyConOcc = nameOccName . ifaceTyConName . ifFamInstTyCon
+ ifFamInstTcName = ifaceTyConName . ifFamInstTyCon
-
-----------------------------
writeIfaceFile :: DynFlags -> ModLocation -> ModIface -> IO ()
writeIfaceFile dflags location new_iface
addVersionInfo ver_fn Nothing new_iface new_decls
-- No old interface, so definitely write a new one!
= (new_iface { mi_orphan = anyNothing ifInstOrph (mi_insts new_iface)
- || anyNothing ifRuleOrph (mi_rules new_iface),
- mi_decls = [(initialVersion, decl) | decl <- new_decls],
- mi_ver_fn = mkIfaceVerCache (zip (repeat initialVersion) new_decls)},
+ || anyNothing ifRuleOrph (mi_rules new_iface)
+ , mi_finsts = not . null $ mi_fam_insts new_iface
+ , mi_decls = [(initialVersion, decl) | decl <- new_decls]
+ , mi_ver_fn = mkIfaceVerCache (zip (repeat initialVersion)
+ new_decls)
+ },
False,
ptext SLIT("No old interface file"),
pprOrphans orph_insts orph_rules)
mi_exp_vers = bump_unless no_export_change old_exp_vers,
mi_rule_vers = bump_unless no_rule_change old_rule_vers,
mi_orphan = not (null new_orph_rules && null new_orph_insts),
+ mi_finsts = not . null $ mi_fam_insts new_iface,
mi_decls = decls_w_vers,
mi_ver_fn = mkIfaceVerCache decls_w_vers }
mkOrphMap ifInstOrph (mi_insts old_iface)
(new_non_orph_insts, new_orph_insts) =
mkOrphMap ifInstOrph (mi_insts new_iface)
+ old_fam_insts = mi_fam_insts old_iface
+ new_fam_insts = mi_fam_insts new_iface
same_insts occ = eqMaybeBy (eqListBy eqIfInst)
(lookupOccEnv old_non_orph_insts occ)
(lookupOccEnv new_non_orph_insts occ)
-- Kept sorted
no_decl_change = isEmptyOccSet changed_occs
no_rule_change = not (changedWrtNames changed_occs (eqListBy eqIfRule old_orph_rules new_orph_rules)
- || changedWrtNames changed_occs (eqListBy eqIfInst old_orph_insts new_orph_insts))
+ || changedWrtNames changed_occs (eqListBy eqIfInst old_orph_insts new_orph_insts)
+ || changedWrtNames changed_occs (eqListBy eqIfFamInst old_fam_insts new_fam_insts))
no_deprec_change = mi_deprecs new_iface == mi_deprecs old_iface
-- If the usages havn't changed either, we don't need to write the interface file
where
occ = ifName new_decl
why = case lookupOccEnv eq_env occ of
- Just (EqBut names) -> sep [ppr occ <> colon, ptext SLIT("Free vars (only) changed:"),
+ Just (EqBut names) -> sep [ppr occ <> colon, ptext SLIT("Free vars (only) changed:") <> ppr names,
nest 2 (braces (fsep (map ppr (occSetElts
(occs `intersectOccSet` changed_occs)))))]
where occs = mkOccSet (map nameOccName (nameSetToList names))
-- a) we used something from; has something in used_names
-- b) we imported all of it, even if we used nothing from it
-- (need to recompile if its export list changes: export_vers)
- -- c) is a home-package orphan module (need to recompile if its
- -- instance decls change: rules_vers)
+ -- c) is a home-package orphan or family-instance module (need to
+ -- recompile if its instance decls change: rules_vers)
mkUsage :: (ModuleName, IsBootInterface) -> Maybe Usage
mkUsage (mod_name, _)
| isNothing maybe_iface -- We can't depend on it if we didn't
|| (null used_occs -- load its interface.
&& isNothing export_vers
- && not orphan_mod)
+ && not orphan_mod
+ && not finsts_mod)
= Nothing -- Record no usage info
| otherwise
Just iface = maybe_iface
orphan_mod = mi_orphan iface
+ finsts_mod = mi_finsts iface
version_env = mi_ver_fn iface
mod_vers = mi_mod_vers iface
rules_vers = mi_rule_vers iface
= IfaceForeign { ifName = getOccName tycon,
ifExtName = tyConExtName tycon }
- | isPrimTyCon tycon || isFunTyCon tycon
- -- Needed in GHCi for ':info Int#', for example
- = IfaceData { ifName = getOccName tycon,
- ifTyVars = toIfaceTvBndrs (take (tyConArity tycon) alphaTyVars),
- ifCtxt = [],
- ifCons = IfAbstractTyCon,
- ifGadtSyntax = False,
- ifGeneric = False,
- ifRec = NonRecursive,
- ifFamInst = Nothing }
-
| otherwise = pprPanic "toIfaceDecl" (ppr tycon)
where
tyvars = tyConTyVars tycon