import Class ( Class, DefMeth(..), classBigSig )
import Var ( idName, idType )
import VarSet ( emptyVarSet )
+import Id ( setIdLocalExported )
import MkId ( mkDictFunId )
import FunDeps ( checkInstFDs )
import Generics ( validGenericInstanceType )
import Module ( Module, foldModuleEnv )
import Name ( getSrcLoc )
-import NameSet ( unitNameSet, nameSetToList )
+import NameSet ( unitNameSet, emptyNameSet, nameSetToList )
import PrelInfo ( eRROR_ID )
import TyCon ( TyCon )
import Subst ( mkTopTyVarSubst, substTheta )
import Name ( Name )
import SrcLoc ( SrcLoc )
import Unique ( Uniquable(..) )
+import Util ( lengthExceeds )
import BasicTypes ( NewOrData(..), Fixity )
import ErrUtils ( dumpIfSet_dyn )
import ListSetOps ( Assoc, emptyAssoc, plusAssoc_C, mapAssoc,
| null groups
= returnTc [] -- The comon case: no generic default methods
- | otherwise -- A local class decl with generic default methods
+ | otherwise -- A source class decl with generic default methods
= recoverNF_Tc (returnNF_Tc []) $
tcAddDeclCtxt decl $
tcLookupClass class_name `thenTc` \ clas ->
tc_inst_infos = [(simpleInstInfoTyCon i, i) | i <- inst_infos]
bad_groups = [group | group <- equivClassesByUniq get_uniq tc_inst_infos,
- length group > 1]
+ group `lengthExceeds` 1]
get_uniq (tc,_) = getUnique tc
in
mapTc (addErrTc . dupGenericInsts) bad_groups `thenTc_`
-- Create the result bindings
let
+ local_dfun_id = setIdLocalExported dfun_id
+ -- Reason for setIdLocalExported: see notes with MkId.mkDictFunId
+
dict_constr = classDataCon clas
scs_and_meths = map instToId (sc_dicts ++ meth_insts)
this_dict_id = instToId this_dict
- inlines = unitNameSet (idName dfun_id)
+ inlines | null dfun_arg_dicts = emptyNameSet
+ | otherwise = unitNameSet (idName dfun_id)
-- Always inline the dfun; this is an experimental decision
-- because it makes a big performance difference sometimes.
-- Often it means we can do the method selection, and then
-- inline the method as well. Marcin's idea; see comments below.
+ --
+ -- BUT: don't inline it if it's a constant dictionary;
+ -- we'll get all the benefit without inlining, and we get
+ -- a **lot** of code duplication if we inline it
dict_rhs
| null scs_and_meths
= AbsBinds
zonked_inst_tyvars
(map instToId dfun_arg_dicts)
- [(inst_tyvars', dfun_id, this_dict_id)]
+ [(inst_tyvars', local_dfun_id, this_dict_id)]
inlines
(lie_binds1 `AndMonoBinds`
lie_binds2 `AndMonoBinds`