X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=ghc%2Fcompiler%2Ftypecheck%2FTcInstDcls.lhs;h=bc332aa294c9af03220ab7e8e42724213430e222;hb=136d634590dfed8008c084e2418e7c1663924829;hp=4f670fa884c6a8c78ef7b7d955b267cea8bf79fd;hpb=00e85a3cb0dd8f268f6c40f898ac92d19ea90081;p=ghc-hetmet.git diff --git a/ghc/compiler/typecheck/TcInstDcls.lhs b/ghc/compiler/typecheck/TcInstDcls.lhs index 4f670fa..bc332aa 100644 --- a/ghc/compiler/typecheck/TcInstDcls.lhs +++ b/ghc/compiler/typecheck/TcInstDcls.lhs @@ -545,9 +545,6 @@ tcInstDecl2 (InstInfo { iDFunId = dfun_id, iBinds = binds }) -- 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_ids this_dict_id = instToId this_dict @@ -593,10 +590,10 @@ tcInstDecl2 (InstInfo { iDFunId = dfun_id, iBinds = binds }) main_bind = AbsBinds zonked_inst_tyvars (map instToId dfun_arg_dicts) - [(inst_tyvars', local_dfun_id, this_dict_id)] + [(inst_tyvars', dfun_id, this_dict_id)] inlines all_binds in - showLIE "instance" `thenM_` + showLIE (text "instance") `thenM_` returnM (main_bind `AndMonoBinds` prag_binds `AndMonoBinds` sc_binds_outer) @@ -610,19 +607,50 @@ tcMethods clas inst_tyvars inst_tyvars' dfun_theta' inst_tys' mappM (addErrTc . badMethodErr clas) bad_bndrs `thenM_` -- Make the method bindings - mapAndUnzipM do_one op_items `thenM` \ (meth_ids, meth_binds_s) -> + let + mk_method_bind = mkMethodBind InstanceDeclOrigin clas inst_tys' monobinds + in + mapAndUnzipM mk_method_bind op_items `thenM` \ (meth_insts, meth_infos) -> + + -- And type check them + -- It's really worth making meth_insts available to the tcMethodBind + -- Consider instance Monad (ST s) where + -- {-# INLINE (>>) #-} + -- (>>) = ...(>>=)... + -- If we don't include meth_insts, we end up with bindings like this: + -- rec { dict = MkD then bind ... + -- then = inline_me (... (GHC.Base.>>= dict) ...) + -- bind = ... } + -- The trouble is that (a) 'then' and 'dict' are mutually recursive, + -- and (b) the inline_me prevents us inlining the >>= selector, which + -- would unravel the loop. Result: (>>) ends up as a loop breaker, and + -- is not inlined across modules. Rather ironic since this does not + -- happen without the INLINE pragma! + -- + -- Solution: make meth_insts available, so that 'then' refers directly + -- to the local 'bind' rather than going via the dictionary. + -- + -- BUT WATCH OUT! If the method type mentions the class variable, then + -- this optimisation is not right. Consider + -- class C a where + -- op :: Eq a => a + -- + -- instance C Int where + -- op = op + -- The occurrence of 'op' on the rhs gives rise to a constraint + -- op at Int + -- The trouble is that the 'meth_inst' for op, which is 'available', also + -- looks like 'op at Int'. But they are not the same. + let + all_insts = avail_insts ++ catMaybes meth_insts + xtve = inst_tyvars `zip` inst_tyvars' + tc_method_bind = tcMethodBind xtve inst_tyvars' dfun_theta' all_insts uprags + in + mapM tc_method_bind meth_infos `thenM` \ meth_binds_s -> - returnM (meth_ids, andMonoBindList meth_binds_s) + returnM ([meth_id | (_,meth_id,_) <- meth_infos], + andMonoBindList meth_binds_s) - where - xtve = inst_tyvars `zip` inst_tyvars' - do_one op_item - = mkMethodBind InstanceDeclOrigin clas - inst_tys' monobinds op_item `thenM` \ (meth_inst, meth_info) -> - tcMethodBind xtve inst_tyvars' dfun_theta' - avail_insts uprags meth_info `thenM` \ meth_bind -> - -- Could add meth_insts to avail_insts, but not worth the bother - returnM (instToId meth_inst, meth_bind) -- Derived newtype instances tcMethods clas inst_tyvars inst_tyvars' dfun_theta' inst_tys'