- let
- (tyvars, _, _, op_items) = classBigSig clas
- rigid_info = ClsSkol clas
- origin = SigOrigin rigid_info
- prag_fn = mkPragFun sigs
- sig_fn = mkTcSigFun sigs
- clas_tyvars = tcSkolSigTyVars rigid_info tyvars
- tc_dm = tcDefMeth origin clas clas_tyvars
- default_binds sig_fn prag_fn
-
- dm_sel_ids = [sel_id | (sel_id, DefMeth) <- op_items]
- -- Generate code for polymorphic default methods only
- -- (Generic default methods have turned into instance decls by now.)
- -- This is incompatible with Hugs, which expects a polymorphic
- -- default method for every class op, regardless of whether or not
- -- the programmer supplied an explicit default decl for the class.
- -- (If necessary we can fix that, but we don't have a convenient Id to hand.)
-
- (defm_binds, dm_ids_s) <- mapAndUnzipM tc_dm dm_sel_ids
- return (listToBag defm_binds, concat dm_ids_s)
-
-tcDefMeth origin clas tyvars binds_in sig_fn prag_fn sel_id
- = do { dm_name <- lookupTopBndrRn (mkDefMethRdrName sel_id)
- ; let inst_tys = mkTyVarTys tyvars
- dm_ty = idType sel_id -- Same as dict selector!
- cls_pred = mkClassPred clas inst_tys
- local_dm_id = mkDefaultMethodId dm_name dm_ty
-
- ; (_, meth_info) <- mkMethodBind origin clas inst_tys binds_in (sel_id, DefMeth)
- ; loc <- getInstLoc origin
- ; this_dict <- newDictBndr loc cls_pred
- ; (defm_bind, insts_needed) <- getLIE (tcMethodBind tyvars [cls_pred] [this_dict]
- sig_fn prag_fn meth_info)
-
- ; addErrCtxt (defltMethCtxt clas) $ do
-
- -- Check the context
- { dict_binds <- tcSimplifyCheck
- loc
- tyvars
- [this_dict]
- insts_needed
-
- -- Simplification can do unification
- ; checkSigTyVars tyvars
-
- -- Inline pragmas
- -- We'll have an inline pragma on the local binding, made by tcMethodBind
- -- but that's not enough; we want one on the global default method too
- -- Specialisations, on the other hand, belong on the thing inside only, I think
- ; let (_,dm_inst_id,_) = meth_info
- sel_name = idName sel_id
- inline_prags = filter isInlineLSig (prag_fn sel_name)
- ; prags <- tcPrags dm_inst_id inline_prags
-
- ; let full_bind = AbsBinds tyvars
- [instToId this_dict]
- [(tyvars, local_dm_id, dm_inst_id, prags)]
- (dict_binds `unionBags` defm_bind)
- ; return (noLoc full_bind, [local_dm_id]) }}
-
-mkDefMethRdrName :: Id -> RdrName
-mkDefMethRdrName sel_id = mkDerivedRdrName (idName sel_id) mkDefaultMethodOcc
-\end{code}
-
-
-%************************************************************************
-%* *
-\subsection{Typechecking a method}
-%* *
-%************************************************************************
-
-@tcMethodBind@ is used to type-check both default-method and
-instance-decl method declarations. We must type-check methods one at a
-time, because their signatures may have different contexts and
-tyvar sets.
-
-\begin{code}
-type MethodSpec = (Id, -- Global selector Id
- Id, -- Local Id (class tyvars instantiated)
- LHsBind Name) -- Binding for the method
-
-tcMethodBind
- :: [TcTyVar] -- Skolemised type variables for the
- -- enclosing class/instance decl.
- -- They'll be signature tyvars, and we
- -- want to check that they don't get bound
- -- Also they are scoped, so we bring them into scope
- -- Always equal the range of the type envt
- -> TcThetaType -- Available theta; it's just used for the error message
- -> [Inst] -- Available from context, used to simplify constraints
- -- from the method body
- -> TcSigFun -- For scoped tyvars, indexed by sel_name
- -> TcPragFun -- Pragmas (e.g. inline pragmas), indexed by sel_name
- -> MethodSpec -- Details of this method
- -> TcM (LHsBinds Id)
-
-tcMethodBind inst_tyvars inst_theta avail_insts sig_fn prag_fn
- (sel_id, meth_id, meth_bind)
- = recoverM (return emptyLHsBinds) $ do
- -- If anything fails, recover returning no bindings.
- -- This is particularly useful when checking the default-method binding of
- -- a class decl. If we don't recover, we don't add the default method to
- -- the type enviroment, and we get a tcLookup failure on $dmeth later.
-
- -- Check the bindings; first adding inst_tyvars to the envt
- -- so that we don't quantify over them in nested places
-
- let sel_name = idName sel_id
- meth_sig_fn meth_name = ASSERT( meth_name == idName meth_id ) sig_fn sel_name
- -- The meth_bind metions the meth_name, but sig_fn is indexed by sel_name
-
- ((meth_bind, mono_bind_infos), meth_lie)
- <- tcExtendTyVarEnv inst_tyvars $
- tcExtendIdEnv [meth_id] $ -- In scope for tcInstSig
- addErrCtxt (methodCtxt sel_id) $
- getLIE $
- tcMonoBinds [meth_bind] meth_sig_fn Recursive
-
- -- Now do context reduction. We simplify wrt both the local tyvars
- -- and the ones of the class/instance decl, so that there is
- -- no problem with
- -- class C a where
- -- op :: Eq a => a -> b -> a
- --
- -- We do this for each method independently to localise error messages
-
- let
- [(_, Just sig, local_meth_id)] = mono_bind_infos
- loc = sig_loc sig
-
- addErrCtxtM (sigCtxt sel_id inst_tyvars inst_theta (idType meth_id)) $ do
- meth_dicts <- newDictBndrs loc (sig_theta sig)
- let
- meth_tvs = sig_tvs sig
- all_tyvars = meth_tvs ++ inst_tyvars
- all_insts = avail_insts ++ meth_dicts