+getGates source_fvs decl
+ = get_gates (\n -> n `elemNameSet` source_fvs) decl
+
+get_gates is_used (ForeignType {tcdName = tycon}) = unitNameSet tycon
+get_gates is_used (IfaceSig {tcdType = ty}) = extractHsTyNames ty
+
+get_gates is_used (ClassDecl { tcdCtxt = ctxt, tcdName = cls, tcdTyVars = tvs, tcdSigs = sigs})
+ = (super_cls_and_sigs `addOneToNameSet` cls) `unionNameSets`
+ implicitClassGates cls
+ where
+ super_cls_and_sigs = delListFromNameSet (foldr (plusFV . get) (extractHsCtxtTyNames ctxt) sigs)
+ (hsTyVarNames tvs)
+ 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)
+
+implicitClassGates :: Name -> FreeVars
+implicitClassGates cls
+ -- If we load class Num, add Integer to the free gates
+ -- This takes account of the fact that Integer might be needed for
+ -- defaulting, but we don't want to load Integer (and all its baggage)
+ -- if there's no numeric stuff needed.
+ -- Similarly for class Fractional and Double
+ --
+ -- NB: adding T to the gates will force T to be loaded
+ --
+ -- NB: If we load (say) Floating, we'll end up loading Fractional too,
+ -- since Fractional is a superclass of Floating
+ | cls `hasKey` numClassKey = unitFV integerTyConName
+ | cls `hasKey` fractionalClassKey = unitFV doubleTyConName
+ | otherwise = emptyFVs