+tcMatches :: TcMatchCtxt
+ -> [Expected TcRhoType] -- Expected pattern types
+ -> Expected TcRhoType -- Expected result-type of the Match.
+ -> MatchGroup Name
+ -> TcM (MatchGroup TcId)
+
+data TcMatchCtxt -- c.f. TcStmtCtxt, also in this module
+ = MC { mc_what :: HsMatchContext Name, -- What kind of thing this is
+ mc_body :: LHsExpr Name -- Type checker for a body of an alternative
+ -> Expected TcRhoType
+ -> TcM (LHsExpr TcId) }
+
+tcMatches ctxt pat_tys rhs_ty (MatchGroup matches _)
+ = do { matches' <- mapM (tcMatch ctxt pat_tys rhs_ty) matches
+ ; pat_tys' <- mapM readExpectedType pat_tys
+ ; rhs_ty' <- readExpectedType rhs_ty
+ ; return (MatchGroup matches' (mkFunTys pat_tys' rhs_ty')) }
+
+-------------
+tcMatch :: TcMatchCtxt
+ -> [Expected TcRhoType] -- Expected pattern types
+ -> Expected TcRhoType -- Expected result-type of the Match.
+ -> LMatch Name
+ -> TcM (LMatch TcId)
+
+tcMatch ctxt pat_tys rhs_ty match
+ = wrapLocM (tc_match ctxt pat_tys rhs_ty) match
+
+tc_match ctxt pat_tys rhs_ty match@(Match pats maybe_rhs_sig grhss)
+ = addErrCtxt (matchCtxt (mc_what ctxt) match) $
+ do { (pats', grhss') <- tcMatchPats pats pat_tys rhs_ty $
+ tc_grhss ctxt maybe_rhs_sig grhss rhs_ty
+ ; returnM (Match pats' Nothing grhss') }
+
+
+-------------
+tc_grhss ctxt Nothing grhss rhs_ty
+ = tcGRHSs ctxt grhss rhs_ty -- No result signature
+
+tc_grhss ctxt (Just res_sig) grhss rhs_ty
+ = do { (sig_tvs, sig_ty) <- tcHsPatSigType ResSigCtxt res_sig
+ ; traceTc (text "tc_grhss" <+> ppr sig_tvs)
+ ; (co_fn, grhss') <- tcExtendTyVarEnv sig_tvs $
+ tcThingWithSig sig_ty (tcGRHSs ctxt grhss . Check) rhs_ty
+
+ -- Push the coercion down to the right hand sides,
+ -- because there is no convenient place to hang it otherwise.
+ ; if isIdCoercion co_fn then
+ return grhss'
+ else
+ return (lift_grhss co_fn grhss') }
+
+-------------
+lift_grhss co_fn (GRHSs grhss binds)
+ = GRHSs (map (fmap lift_grhs) grhss) binds
+ where
+ lift_grhs (GRHS stmts) = GRHS (map lift_stmt stmts)
+
+ lift_stmt (L loc (ResultStmt e)) = L loc (ResultStmt (fmap (co_fn <$>) e))
+ lift_stmt stmt = stmt
+
+-------------
+tcGRHSs :: TcMatchCtxt -> GRHSs Name
+ -> Expected TcRhoType
+ -> TcM (GRHSs TcId)
+
+ -- Special case when there is just one equation with a degenerate
+ -- guard; then we pass in the full Expected type, so that we get
+ -- good inference from simple things like
+ -- f = \(x::forall a.a->a) -> <stuff>
+ -- This is a consequence of the fact that tcStmts takes a TcType,
+ -- not a Expected TcType, a decision we could revisit if necessary
+tcGRHSs ctxt (GRHSs [L loc1 (GRHS [L loc2 (ResultStmt rhs)])] binds) exp_ty
+ = tcBindsAndThen glueBindsOnGRHSs binds $
+ mc_body ctxt rhs exp_ty `thenM` \ rhs' ->
+ returnM (GRHSs [L loc1 (GRHS [L loc2 (ResultStmt rhs')])] [])
+
+tcGRHSs ctxt (GRHSs grhss binds) exp_ty
+ = tcBindsAndThen glueBindsOnGRHSs binds $
+ zapExpectedType exp_ty openTypeKind `thenM` \ exp_ty' ->
+ -- Even if there is only one guard, we zap the RHS type to
+ -- a monotype. Reason: it makes tcStmts much easier,
+ -- and even a one-armed guard has a notional second arm
+ let
+ stmt_ctxt = SC { sc_what = PatGuard (mc_what ctxt),
+ sc_rhs = tcInferRho,
+ sc_body = sc_body,
+ sc_ty = exp_ty' }
+ sc_body body = mc_body ctxt body (Check exp_ty')
+
+ tc_grhs (GRHS guarded)
+ = tcStmts stmt_ctxt guarded `thenM` \ guarded' ->
+ returnM (GRHS guarded')
+ in
+ mappM (wrapLocM tc_grhs) grhss `thenM` \ grhss' ->
+ returnM (GRHSs grhss' [])
+\end{code}