+ = ASSERT2( not (isLocalName (availName avail)), ppr avail )
+ ifaces { iDecls = (new_decls_map, n_slurped+1),
+ iSlurp = new_slurped_names,
+ iVSlurp = updateVSlurp vslurp (availName avail) }
+ where
+ new_decls_map = foldl delFromNameEnv decls_map (availNames avail)
+ new_slurped_names = addAvailToNameSet slurped_names avail
+
+
+-- recordTypeEnvSlurp is used when we slurp something that's
+-- already in the type environment, that was not slurped in an earlier compilation.
+-- We record it in the iVSlurp set, because that's used to
+-- generate usage information
+
+recordTypeEnvSlurp ifaces ty_thing
+ = ifaces { iVSlurp = updateVSlurp (iVSlurp ifaces) (get_main_name ty_thing) }
+ where
+ -- Tiresomely, we must get the "main" name for the
+ -- thing, because that's what VSlurp contains, and what
+ -- is recorded in the usage information
+ get_main_name (AClass cl) = className cl
+ get_main_name (ATyCon tc)
+ | Just clas <- tyConClass_maybe tc = get_main_name (AClass clas)
+ | otherwise = tyConName tc
+ get_main_name (AnId id)
+ = case globalIdDetails id of
+ DataConId dc -> get_main_name (ATyCon (dataConTyCon dc))
+ DataConWrapId dc -> get_main_name (ATyCon (dataConTyCon dc))
+ RecordSelId lbl -> get_main_name (ATyCon (fieldLabelTyCon lbl))
+ other -> idName id
+
+updateVSlurp (imp_mods, imp_names) main_name
+ | isHomeModule mod = (imp_mods, addOneToNameSet imp_names main_name)
+ | otherwise = (extendModuleSet imp_mods mod, imp_names)
+ where
+ mod = nameModule main_name
+
+recordLocalSlurps new_names
+ = getIfacesRn `thenRn` \ ifaces ->
+ setIfacesRn (ifaces { iSlurp = iSlurp ifaces `unionNameSets` new_names })
+\end{code}
+
+
+
+%*********************************************************
+%* *
+\subsection{Extracting the `gates'}
+%* *
+%*********************************************************
+
+The gating story
+~~~~~~~~~~~~~~~~~
+We want to avoid sucking in too many instance declarations.
+An instance decl is only useful if the types and classes mentioned in
+its 'head' are all available in the program being compiled. E.g.
+
+ instance (..) => C (T1 a) (T2 b) where ...
+
+is only useful if C, T1 and T2 are all "available". So we keep
+instance decls that have been parsed from .hi files, but not yet
+slurped in, in a pool called the 'gated instance pool'.
+Each has its set of 'gates': {C, T1, T2} in the above example.
+
+More precisely, the gates of a module are the types and classes
+that are mentioned in:
+
+ a) the source code
+ b) the type of an Id that's mentioned in the source code
+ [includes constructors and selectors]
+ c) the RHS of a type synonym that is a gate
+ d) the superclasses of a class that is a gate
+ e) the context of an instance decl that is slurped in
+
+We slurp in an instance decl from the gated instance pool iff
+
+ all its gates are either in the gates of the module,
+ or are a previously-loaded class.
+
+The latter constraint is because there might have been an instance
+decl slurped in during an earlier compilation, like this:
+
+ instance Foo a => Baz (Maybe a) where ...
+
+In the module being compiled we might need (Baz (Maybe T)), where T
+is defined in this module, and hence we need (Foo T). So @Foo@ becomes
+a gate. But there's no way to 'see' that, so we simply treat all
+previously-loaded classes as gates.
+
+Consructors and class operations
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+When we import a declaration like
+
+ data T = T1 Wibble | T2 Wobble
+
+we don't want to treat @Wibble@ and @Wobble@ as gates {\em unless}
+@T1@, @T2@ respectively are mentioned by the user program. If only
+@T@ is mentioned we want only @T@ to be a gate; that way we don't suck
+in useless instance decls for (say) @Eq Wibble@, when they can't
+possibly be useful.
+
+And that's just what (b) says: we only treat T1's type as a gate if
+T1 is mentioned. getGates, which deals with decls we are slurping in,
+has to be a bit careful, because a mention of T1 will slurp in T's whole
+declaration.
+
+-----------------------------
+@getGates@ takes a newly imported (and renamed) decl, and the free
+vars of the source program, and extracts from the decl the gate names.
+
+\begin{code}
+getGates :: FreeVars -- Things mentioned in the source program
+ -> RenamedTyClDecl
+ -> FreeVars
+
+getGates source_fvs decl
+ = get_gates (\n -> n `elemNameSet` source_fvs) decl
+
+get_gates is_used (IfaceSig {tcdType = ty}) = extractHsTyNames ty
+
+get_gates is_used (ClassDecl { tcdCtxt = ctxt, tcdName = cls, tcdTyVars = tvs, tcdSigs = sigs})
+ = (delListFromNameSet (foldr (plusFV . get) (extractHsCtxtTyNames ctxt) sigs)
+ (hsTyVarNames tvs)
+ `addOneToNameSet` cls)
+ `plusFV` implicitGates cls
+ where
+ get (ClassOpSig n _ ty _)
+ | is_used n = extractHsTyNames ty
+ | otherwise = emptyFVs
+
+get_gates is_used (TySynonym {tcdTyVars = tvs, tcdSynRhs = ty})
+ = delListFromNameSet (extractHsTyNames ty) (hsTyVarNames tvs)
+ -- A type synonym type constructor isn't a "gate" for instance decls
+
+get_gates is_used (TyData {tcdCtxt = ctxt, tcdName = tycon, tcdTyVars = tvs, tcdCons = cons})
+ = delListFromNameSet (foldr (plusFV . get) (extractHsCtxtTyNames ctxt) cons)
+ (hsTyVarNames tvs)
+ `addOneToNameSet` tycon
+ where
+ get (ConDecl n _ tvs ctxt details _)
+ | is_used n
+ -- If the constructor is method, get fvs from all its fields
+ = delListFromNameSet (get_details details `plusFV`
+ extractHsCtxtTyNames ctxt)
+ (hsTyVarNames tvs)
+ get (ConDecl n _ tvs ctxt (RecCon fields) _)
+ -- Even if the constructor isn't mentioned, the fields
+ -- might be, as selectors. They can't mention existentially
+ -- bound tyvars (typechecker checks for that) so no need for
+ -- the deleteListFromNameSet part
+ = foldr (plusFV . get_field) emptyFVs fields
+
+ get other_con = emptyFVs
+
+ get_details (VanillaCon tys) = plusFVs (map get_bang tys)
+ get_details (InfixCon t1 t2) = get_bang t1 `plusFV` get_bang t2
+ get_details (RecCon fields) = plusFVs [get_bang t | (_, t) <- fields]
+
+ get_field (fs,t) | any is_used fs = get_bang t
+ | otherwise = emptyFVs
+
+ get_bang bty = extractHsTyNames (getBangType bty)
+\end{code}
+
+@getWiredInGates@ is just like @getGates@, but it sees a previously-loaded
+thing rather than a declaration.
+
+\begin{code}
+getWiredInGates :: TyThing -> FreeVars
+-- The TyThing is one that we already have in our type environment, either
+-- a) because the TyCon or Id is wired in, or
+-- b) from a previous compile
+-- Either way, we might have instance decls in the (persistent) collection
+-- of parsed-but-not-slurped instance decls that should be slurped in.
+-- This might be the first module that mentions both the type and the class
+-- for that instance decl, even though both the type and the class were
+-- mentioned in other modules, and hence are in the type environment
+
+getWiredInGates (AnId the_id) = namesOfType (idType the_id)
+getWiredInGates (AClass cl) = emptyFVs -- The superclasses must also be previously
+ -- loaded, and hence are automatically gates
+getWiredInGates (ATyCon tc)
+ | isSynTyCon tc = delListFromNameSet (namesOfType ty) (map getName tyvars)
+ | otherwise = unitFV (getName tc)
+ where
+ (tyvars,ty) = getSynTyConDefn tc
+
+getInstDeclGates (InstDecl inst_ty _ _ _ _) = extractHsTyNames inst_ty
+\end{code}
+
+\begin{code}
+getImportedInstDecls :: NameSet -> RnMG [(Module,RdrNameInstDecl)]
+getImportedInstDecls gates
+ = -- First, load any orphan-instance modules that aren't aready loaded
+ -- Orphan-instance modules are recorded in the module dependecnies
+ getIfacesRn `thenRn` \ ifaces ->
+ let
+ orphan_mods =
+ [mod | (mod, (True, _)) <- fmToList (iImpModInfo ifaces)]
+ in
+ loadOrphanModules orphan_mods `thenRn_`
+
+ -- Now we're ready to grab the instance declarations
+ -- Find the un-gated ones and return them,
+ -- removing them from the bag kept in Ifaces
+ getIfacesRn `thenRn` \ ifaces ->
+ getTypeEnvRn `thenRn` \ lookup ->
+ let
+ available n = n `elemNameSet` gates
+ || case lookup n of { Just (AClass c) -> True; other -> False }
+ -- See "The gating story" above for the AClass thing
+
+ (decls, new_insts) = selectGated available (iInsts ifaces)