[project @ 1996-07-25 20:43:49 by partain]
[ghc-hetmet.git] / ghc / compiler / typecheck / TcExpr.lhs
index f6fc5be..9c59b43 100644 (file)
@@ -8,51 +8,69 @@
 
 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 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 TcType          ( SYN_IE(TcType), TcMaybe(..),
+                         tcInstId, tcInstType, tcInstSigTcType,
+                         tcInstSigType, tcInstTcType, tcInstTheta,
+                         newTyVarTy, zonkTcTyVars, zonkTcType )
+import TcKind          ( TcKind )
+
+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,
-                         getTyVar_maybe, getFunTy_maybe,
-                         splitForAllTy, splitRhoTy, splitSigmaTy,
-                         isTauTy, mkFunTys, tyVarsOfType, getForAllTy_maybe )
-import TyVar           ( GenTyVar, TyVarSet(..), unionTyVarSets, tyVarListToSet )
-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
@@ -71,7 +89,7 @@ tcExpr :: RenamedHsExpr -> TcM s (TcExpr s, LIE s, TcType s)
 
 \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
@@ -153,6 +171,11 @@ tcExpr (HsLit lit@(HsString str))
 %************************************************************************
 
 \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)
@@ -207,7 +230,7 @@ tcExpr in_expr@(SectionR op expr)
     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}
@@ -244,10 +267,11 @@ tcExpr (CCall lbl args may_gc is_asm ignored_fake_result_ty)
 
        -- 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}
@@ -280,7 +304,7 @@ tcExpr (HsIf pred b1 b2 src_loc)
     tcExpr pred                        `thenTc`    \ (pred',lie1,predTy) ->
 
     tcAddErrCtxt (predCtxt pred) (
-      unifyTauTy predTy boolTy
+      unifyTauTy boolTy predTy
     )                          `thenTc_`
 
     tcExpr b1                  `thenTc`    \ (b1',lie2,result_ty) ->
@@ -297,36 +321,8 @@ tcExpr (ListComp expr quals)
 \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}
@@ -345,10 +341,57 @@ tcExpr (ExplicitTuple exprs)
   = 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) ->
@@ -424,15 +467,19 @@ tcExpr in_expr@(ExprWithTySig expr poly_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
-       (tyVarListToSet sig_tyvars')
+       (mkTyVarSet sig_tyvars')
        sig_dicts lie                           `thenTc_`
 
        -- If everything is ok, return the stuff unchanged, except for
@@ -460,7 +507,7 @@ tcApp fun args
        -- 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) ->
 
@@ -484,46 +531,23 @@ tcApp_help :: RenamedHsExpr -> Int        -- Function and arg position, used in error m
 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}
@@ -546,14 +570,19 @@ tcArg expected_arg_ty arg
        -- 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
@@ -565,32 +594,29 @@ tcArg expected_arg_ty arg
        -- 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 (tyVarListToSet 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}
 
@@ -601,39 +627,51 @@ tcArg expected_arg_ty arg
 %************************************************************************
 
 \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       = map mkTyVarTy 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}
 %*                                                                     *
 %************************************************************************
 
@@ -661,6 +699,12 @@ tcListComp expr (qual@(GeneratorQual pat rhs) : quals)
       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) 
@@ -692,63 +736,138 @@ tcListComp expr (LetQual binds : quals)
 %************************************************************************
 
 \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}
 
 %************************************************************************
@@ -820,7 +939,7 @@ stmtCtxt stmt sty
   = 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)
 
@@ -833,5 +952,18 @@ rank2ArgCtxt arg expected_arg_ty sty
   = 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}