-%************************************************************************
-%* *
-\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
- :: InstOrigin
- -> [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 -- Current dictionary (this_dict)
- -> [Inst] -- Other stuff available from context, used to simplify
- -- constraints from the method body (exclude this_dict)
- -> TcSigFun -- For scoped tyvars, indexed by sel_name
- -> TcPragFun -- Pragmas (e.g. inline pragmas), indexed by sel_name
- -> LHsBinds Name -- Method binding (pick the right one from in here)
- -> ClassOpItem
- -> TcId -- The method Id
- -> TcM (LHsBinds Id)
-
-tcMethodBind origin inst_tyvars inst_theta
- this_dict extra_insts
- sig_fn prag_fn meth_binds
- (sel_id, dm_info) meth_id
- | Just user_bind <- find_bind sel_name meth_name meth_binds
- = -- If there is a user-supplied method binding, typecheck it
- tc_method_bind inst_tyvars inst_theta (this_dict:extra_insts)
- sig_fn prag_fn
- sel_id meth_id user_bind
-
- | otherwise -- The user didn't supply a method binding, so we have to make
- -- up a default binding, in a way depending on the default-method info
- = case dm_info of
- NoDefMeth -> do { warn <- doptM Opt_WarnMissingMethods
- ; warnTc (isInstDecl origin
- && warn -- Warn only if -fwarn-missing-methods
- && reportIfUnused (getOccName sel_id))
- -- Don't warn about _foo methods
- (omittedMethodWarn sel_id)
- ; return (unitBag $ L loc (VarBind meth_id error_rhs)) }
-
- DefMeth -> do { -- An polymorphic default method
- -- Might not be imported, but will be an OrigName
- dm_name <- lookupImportedName (mkDefMethRdrName sel_id)
- ; dm_id <- tcLookupId dm_name
- -- Note [Default methods in instances]
- ; return (unitBag $ L loc (VarBind meth_id (mk_dm_app dm_id))) }
-
- GenDefMeth -> ASSERT( isInstDecl origin ) -- We never get here from a class decl
- do { meth_bind <- mkGenericDefMethBind clas inst_tys sel_id meth_name
- ; tc_method_bind inst_tyvars inst_theta (this_dict:extra_insts)
- sig_fn prag_fn
- sel_id meth_id meth_bind }
+---------------------------
+-- 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.
+findMethodBind :: Name -> Name -- Selector and method name
+ -> LHsBinds Name -- A group of bindings
+ -> Maybe (LHsBind Name) -- The binding, with meth_name replacing sel_name
+findMethodBind sel_name meth_name binds
+ = foldlBag mplus Nothing (mapBag f binds)
+ where
+ f (L loc1 bind@(FunBind { fun_id = L loc2 op_name }))
+ | op_name == sel_name
+ = Just (L loc1 (bind { fun_id = L loc2 meth_name }))
+ f _other = Nothing