- -> 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 (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 ])
+ -> Bool -- True <=> This method is from an instance declaration
+ -> ClassOpItem -- The method selector and default-method Id
+ -> TcM (TcMonoBinds, LIE, Inst)
+
+tcMethodBind clas origin inst_tyvars inst_tys inst_theta
+ meth_binds prags is_inst_decl (sel_id, dm_info)
+ = tcGetSrcLoc `thenNF_Tc` \ loc ->
+ newMethod origin sel_id inst_tys `thenNF_Tc` \ meth ->
+ let
+ meth_id = instToId meth
+ meth_name = idName meth_id
+ meth_prags = find_prags (idName sel_id) meth_name prags
+ in
+ mkTcSig meth_id loc `thenNF_Tc` \ sig_info ->
+
+ -- Figure out what method binding to use
+ -- If the user suppplied one, use it, else construct a default one
+ (case find_bind (idName sel_id) meth_name meth_binds of
+ Just user_bind -> returnTc user_bind
+ Nothing -> mkDefMethRhs is_inst_decl clas inst_tys sel_id loc dm_info `thenTc` \ rhs ->
+ returnTc (FunMonoBind meth_name False -- Not infix decl
+ [mkSimpleMatch [] rhs placeHolderType loc] loc)
+ ) `thenTc` \ meth_bind ->
+ -- Check the bindings; first add inst_tyvars to the envt
+ -- so that we don't quantify over them in nested places
+ -- The *caller* put the class/inst decl tyvars into the envt
+ tcExtendGlobalTyVars (mkVarSet inst_tyvars)
+ (tcAddErrCtxt (methodCtxt sel_id) $
+ tcBindWithSigs NotTopLevel meth_bind
+ [sig_info] meth_prags NonRecursive
+ ) `thenTc` \ (binds, insts, _) ->
+
+ tcExtendLocalValEnv [(meth_name, meth_id)]
+ (tcSpecSigs meth_prags) `thenTc` \ (prag_binds1, prag_lie) ->
+
+ -- 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
+ --
+ -- We do this for each method independently to localise error messages
+ -- ...and this is why the call to tcExtendGlobalTyVars must be here
+ -- rather than in the caller
+ tcAddErrCtxt (ptext SLIT("When checking the type of class method")
+ <+> quotes (ppr sel_id)) $
+ tcAddErrCtxtM (sigCtxt inst_tyvars inst_theta (idType meth_id)) $
+ checkSigTyVars inst_tyvars emptyVarSet `thenTc_`
+
+ returnTc (binds `AndMonoBinds` prag_binds1 `AndMonoBinds` prag_binds2,
+ insts `plusLIE` prag_lie',
+ meth)
+
+ -- The user didn't supply a method binding,
+ -- so we have to make up a default binding
+ -- The RHS of a default method depends on the default-method info
+mkDefMethRhs is_inst_decl clas inst_tys sel_id loc (DefMeth dm_name)
+ = -- An polymorphic default method
+ returnTc (HsVar dm_name)
+
+mkDefMethRhs is_inst_decl clas inst_tys sel_id loc NoDefMeth
+ = -- No default method
+ -- Warn only if -fwarn-missing-methods
+ doptsTc Opt_WarnMissingMethods `thenNF_Tc` \ warn ->
+ warnTc (is_inst_decl && warn)
+ (omittedMethodWarn sel_id) `thenNF_Tc_`
+ returnTc error_rhs
+ where
+ error_rhs = HsApp (HsVar (getName nO_METHOD_BINDING_ERROR_ID))
+ (HsLit (HsString (_PK_ error_msg)))
+ error_msg = showSDoc (hcat [ppr loc, text "|", ppr sel_id ])
+
+
+mkDefMethRhs is_inst_decl clas inst_tys sel_id loc GenDefMeth
+ = -- A generic default method
+ -- If the method is defined generically, we can only do the job if the
+ -- instance declaration is for a single-parameter type class with
+ -- a type constructor applied to type arguments in the instance decl
+ -- (checkTc, so False provokes the error)
+ checkTc (not is_inst_decl || simple_inst)
+ (badGenericInstance sel_id) `thenTc_`
+
+ ioToTc (dumpIfSet opt_PprStyle_Debug "Generic RHS" stuff) `thenNF_Tc_`
+ returnTc rhs
+ where
+ rhs = mkGenericRhs sel_id clas_tyvar tycon
+
+ stuff = vcat [ppr clas <+> ppr inst_tys,
+ nest 4 (ppr sel_id <+> equals <+> ppr rhs)]
+
+ -- The tycon is only used in the generic case, and in that
+ -- case we require that the instance decl is for a single-parameter
+ -- type class with type variable arguments:
+ -- instance (...) => C (T a b)
+ simple_inst = maybeToBool maybe_tycon
+ clas_tyvar = head (classTyVars clas)
+ Just tycon = maybe_tycon
+ maybe_tycon = case inst_tys of
+ [ty] -> case tcSplitTyConApp_maybe ty of
+ Just (tycon, arg_tys) | all tcIsTyVarTy arg_tys -> Just tycon
+ other -> Nothing
+ other -> Nothing
+\end{code}
+
+
+\begin{code}
+-- 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 sel_name meth_name (FunMonoBind op_name fix matches loc)
+ | op_name == sel_name = Just (FunMonoBind meth_name fix matches loc)
+find_bind sel_name meth_name (AndMonoBinds b1 b2)
+ = find_bind sel_name meth_name b1 `seqMaybe` find_bind sel_name meth_name b2
+find_bind sel_name meth_name other = Nothing -- Default case
+
+ -- Find the prags for this method, and replace the
+ -- selector name with the method name
+find_prags sel_name meth_name [] = []
+find_prags sel_name meth_name (SpecSig name ty loc : prags)
+ | name == sel_name = SpecSig meth_name ty loc : find_prags sel_name meth_name prags
+find_prags sel_name meth_name (InlineSig sense name phase loc : prags)
+ | name == sel_name = InlineSig sense meth_name phase loc : find_prags sel_name meth_name prags
+find_prags sel_name meth_name (prag:prags) = find_prags sel_name meth_name prags