+ -> InstOrigin s
+ -> [TcType s] -- Instance types
+ -> [TcTyVar s] -- Free variables of those instance types
+ -- they'll be signature tyvars, and we
+ -- want to check that they don't bound
+ -> RenamedMonoBinds -- Method binding (pick the right one from in here)
+ -> [RenamedSig] -- Pramgas (just for this one)
+ -> Bool -- True <=> supply default decl if no explicit decl
+ -- This is true for instance decls,
+ -- false for class decls
+ -> (Id, Maybe Id) -- The method selector and default-method Id
+ -> TcM s (TcMonoBinds s, LIE s, (LIE s, TcIdOcc s))
+
+tcMethodBind clas origin inst_tys inst_tyvars
+ meth_binds prags supply_default_bind
+ (sel_id, maybe_dm_id)
+ | no_user_bind && not supply_default_bind
+ = pprPanic "tcMethodBind" (ppr clas <+> ppr inst_tys)
+
+ | otherwise
+ = tcGetSrcLoc `thenNF_Tc` \ loc ->
+
+ -- Warn if no method binding, only if -fwarn-missing-methods
+ warnTc (opt_WarnMissingMethods && no_user_bind && no_user_default)
+ (omittedMethodWarn sel_id clas) `thenNF_Tc_`
+
+ newMethod origin (RealId sel_id) inst_tys `thenNF_Tc` \ meth@(_, TcId meth_id) ->
+ tcInstSigTcType (idType meth_id) `thenNF_Tc` \ (tyvars', rho_ty') ->
+ let
+ (theta', tau') = splitRhoTy rho_ty'
+
+ meth_name = idName meth_id
+ sig_info = TySigInfo meth_name meth_id tyvars' theta' tau' loc
+ meth_bind = mk_meth_bind meth_name loc
+ meth_prags = find_prags meth_name prags
+ in
+ tcExtendLocalValEnv [meth_name] [meth_id] (
+ tcPragmaSigs meth_prags
+ ) `thenTc` \ (prag_info_fn, prag_binds1, prag_lie) ->
+
+ -- Check that the signatures match
+ tcExtendGlobalTyVars inst_tyvars (
+ tcAddErrCtxt (methodCtxt sel_id) $
+ tcBindWithSigs NotTopLevel [meth_name] meth_bind [sig_info]
+ NonRecursive prag_info_fn
+ ) `thenTc` \ (binds, insts, _) ->
+
+ -- The prag_lie for a SPECIALISE pragma will mention the function
+ -- itself, so we have to simplify them away right now lest they float
+ -- outwards!
+ bindInstsOfLocalFuns prag_lie [meth_id] `thenTc` \ (prag_lie', prag_binds2) ->
+
+ -- Now check that the instance type variables
+ -- (or, in the case of a class decl, the class tyvars)
+ -- have not been unified with anything in the environment
+ tcAddErrCtxt (monoCtxt sel_id) (
+ tcAddErrCtxt (sigCtxt sel_id) $
+ checkSigTyVars inst_tyvars (idType meth_id)
+ ) `thenTc_`
+
+ returnTc (binds `AndMonoBinds` prag_binds1 `AndMonoBinds` prag_binds2,
+ insts `plusLIE` prag_lie',
+ meth)
+ where
+ sel_name = idName sel_id
+
+ maybe_user_bind = find meth_binds
+
+ no_user_bind = case maybe_user_bind of {Nothing -> True; other -> False}
+ no_user_default = case maybe_dm_id of {Nothing -> True; other -> False}
+
+ find EmptyMonoBinds = Nothing
+ find (AndMonoBinds b1 b2) = find b1 `seqMaybe` find b2
+ find b@(FunMonoBind op_name _ _ _) = if op_name == sel_name then Just b else Nothing
+ find b@(PatMonoBind (VarPatIn op_name) _ _) = if op_name == sel_name then Just b else Nothing
+ find other = panic "Urk! Bad instance method binding"
+
+ -- The renamer just puts the selector ID as the binder in the method binding
+ -- but we must use the method name; so we substitute it here. Crude but simple.
+ mk_meth_bind meth_name loc
+ = case maybe_user_bind of
+ Just (FunMonoBind _ fix matches loc) -> FunMonoBind meth_name fix matches loc
+ Just (PatMonoBind (VarPatIn _) rhs loc) -> PatMonoBind (VarPatIn meth_name) rhs loc
+ Nothing -> mk_default_bind meth_name loc
+
+ -- Find the prags for this method, and replace the
+ -- selector name with the method name
+ find_prags meth_name [] = []
+ find_prags meth_name (SpecSig name ty spec loc : prags)
+ | name == sel_name = SpecSig meth_name ty spec loc : find_prags meth_name prags
+ find_prags meth_name (InlineSig name loc : prags)
+ | name == sel_name = InlineSig meth_name loc : find_prags meth_name prags
+ find_prags meth_name (prag:prags) = find_prags meth_name prags
+
+ mk_default_bind local_meth_name loc
+ = PatMonoBind (VarPatIn local_meth_name)
+ (GRHSsAndBindsIn (unguardedRHS (default_expr loc) loc) EmptyBinds)
+ loc
+
+ default_expr loc
+ = case maybe_dm_id of
+ Just dm_id -> HsVar (getName dm_id) -- There's a default method
+ Nothing -> error_expr loc -- No default method
+
+ error_expr loc = HsApp (HsVar (getName nO_METHOD_BINDING_ERROR_ID))
+ (HsLit (HsString (_PK_ (error_msg loc))))
+
+ error_msg loc = showSDoc (hcat [ppr loc, text "|", ppr sel_id ])
+\end{code}
+
+Contexts and errors
+~~~~~~~~~~~~~~~~~~~
+\begin{code}
+classArityErr class_name
+ = ptext SLIT("Too many parameters for class") <+> quotes (ppr class_name)
+
+classDeclCtxt class_name
+ = ptext SLIT("In the class declaration for") <+> quotes (ppr class_name)
+
+methodCtxt sel_id
+ = ptext SLIT("In the definition for method") <+> quotes (ppr sel_id)