module TcExpr ( tcExpr ) where
-import Ubiq
+IMP_Ubiq()
-import HsSyn ( HsExpr(..), Qual(..), Stmt(..),
+import HsSyn ( HsExpr(..), Qualifier(..), Stmt(..),
HsBinds(..), Bind(..), MonoBinds(..),
ArithSeqInfo(..), HsLit(..), Sig, GRHSsAndBinds,
Match, Fake, InPat, OutPat, PolyType,
- irrefutablePat, collectPatBinders )
-import RnHsSyn ( RenamedHsExpr(..), RenamedQual(..), RenamedStmt(..) )
-import TcHsSyn ( TcExpr(..), TcQual(..), TcStmt(..), TcIdOcc(..) )
-
-import TcMonad
+ failureFreePat, collectPatBinders )
+import RnHsSyn ( SYN_IE(RenamedHsExpr), SYN_IE(RenamedQual),
+ SYN_IE(RenamedStmt), SYN_IE(RenamedRecordBinds),
+ RnName{-instance Outputable-}
+ )
+import TcHsSyn ( SYN_IE(TcExpr), SYN_IE(TcQual), SYN_IE(TcStmt),
+ TcIdOcc(..), SYN_IE(TcRecordBinds),
+ mkHsTyApp
+ )
+
+import TcMonad hiding ( rnMtoTcM )
import Inst ( Inst, InstOrigin(..), OverloadedLit(..),
- LIE(..), emptyLIE, plusLIE, newOverloadedLit,
+ SYN_IE(LIE), emptyLIE, plusLIE, plusLIEs, newOverloadedLit,
newMethod, newMethodWithGivenTy, newDicts )
import TcBinds ( tcBindsAndThen )
import TcEnv ( tcLookupLocalValue, tcLookupGlobalValue, tcLookupClassByKey,
- tcLookupGlobalValueByKey, newMonoIds, tcGetGlobalTyVars )
+ tcLookupGlobalValueByKey, newMonoIds, tcGetGlobalTyVars,
+ tcExtendGlobalTyVars
+ )
+import SpecEnv ( SpecEnv )
import TcMatches ( tcMatchesCase, tcMatch )
import TcMonoType ( tcPolyType )
import TcPat ( tcPat )
import TcSimplify ( tcSimplifyAndCheck, tcSimplifyRank2 )
-import TcType ( TcType(..), TcMaybe(..), tcReadTyVar,
- tcInstType, tcInstTcType,
- tcInstTyVar, newTyVarTy, zonkTcTyVars )
+import TcType ( SYN_IE(TcType), TcMaybe(..),
+ tcInstId, tcInstType, tcInstSigTcType,
+ tcInstSigType, tcInstTcType, tcInstTheta,
+ newTyVarTy, zonkTcTyVars, zonkTcType )
import TcKind ( TcKind )
-import Class ( Class(..), getClassSig )
-import Id ( Id(..), GenId, idType )
-import Kind ( Kind, mkBoxedTypeKind, mkTypeKind )
-import GenSpecEtc ( checkSigTyVars, checkSigTyVarsGivenGlobals, specTy )
-import PrelInfo ( intPrimTy, charPrimTy, doublePrimTy,
- floatPrimTy, addrPrimTy, addrTy,
+import Class ( SYN_IE(Class), classSig )
+import FieldLabel ( fieldLabelName )
+import Id ( idType, dataConFieldLabels, dataConSig, SYN_IE(Id), GenId )
+import Kind ( Kind, mkBoxedTypeKind, mkTypeKind, mkArrowKind )
+import GenSpecEtc ( checkSigTyVars )
+import Name ( Name{-instance Eq-} )
+import Type ( mkFunTy, mkAppTy, mkTyVarTy, mkTyVarTys, mkRhoTy,
+ getTyVar_maybe, getFunTy_maybe, instantiateTy,
+ splitForAllTy, splitRhoTy, splitSigmaTy, splitFunTy,
+ isTauTy, mkFunTys, tyVarsOfType, getForAllTy_maybe,
+ getAppDataTyCon, maybeAppDataTyCon
+ )
+import TyVar ( GenTyVar, SYN_IE(TyVarSet), unionTyVarSets, mkTyVarSet )
+import TysPrim ( intPrimTy, charPrimTy, doublePrimTy,
+ floatPrimTy, addrPrimTy, realWorldTy
+ )
+import TysWiredIn ( addrTy,
boolTy, charTy, stringTy, mkListTy,
- mkTupleTy, mkPrimIoTy )
-import Type ( mkFunTy, mkAppTy, mkTyVarTy, mkTyVarTys,
- getTyVar_maybe, getFunTy_maybe,
- splitForAllTy, splitRhoTy, splitSigmaTy,
- isTauTy, mkFunTys, tyVarsOfType, getForAllTy_maybe )
-import TyVar ( GenTyVar, TyVarSet(..), unionTyVarSets, mkTyVarSet )
-import Unify ( unifyTauTy, unifyTauTyList, unifyTauTyLists )
+ mkTupleTy, mkPrimIoTy, stDataCon
+ )
+import Unify ( unifyTauTy, unifyTauTyList, unifyTauTyLists, unifyFunTy )
import Unique ( Unique, cCallableClassKey, cReturnableClassKey,
enumFromClassOpKey, enumFromThenClassOpKey,
enumFromToClassOpKey, enumFromThenToClassOpKey,
- monadClassKey, monadZeroClassKey )
-
-import Name ( Name ) -- Instance
+ thenMClassOpKey, zeroClassOpKey
+ )
+import Outputable ( interpp'SP )
import PprType ( GenType, GenTyVar ) -- Instances
import Maybes ( maybeToBool )
import Pretty
\begin{code}
tcExpr (HsVar name)
- = tcId name `thenTc` \ (expr', lie, res_ty) ->
+ = tcId name `thenNF_Tc` \ (expr', lie, res_ty) ->
-- Check that the result type doesn't have any nested for-alls.
-- For example, a "build" on its own is no good; it must be
%************************************************************************
\begin{code}
+tcExpr (HsPar expr) -- preserve parens so printing needn't guess where they go
+ = tcExpr expr
+
+tcExpr (NegApp expr neg) = tcExpr (HsApp neg expr)
+
tcExpr (HsLam match)
= tcMatch match `thenTc` \ (match',lie,ty) ->
returnTc (HsLam match', lie, ty)
newTyVarTy mkTypeKind `thenNF_Tc` \ ty1 ->
newTyVarTy mkTypeKind `thenNF_Tc` \ ty2 ->
tcAddErrCtxt (sectionRAppCtxt in_expr) $
- unifyTauTy op_ty (mkFunTys [ty1, expr_ty] ty2) `thenTc_`
+ unifyTauTy (mkFunTys [ty1, expr_ty] ty2) op_ty `thenTc_`
returnTc (SectionR op' expr', lie1 `plusLIE` lie2, mkFunTy ty1 ty2)
\end{code}
-- Construct the extra insts, which encode the
-- constraints on the argument and result types.
- mapNF_Tc new_arg_dict (args `zip` arg_tys) `thenNF_Tc` \ ccarg_dicts_s ->
- newDicts result_origin [(cReturnableClass, result_ty)] `thenNF_Tc` \ (ccres_dict, _) ->
+ mapNF_Tc new_arg_dict (zipEqual "tcExpr:CCall" args arg_tys) `thenNF_Tc` \ ccarg_dicts_s ->
+ newDicts result_origin [(cReturnableClass, result_ty)] `thenNF_Tc` \ (ccres_dict, _) ->
- returnTc (CCall lbl args' may_gc is_asm result_ty,
+ returnTc (HsCon stDataCon [realWorldTy, result_ty] [CCall lbl args' may_gc is_asm result_ty],
+ -- do the wrapping in the newtype constructor here
foldr plusLIE ccres_dict ccarg_dicts_s `plusLIE` args_lie,
mkPrimIoTy result_ty)
\end{code}
tcExpr pred `thenTc` \ (pred',lie1,predTy) ->
tcAddErrCtxt (predCtxt pred) (
- unifyTauTy predTy boolTy
+ unifyTauTy boolTy predTy
) `thenTc_`
tcExpr b1 `thenTc` \ (b1',lie2,result_ty) ->
\end{code}
\begin{code}
-tcExpr (HsDo stmts src_loc)
- = -- get the Monad and MonadZero classes
- -- create type consisting of a fresh monad tyvar
- tcAddSrcLoc src_loc $
- tcLookupClassByKey monadClassKey `thenNF_Tc` \ monadClass ->
- tcLookupClassByKey monadZeroClassKey `thenNF_Tc` \ monadZeroClass ->
- let
- (tv,_,_) = getClassSig monadClass
- in
- tcInstTyVar tv `thenNF_Tc` \ m_tyvar ->
- let
- m = mkTyVarTy m_tyvar
- in
- tcDoStmts False m stmts `thenTc` \ ((stmts',monad,mzero), lie, do_ty) ->
-
- -- create dictionaries for monad and possibly monadzero
- (if monad then
- newDicts DoOrigin [(monadClass, m)]
- else
- returnNF_Tc (emptyLIE, [panic "TcExpr: MonadZero dictionary"])
- ) `thenNF_Tc` \ (m_lie, [m_id]) ->
- (if mzero then
- newDicts DoOrigin [(monadZeroClass, m)]
- else
- returnNF_Tc (emptyLIE, [panic "TcExpr: MonadZero dictionary"])
- ) `thenNF_Tc` \ (mz_lie, [mz_id]) ->
-
- returnTc (HsDoOut stmts' m_id mz_id src_loc,
- lie `plusLIE` m_lie `plusLIE` mz_lie,
- do_ty)
+tcExpr expr@(HsDo stmts src_loc)
+ = tcDoStmts stmts src_loc
\end{code}
\begin{code}
= tcExprs exprs `thenTc` \ (exprs', lie, tys) ->
returnTc (ExplicitTuple exprs', lie, mkTupleTy (length tys) tys)
-tcExpr (RecordCon con rbinds)
- = panic "tcExpr:RecordCon"
-tcExpr (RecordUpd exp rbinds)
- = panic "tcExpr:RecordUpd"
+tcExpr (RecordCon (HsVar con) rbinds)
+ = tcId con `thenNF_Tc` \ (con_expr, con_lie, con_tau) ->
+ let
+ (_, record_ty) = splitFunTy con_tau
+ in
+ -- Con is syntactically constrained to be a data constructor
+ ASSERT( maybeToBool (maybeAppDataTyCon record_ty ) )
+
+ tcRecordBinds record_ty rbinds `thenTc` \ (rbinds', rbinds_lie) ->
+
+ -- Check that the record bindings match the constructor
+ tcLookupGlobalValue con `thenNF_Tc` \ con_id ->
+ checkTc (checkRecordFields rbinds con_id)
+ (badFieldsCon con rbinds) `thenTc_`
+
+ returnTc (RecordCon con_expr rbinds', con_lie `plusLIE` rbinds_lie, record_ty)
+
+-- One small complication in RecordUpd is that we have to generate some
+-- dictionaries for the data type context, since we are going to
+-- do some construction.
+--
+-- What dictionaries do we need? For the moment we assume that all
+-- data constructors have the same context, and grab it from the first
+-- constructor. If they have varying contexts then we'd have to
+-- union the ones that could participate in the update.
+
+tcExpr (RecordUpd record_expr rbinds)
+ = ASSERT( not (null rbinds) )
+ tcAddErrCtxt recordUpdCtxt $
+
+ tcExpr record_expr `thenTc` \ (record_expr', record_lie, record_ty) ->
+ tcRecordBinds record_ty rbinds `thenTc` \ (rbinds', rbinds_lie) ->
+
+ -- Check that the field names are plausible
+ zonkTcType record_ty `thenNF_Tc` \ record_ty' ->
+ let
+ (tycon, inst_tys, data_cons) = --trace "TcExpr.getAppDataTyCon" $
+ getAppDataTyCon record_ty'
+ -- The record binds are non-empty (syntax); so at least one field
+ -- label will have been unified with record_ty by tcRecordBinds;
+ -- field labels must be of data type; hencd the getAppDataTyCon must succeed.
+ (tyvars, theta, _, _) = dataConSig (head data_cons)
+ in
+ tcInstTheta (zipEqual "tcExpr:RecordUpd" tyvars inst_tys) theta `thenNF_Tc` \ theta' ->
+ newDicts RecordUpdOrigin theta' `thenNF_Tc` \ (con_lie, dicts) ->
+ checkTc (any (checkRecordFields rbinds) data_cons)
+ (badFieldsUpd rbinds) `thenTc_`
+
+ returnTc (RecordUpdOut record_expr' dicts rbinds',
+ con_lie `plusLIE` record_lie `plusLIE` rbinds_lie,
+ record_ty)
tcExpr (ArithSeqIn seq@(From expr))
= tcExpr expr `thenTc` \ (expr', lie1, ty) ->
-- Check the tau-type part
tcSetErrCtxt (exprSigCtxt in_expr) $
- specTy SignatureOrigin sigma_sig `thenNF_Tc` \ (sig_tyvars, sig_dicts, sig_tau, _) ->
- unifyTauTy tau_ty sig_tau `thenTc_`
+ tcInstSigType sigma_sig `thenNF_Tc` \ sigma_sig' ->
+ let
+ (sig_tyvars', sig_theta', sig_tau') = splitSigmaTy sigma_sig'
+ in
+ unifyTauTy sig_tau' tau_ty `thenTc_`
-- Check the type variables of the signature
- checkSigTyVars sig_tyvars sig_tau tau_ty `thenTc` \ sig_tyvars' ->
+ checkSigTyVars sig_tyvars' sig_tau' `thenTc_`
-- Check overloading constraints
+ newDicts SignatureOrigin sig_theta' `thenNF_Tc` \ (sig_dicts, _) ->
tcSimplifyAndCheck
(mkTyVarSet sig_tyvars')
sig_dicts lie `thenTc_`
-- In the HsVar case we go straight to tcId to avoid hitting the
-- rank-2 check, which we check later here anyway
(case fun of
- HsVar name -> tcId name
+ HsVar name -> tcId name `thenNF_Tc` \ stuff -> returnTc stuff
other -> tcExpr fun
) `thenTc` \ (fun', lie_fun, fun_ty) ->
tcApp_help orig_fun arg_no fun_ty []
= returnTc ([], emptyLIE, fun_ty)
-tcApp_help orig_fun arg_no fun_ty (arg:args)
- | maybeToBool maybe_arrow_ty
- = -- The function's type is A->B
+tcApp_help orig_fun arg_no fun_ty all_args@(arg:args)
+ = -- Expect the function to have type A->B
+ tcAddErrCtxt (tooManyArgsCtxt orig_fun) (
+ unifyFunTy fun_ty
+ ) `thenTc` \ (expected_arg_ty, result_ty) ->
+
+ -- Type check the argument
tcAddErrCtxt (funAppCtxt orig_fun arg_no arg) (
- tcArg expected_arg_ty arg
- ) `thenTc` \ (arg', lie_arg) ->
+ tcArg expected_arg_ty arg
+ ) `thenTc` \ (arg', lie_arg) ->
+ -- Do the other args
tcApp_help orig_fun (arg_no+1) result_ty args `thenTc` \ (args', lie_args, res_ty) ->
- returnTc (arg':args', lie_arg `plusLIE` lie_args, res_ty)
-
- | maybeToBool maybe_tyvar_ty
- = -- The function's type is just a type variable
- tcReadTyVar fun_tyvar `thenNF_Tc` \ maybe_fun_ty ->
- case maybe_fun_ty of
-
- BoundTo new_fun_ty -> -- The tyvar in the corner of the function is bound
- -- to something ... so carry on ....
- tcApp_help orig_fun arg_no new_fun_ty (arg:args)
-
- UnBound -> -- Extra args match against an unbound type
- -- variable as the final result type, so unify the tyvar.
- newTyVarTy mkTypeKind `thenNF_Tc` \ result_ty ->
- tcExprs args `thenTc` \ (args', lie_args, arg_tys) ->
- -- Unification can't fail, since we're unifying against a tyvar
- unifyTauTy fun_ty (mkFunTys arg_tys result_ty) `thenTc_`
-
- returnTc (args', lie_args, result_ty)
-
- | otherwise
- = -- Must be an error: a lurking for-all, or (more commonly)
- -- a TyConTy... we've applied the function to too many args
- failTc (tooManyArgs orig_fun)
-
- where
- maybe_arrow_ty = getFunTy_maybe fun_ty
- Just (expected_arg_ty, result_ty) = maybe_arrow_ty
+ -- Done
+ returnTc (arg':args', lie_arg `plusLIE` lie_args, res_ty)
- maybe_tyvar_ty = getTyVar_maybe fun_ty
- Just fun_tyvar = maybe_tyvar_ty
\end{code}
\begin{code}
-- of instantiating a function involving rank-2 polymorphism, so there
-- isn't any danger of using the same tyvars twice
-- The argument type shouldn't be overloaded type (hence ASSERT)
+
+ -- To ensure that the forall'd type variables don't get unified with each
+ -- other or any other types, we make fresh *signature* type variables
+ -- and unify them with the tyvars.
+ tcInstSigTcType expected_arg_ty `thenNF_Tc` \ (sig_tyvars, sig_rho) ->
let
- (expected_tyvars, expected_theta, expected_tau) = splitSigmaTy expected_arg_ty
+ (sig_theta, sig_tau) = splitRhoTy sig_rho
in
- ASSERT( null expected_theta )
-
+ ASSERT( null sig_theta ) -- And expected_tyvars are all DontBind things
+
-- Type-check the arg and unify with expected type
tcExpr arg `thenTc` \ (arg', lie_arg, actual_arg_ty) ->
- unifyTauTy expected_tau actual_arg_ty `thenTc_` (
+ unifyTauTy sig_tau actual_arg_ty `thenTc_`
-- Check that the arg_tyvars havn't been constrained
-- The interesting bit here is that we must include the free variables
-- So now s' isn't unconstrained because it's linked to a.
-- Conclusion: include the free vars of the expected arg type in the
-- list of "free vars" for the signature check.
- tcAddErrCtxt (rank2ArgCtxt arg expected_arg_ty) $
- tcGetGlobalTyVars `thenNF_Tc` \ env_tyvars ->
- zonkTcTyVars (tyVarsOfType expected_arg_ty) `thenNF_Tc` \ free_tyvars ->
- checkSigTyVarsGivenGlobals
- (env_tyvars `unionTyVarSets` free_tyvars)
- expected_tyvars expected_tau actual_arg_ty `thenTc` \ arg_tyvars' ->
-
- -- Check that there's no overloading involved
- -- Even if there isn't, there may be some Insts which mention the arg_tyvars,
- -- but which, on simplification, don't actually need a dictionary involving
- -- the tyvar. So we have to do a proper simplification right here.
- tcSimplifyRank2 (mkTyVarSet arg_tyvars')
- lie_arg `thenTc` \ (free_insts, inst_binds) ->
-
- -- This HsLet binds any Insts which came out of the simplification.
- -- It's a bit out of place here, but using AbsBind involves inventing
- -- a couple of new names which seems worse.
- returnTc (TyLam arg_tyvars' (HsLet (mk_binds inst_binds) arg'), free_insts)
+
+ tcAddErrCtxt (rank2ArgCtxt arg expected_arg_ty) (
+ tcExtendGlobalTyVars (tyVarsOfType expected_arg_ty) (
+ checkSigTyVars sig_tyvars sig_tau
+ ) `thenTc_`
+
+ -- Check that there's no overloading involved
+ -- Even if there isn't, there may be some Insts which mention the expected_tyvars,
+ -- but which, on simplification, don't actually need a dictionary involving
+ -- the tyvar. So we have to do a proper simplification right here.
+ tcSimplifyRank2 (mkTyVarSet sig_tyvars)
+ lie_arg `thenTc` \ (free_insts, inst_binds) ->
+
+ -- This HsLet binds any Insts which came out of the simplification.
+ -- It's a bit out of place here, but using AbsBind involves inventing
+ -- a couple of new names which seems worse.
+ returnTc (TyLam sig_tyvars (HsLet (mk_binds inst_binds) arg'), free_insts)
)
where
- mk_binds []
- = EmptyBinds
+ mk_binds [] = EmptyBinds
mk_binds ((inst,rhs):inst_binds)
- = (SingleBind (NonRecBind (VarMonoBind inst rhs)))
- `ThenBinds`
+ = (SingleBind (NonRecBind (VarMonoBind inst rhs))) `ThenBinds`
mk_binds inst_binds
\end{code}
%************************************************************************
\begin{code}
-tcId :: Name -> TcM s (TcExpr s, LIE s, TcType s)
+tcId :: RnName -> NF_TcM s (TcExpr s, LIE s, TcType s)
+
tcId name
= -- Look up the Id and instantiate its type
- (tcLookupLocalValue name `thenNF_Tc` \ maybe_local ->
- case maybe_local of
- Just tc_id -> tcInstTcType [] (idType tc_id) `thenNF_Tc` \ ty ->
- returnNF_Tc (TcId tc_id, ty)
-
- Nothing -> tcLookupGlobalValue name `thenNF_Tc` \ id ->
- tcInstType [] (idType id) `thenNF_Tc` \ ty ->
- returnNF_Tc (RealId id, ty)
- ) `thenNF_Tc` \ (tc_id_occ, ty) ->
- let
- (tyvars, rho) = splitForAllTy ty
- (theta,tau) = splitRhoTy rho
- arg_tys = mkTyVarTys tyvars
- in
- -- Is it overloaded?
- case theta of
- [] -> -- Not overloaded, so just make a type application
- returnTc (TyApp (HsVar tc_id_occ) arg_tys, emptyLIE, tau)
-
- _ -> -- Overloaded, so make a Method inst
- newMethodWithGivenTy (OccurrenceOf tc_id_occ)
- tc_id_occ arg_tys rho `thenNF_Tc` \ (lie, meth_id) ->
- returnTc (HsVar meth_id, lie, tau)
-\end{code}
+ tcLookupLocalValue name `thenNF_Tc` \ maybe_local ->
+
+ case maybe_local of
+ Just tc_id -> instantiate_it (TcId tc_id) (idType tc_id)
+ Nothing -> tcLookupGlobalValue name `thenNF_Tc` \ id ->
+ tcInstType [] (idType id) `thenNF_Tc` \ inst_ty ->
+ let
+ (tyvars, rho) = splitForAllTy inst_ty
+ in
+ instantiate_it2 (RealId id) tyvars rho
+ where
+ -- The instantiate_it loop runs round instantiating the Id.
+ -- It has to be a loop because we are now prepared to entertain
+ -- types like
+ -- f:: forall a. Eq a => forall b. Baz b => tau
+ -- We want to instantiate this to
+ -- f2::tau {f2 = f1 b (Baz b), f1 = f a (Eq a)}
+ instantiate_it tc_id_occ ty
+ = tcInstTcType ty `thenNF_Tc` \ (tyvars, rho) ->
+ instantiate_it2 tc_id_occ tyvars rho
+
+ instantiate_it2 tc_id_occ tyvars rho
+ | null theta -- Is it overloaded?
+ = returnNF_Tc (mkHsTyApp (HsVar tc_id_occ) arg_tys, emptyLIE, tau)
+
+ | otherwise -- Yes, it's overloaded
+ = newMethodWithGivenTy (OccurrenceOf tc_id_occ)
+ tc_id_occ arg_tys rho `thenNF_Tc` \ (lie1, meth_id) ->
+ instantiate_it meth_id tau `thenNF_Tc` \ (expr, lie2, final_tau) ->
+ returnNF_Tc (expr, lie1 `plusLIE` lie2, final_tau)
+
+ where
+ (theta, tau) = splitRhoTy rho
+ arg_tys = mkTyVarTys tyvars
+\end{code}
%************************************************************************
%* *
-\subsection{@tcQuals@ typchecks list comprehension qualifiers}
+\subsection{@tcQuals@ typechecks list-comprehension qualifiers}
%* *
%************************************************************************
tcAddErrCtxt (qualCtxt qual) (
tcPat pat `thenTc` \ (pat', lie_pat, pat_ty) ->
tcExpr rhs `thenTc` \ (rhs', lie_rhs, rhs_ty) ->
+ -- NB: the environment has been extended with the new binders
+ -- which the rhs can't "see", but the renamer should have made
+ -- sure that everything is distinct by now, so there's no problem.
+ -- Putting the tcExpr before the newMonoIds messes up the nesting
+ -- of error contexts, so I didn't bother
+
unifyTauTy (mkListTy pat_ty) rhs_ty `thenTc_`
returnTc (GeneratorQual pat' rhs',
lie_pat `plusLIE` lie_rhs)
%************************************************************************
\begin{code}
-tcDoStmts :: Bool -- True => require a monad
- -> TcType s -- m
- -> [RenamedStmt]
- -> TcM s (([TcStmt s],
- Bool, -- True => Monad
- Bool), -- True => MonadZero
- LIE s,
- TcType s)
-
-tcDoStmts monad m [stmt@(ExprStmt exp src_loc)]
- = tcAddSrcLoc src_loc $
- tcSetErrCtxt (stmtCtxt stmt) $
- tcExpr exp `thenTc` \ (exp', exp_lie, exp_ty) ->
- (if monad then
- newTyVarTy mkTypeKind `thenNF_Tc` \ a ->
- unifyTauTy (mkAppTy m a) exp_ty
- else
- returnTc ()
- ) `thenTc_`
- returnTc (([ExprStmt exp' src_loc], monad, False), exp_lie, exp_ty)
-
-tcDoStmts _ m (stmt@(ExprStmt exp src_loc) : stmts)
- = tcAddSrcLoc src_loc (
- tcSetErrCtxt (stmtCtxt stmt) (
- tcExpr exp `thenTc` \ (exp', exp_lie, exp_ty) ->
- newTyVarTy mkTypeKind `thenNF_Tc` \ a ->
- unifyTauTy (mkAppTy m a) exp_ty `thenTc_`
- returnTc (ExprStmt exp' src_loc, exp_lie)
- )) `thenTc` \ (stmt', stmt_lie) ->
- tcDoStmts True m stmts `thenTc` \ ((stmts', _, mzero), stmts_lie, stmts_ty) ->
- returnTc ((stmt':stmts', True, mzero),
- stmt_lie `plusLIE` stmts_lie,
- stmts_ty)
-
-tcDoStmts _ m (stmt@(BindStmt pat exp src_loc) : stmts)
- = tcAddSrcLoc src_loc (
- tcSetErrCtxt (stmtCtxt stmt) (
- tcPat pat `thenTc` \ (pat', pat_lie, pat_ty) ->
- tcExpr exp `thenTc` \ (exp', exp_lie, exp_ty) ->
- newTyVarTy mkTypeKind `thenNF_Tc` \ a ->
- unifyTauTy a pat_ty `thenTc_`
- unifyTauTy (mkAppTy m a) exp_ty `thenTc_`
- returnTc (BindStmt pat' exp' src_loc, pat_lie `plusLIE` exp_lie, irrefutablePat pat')
- )) `thenTc` \ (stmt', stmt_lie, failure_free) ->
- tcDoStmts True m stmts `thenTc` \ ((stmts', _, mzero), stmts_lie, stmts_ty) ->
- returnTc ((stmt':stmts', True, mzero || not failure_free),
- stmt_lie `plusLIE` stmts_lie,
- stmts_ty)
-
-tcDoStmts monad m (LetStmt binds : stmts)
- = tcBindsAndThen -- No error context, but a binding group is
- combine -- rather a large thing for an error context anyway
- binds
- (tcDoStmts monad m stmts)
- where
- combine binds' (stmts', monad, mzero) = ((LetStmt binds' : stmts'), monad, mzero)
+tcDoStmts stmts src_loc
+ = -- get the Monad and MonadZero classes
+ -- create type consisting of a fresh monad tyvar
+ tcAddSrcLoc src_loc $
+ newTyVarTy (mkArrowKind mkBoxedTypeKind mkBoxedTypeKind) `thenNF_Tc` \ m ->
+
+ -- Build the then and zero methods in case we need them
+ tcLookupGlobalValueByKey thenMClassOpKey `thenNF_Tc` \ then_sel_id ->
+ tcLookupGlobalValueByKey zeroClassOpKey `thenNF_Tc` \ zero_sel_id ->
+ newMethod DoOrigin
+ (RealId then_sel_id) [m] `thenNF_Tc` \ (m_lie, then_id) ->
+ newMethod DoOrigin
+ (RealId zero_sel_id) [m] `thenNF_Tc` \ (mz_lie, zero_id) ->
+
+ let
+ get_m_arg ty
+ = newTyVarTy mkTypeKind `thenNF_Tc` \ arg_ty ->
+ unifyTauTy (mkAppTy m arg_ty) ty `thenTc_`
+ returnTc arg_ty
+
+ go [stmt@(ExprStmt exp src_loc)]
+ = tcAddSrcLoc src_loc $
+ tcSetErrCtxt (stmtCtxt stmt) $
+ tcExpr exp `thenTc` \ (exp', exp_lie, exp_ty) ->
+ returnTc ([ExprStmt exp' src_loc], exp_lie, exp_ty)
+
+ go (stmt@(ExprStmt exp src_loc) : stmts)
+ = tcAddSrcLoc src_loc (
+ tcSetErrCtxt (stmtCtxt stmt) (
+ tcExpr exp `thenTc` \ (exp', exp_lie, exp_ty) ->
+ get_m_arg exp_ty `thenTc` \ a ->
+ returnTc (a, exp', exp_lie)
+ )) `thenTc` \ (a, exp', exp_lie) ->
+ go stmts `thenTc` \ (stmts', stmts_lie, stmts_ty) ->
+ get_m_arg stmts_ty `thenTc` \ b ->
+ returnTc (ExprStmtOut exp' src_loc a b : stmts',
+ exp_lie `plusLIE` stmts_lie `plusLIE` m_lie,
+ stmts_ty)
+
+ go (stmt@(BindStmt pat exp src_loc) : stmts)
+ = newMonoIds (collectPatBinders pat) mkBoxedTypeKind $ \ _ ->
+ tcAddSrcLoc src_loc (
+ tcSetErrCtxt (stmtCtxt stmt) (
+ tcPat pat `thenTc` \ (pat', pat_lie, pat_ty) ->
+ tcExpr exp `thenTc` \ (exp', exp_lie, exp_ty) ->
+ -- See comments with tcListComp on GeneratorQual
+
+ get_m_arg exp_ty `thenTc` \ a ->
+ unifyTauTy pat_ty a `thenTc_`
+ returnTc (a, pat', exp', pat_lie `plusLIE` exp_lie)
+ )) `thenTc` \ (a, pat', exp', stmt_lie) ->
+ go stmts `thenTc` \ (stmts', stmts_lie, stmts_ty) ->
+ get_m_arg stmts_ty `thenTc` \ b ->
+ returnTc (BindStmtOut pat' exp' src_loc a b : stmts',
+ stmt_lie `plusLIE` stmts_lie `plusLIE` m_lie `plusLIE`
+ (if failureFreePat pat' then emptyLIE else mz_lie),
+ stmts_ty)
+
+ go (LetStmt binds : stmts)
+ = tcBindsAndThen -- No error context, but a binding group is
+ combine -- rather a large thing for an error context anyway
+ binds
+ (go stmts)
+ where
+ combine binds' stmts' = LetStmt binds' : stmts'
+ in
+
+ go stmts `thenTc` \ (stmts', final_lie, final_ty) ->
+ returnTc (HsDoOut stmts' then_id zero_id src_loc,
+ final_lie,
+ final_ty)
+\end{code}
+
+Game plan for record bindings
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+For each binding
+ field = value
+1. look up "field", to find its selector Id, which must have type
+ forall a1..an. T a1 .. an -> tau
+ where tau is the type of the field.
+
+2. Instantiate this type
+
+3. Unify the (T a1 .. an) part with the "expected result type", which
+ is passed in. This checks that all the field labels come from the
+ same type.
+
+4. Type check the value using tcArg, passing tau as the expected
+ argument type.
+
+This extends OK when the field types are universally quantified.
+
+Actually, to save excessive creation of fresh type variables,
+we
+
+\begin{code}
+tcRecordBinds
+ :: TcType s -- Expected type of whole record
+ -> RenamedRecordBinds
+ -> TcM s (TcRecordBinds s, LIE s)
+
+tcRecordBinds expected_record_ty rbinds
+ = mapAndUnzipTc do_bind rbinds `thenTc` \ (rbinds', lies) ->
+ returnTc (rbinds', plusLIEs lies)
+ where
+ do_bind (field_label, rhs, pun_flag)
+ = tcLookupGlobalValue field_label `thenNF_Tc` \ sel_id ->
+ tcInstId sel_id `thenNF_Tc` \ (_, _, tau) ->
+
+ -- Record selectors all have type
+ -- forall a1..an. T a1 .. an -> tau
+ ASSERT( maybeToBool (getFunTy_maybe tau) )
+ let
+ -- Selector must have type RecordType -> FieldType
+ Just (record_ty, field_ty) = getFunTy_maybe tau
+ in
+ unifyTauTy expected_record_ty record_ty `thenTc_`
+ tcArg field_ty rhs `thenTc` \ (rhs', lie) ->
+ returnTc ((RealId sel_id, rhs', pun_flag), lie)
+
+checkRecordFields :: RenamedRecordBinds -> Id -> Bool -- True iff all the fields in
+ -- RecordBinds are field of the
+ -- specified constructor
+checkRecordFields rbinds data_con
+ = all ok rbinds
+ where
+ data_con_fields = dataConFieldLabels data_con
+
+ ok (field_name, _, _) = any (match (getName field_name)) data_con_fields
+
+ match field_name field_label = field_name == fieldLabelName field_label
\end{code}
%************************************************************************
= ppHang (ppStr "In a do statement:")
4 (ppr sty stmt)
-tooManyArgs f sty
+tooManyArgsCtxt f sty
= ppHang (ppStr "Too many arguments in an application of the function")
4 (ppr sty f)
= ppHang (ppStr "In a polymorphic function argument:")
4 (ppSep [ppBeside (ppr sty arg) (ppStr " ::"),
ppr sty expected_arg_ty])
-\end{code}
+badFieldsUpd rbinds sty
+ = ppHang (ppStr "No constructor has all these fields:")
+ 4 (interpp'SP sty fields)
+ where
+ fields = [field | (field, _, _) <- rbinds]
+
+recordUpdCtxt sty = ppStr "In a record update construct"
+
+badFieldsCon con rbinds sty
+ = ppHang (ppBesides [ppStr "Inconsistent constructor:", ppr sty con])
+ 4 (ppBesides [ppStr "and fields:", interpp'SP sty fields])
+ where
+ fields = [field | (field, _, _) <- rbinds]
+\end{code}