+ -> 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)
+ = tcGetSrcLoc `thenNF_Tc` \ loc ->
+
+ newMethod origin (RealId sel_id) inst_tys `thenNF_Tc` \ meth@(_, TcId meth_id) ->
+ mkTcSig meth_id loc `thenNF_Tc` \ sig_info ->
+
+ let
+ meth_name = idName meth_id
+ maybe_user_bind = find_bind meth_name 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}
+
+ meth_bind = case maybe_user_bind of
+ Just bind -> bind
+ Nothing -> mk_default_bind meth_name loc
+
+ meth_prags = find_prags meth_name prags
+ in
+
+ -- Warn if no method binding, only if -fwarn-missing-methods
+ if no_user_bind && not supply_default_bind then
+ pprPanic "tcMethodBind" (ppr clas <+> ppr inst_tys)
+ else
+ warnTc (opt_WarnMissingMethods && no_user_bind && no_user_default)
+ (omittedMethodWarn sel_id clas) `thenNF_Tc_`
+
+ -- Check the pragmas
+ tcExtendLocalValEnv [meth_name] [meth_id] (
+ tcPragmaSigs meth_prags
+ ) `thenTc` \ (prag_info_fn, prag_binds1, prag_lie) ->
+
+ -- Check the bindings
+ tcExtendGlobalTyVars (mkVarSet inst_tyvars) (
+ tcAddErrCtxt (methodCtxt sel_id) $
+ tcBindWithSigs NotTopLevel 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
+ tcAddErrCtxtM (sigCtxt (quotes (ppr sel_id)) (idType meth_id)) (
+ checkSigTyVars inst_tyvars `thenTc_`
+
+ returnTc (binds `AndMonoBinds` prag_binds1 `AndMonoBinds` prag_binds2,
+ insts `plusLIE` prag_lie',
+ meth))
+
+ where
+ sel_name = idName sel_id
+
+ -- 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.
+ find_bind meth_name (FunMonoBind op_name fix matches loc)
+ | op_name == sel_name = Just (FunMonoBind meth_name fix matches loc)
+ find_bind meth_name (PatMonoBind (VarPatIn op_name) rhs loc)
+ | op_name == sel_name = Just (PatMonoBind (VarPatIn meth_name) rhs loc)
+ find_bind meth_name (AndMonoBinds b1 b2)
+ = find_bind meth_name b1 `seqMaybe` find_bind meth_name b2
+ find_bind meth_name other = Nothing -- Default case
+
+
+ -- 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 (NoInlineSig name loc : prags)
+ | name == sel_name = NoInlineSig 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}