module GHC.Tc.Gen.Pat
( tcLetPat
, newLetBndr
, LetBndrSpec(..)
, tcCheckPat, tcCheckPat_O, tcInferPat
, tcPats
, addDataConStupidTheta
, badFieldCon
, polyPatSig
)
where
#include "HsVersions.h"
import GHC.Prelude
import GHC.Tc.Gen.Expr( tcSyntaxOp, tcSyntaxOpGen, tcInferRho )
import GHC.Hs
import GHC.Tc.Utils.Zonk
import GHC.Tc.Gen.Sig( TcPragEnv, lookupPragEnv, addInlinePrags )
import GHC.Tc.Utils.Monad
import GHC.Tc.Utils.Instantiate
import GHC.Types.Id
import GHC.Types.Var
import GHC.Types.Name
import GHC.Types.Name.Reader
import GHC.Core.Multiplicity
import GHC.Tc.Utils.Env
import GHC.Tc.Utils.TcMType
import GHC.Tc.Validity( arityErr )
import GHC.Core.TyCo.Ppr ( pprTyVars )
import GHC.Tc.Utils.TcType
import GHC.Tc.Utils.Unify
import GHC.Tc.Gen.HsType
import GHC.Builtin.Types
import GHC.Tc.Types.Evidence
import GHC.Tc.Types.Origin
import GHC.Core.TyCon
import GHC.Core.DataCon
import GHC.Core.PatSyn
import GHC.Core.ConLike
import GHC.Builtin.Names
import GHC.Types.Basic hiding (SuccessFlag(..))
import GHC.Driver.Session
import GHC.Types.SrcLoc
import GHC.Types.Var.Set
import GHC.Utils.Misc
import GHC.Utils.Outputable as Outputable
import qualified GHC.LanguageExtensions as LangExt
import Control.Arrow ( second )
import Control.Monad ( when )
import GHC.Data.List.SetOps ( getNth )
tcLetPat :: (Name -> Maybe TcId)
-> LetBndrSpec
-> LPat GhcRn -> Scaled ExpSigmaType
-> TcM a
-> TcM (LPat GhcTc, a)
tcLetPat sig_fn no_gen pat pat_ty thing_inside
= do { bind_lvl <- getTcLevel
; let ctxt = LetPat { pc_lvl = bind_lvl
, pc_sig_fn = sig_fn
, pc_new = no_gen }
penv = PE { pe_lazy = True
, pe_ctxt = ctxt
, pe_orig = PatOrigin }
; tc_lpat pat_ty penv pat thing_inside }
tcPats :: HsMatchContext GhcRn
-> [LPat GhcRn]
-> [Scaled ExpSigmaType]
-> TcM a
-> TcM ([LPat GhcTc], a)
tcPats ctxt pats pat_tys thing_inside
= tc_lpats pat_tys penv pats thing_inside
where
penv = PE { pe_lazy = False, pe_ctxt = LamPat ctxt, pe_orig = PatOrigin }
tcInferPat :: HsMatchContext GhcRn -> LPat GhcRn
-> TcM a
-> TcM ((LPat GhcTc, a), TcSigmaType)
tcInferPat ctxt pat thing_inside
= tcInfer $ \ exp_ty ->
tc_lpat (unrestricted exp_ty) penv pat thing_inside
where
penv = PE { pe_lazy = False, pe_ctxt = LamPat ctxt, pe_orig = PatOrigin }
tcCheckPat :: HsMatchContext GhcRn
-> LPat GhcRn -> Scaled TcSigmaType
-> TcM a
-> TcM (LPat GhcTc, a)
tcCheckPat ctxt = tcCheckPat_O ctxt PatOrigin
tcCheckPat_O :: HsMatchContext GhcRn
-> CtOrigin
-> LPat GhcRn -> Scaled TcSigmaType
-> TcM a
-> TcM (LPat GhcTc, a)
tcCheckPat_O ctxt orig pat (Scaled pat_mult pat_ty) thing_inside
= tc_lpat (Scaled pat_mult (mkCheckExpType pat_ty)) penv pat thing_inside
where
penv = PE { pe_lazy = False, pe_ctxt = LamPat ctxt, pe_orig = orig }
data PatEnv
= PE { pe_lazy :: Bool
, pe_ctxt :: PatCtxt
, pe_orig :: CtOrigin
}
data PatCtxt
= LamPat
(HsMatchContext GhcRn)
| LetPat
{ pc_lvl :: TcLevel
, pc_sig_fn :: Name -> Maybe TcId
, pc_new :: LetBndrSpec
}
data LetBndrSpec
= LetLclBndr
| LetGblBndr TcPragEnv
instance Outputable LetBndrSpec where
ppr LetLclBndr = text "LetLclBndr"
ppr (LetGblBndr {}) = text "LetGblBndr"
makeLazy :: PatEnv -> PatEnv
makeLazy penv = penv { pe_lazy = True }
inPatBind :: PatEnv -> Bool
inPatBind (PE { pe_ctxt = LetPat {} }) = True
inPatBind (PE { pe_ctxt = LamPat {} }) = False
tcPatBndr :: PatEnv -> Name -> Scaled ExpSigmaType -> TcM (HsWrapper, TcId)
tcPatBndr penv@(PE { pe_ctxt = LetPat { pc_lvl = bind_lvl
, pc_sig_fn = sig_fn
, pc_new = no_gen } })
bndr_name exp_pat_ty
| Just bndr_id <- sig_fn bndr_name
= do { wrap <- tc_sub_type penv (scaledThing exp_pat_ty) (idType bndr_id)
; traceTc "tcPatBndr(sig)" (ppr bndr_id $$ ppr (idType bndr_id) $$ ppr exp_pat_ty)
; return (wrap, bndr_id) }
| otherwise
= do { (co, bndr_ty) <- case scaledThing exp_pat_ty of
Check pat_ty -> promoteTcType bind_lvl pat_ty
Infer infer_res -> ASSERT( bind_lvl == ir_lvl infer_res )
do { bndr_ty <- inferResultToType infer_res
; return (mkTcNomReflCo bndr_ty, bndr_ty) }
; let bndr_mult = scaledMult exp_pat_ty
; bndr_id <- newLetBndr no_gen bndr_name bndr_mult bndr_ty
; traceTc "tcPatBndr(nosig)" (vcat [ ppr bind_lvl
, ppr exp_pat_ty, ppr bndr_ty, ppr co
, ppr bndr_id ])
; return (mkWpCastN co, bndr_id) }
tcPatBndr _ bndr_name pat_ty
= do { let pat_mult = scaledMult pat_ty
; pat_ty <- expTypeToType (scaledThing pat_ty)
; traceTc "tcPatBndr(not let)" (ppr bndr_name $$ ppr pat_ty)
; return (idHsWrapper, mkLocalIdOrCoVar bndr_name pat_mult pat_ty) }
newLetBndr :: LetBndrSpec -> Name -> Mult -> TcType -> TcM TcId
newLetBndr LetLclBndr name w ty
= do { mono_name <- cloneLocalName name
; return (mkLocalId mono_name w ty) }
newLetBndr (LetGblBndr prags) name w ty
= addInlinePrags (mkLocalId name w ty) (lookupPragEnv prags name)
tc_sub_type :: PatEnv -> ExpSigmaType -> TcSigmaType -> TcM HsWrapper
tc_sub_type penv t1 t2 = tcSubTypePat (pe_orig penv) GenSigCtxt t1 t2
type Checker inp out = forall r.
PatEnv
-> inp
-> TcM r
-> TcM ( out
, r
)
tcMultiple :: Checker inp out -> Checker [inp] [out]
tcMultiple tc_pat penv args thing_inside
= do { err_ctxt <- getErrCtxt
; let loop _ []
= do { res <- thing_inside
; return ([], res) }
loop penv (arg:args)
= do { (p', (ps', res))
<- tc_pat penv arg $
setErrCtxt err_ctxt $
loop penv args
; return (p':ps', res) }
; loop penv args }
tc_lpat :: Scaled ExpSigmaType
-> Checker (LPat GhcRn) (LPat GhcTc)
tc_lpat pat_ty penv (L span pat) thing_inside
= setSrcSpan span $
do { (pat', res) <- maybeWrapPatCtxt pat (tc_pat pat_ty penv pat)
thing_inside
; return (L span pat', res) }
tc_lpats :: [Scaled ExpSigmaType]
-> Checker [LPat GhcRn] [LPat GhcTc]
tc_lpats tys penv pats
= ASSERT2( equalLength pats tys, ppr pats $$ ppr tys )
tcMultiple (\ penv' (p,t) -> tc_lpat t penv' p)
penv
(zipEqual "tc_lpats" pats tys)
checkManyPattern :: Scaled a -> TcM HsWrapper
checkManyPattern pat_ty = tcSubMult NonLinearPatternOrigin Many (scaledMult pat_ty)
tc_pat :: Scaled ExpSigmaType
-> Checker (Pat GhcRn) (Pat GhcTc)
tc_pat pat_ty penv ps_pat thing_inside = case ps_pat of
VarPat x (L l name) -> do
{ (wrap, id) <- tcPatBndr penv name pat_ty
; (res, mult_wrap) <- tcCheckUsage name (scaledMult pat_ty) $
tcExtendIdEnv1 name id thing_inside
; pat_ty <- readExpType (scaledThing pat_ty)
; return (mkHsWrapPat (wrap <.> mult_wrap) (VarPat x (L l id)) pat_ty, res) }
ParPat x pat -> do
{ (pat', res) <- tc_lpat pat_ty penv pat thing_inside
; return (ParPat x pat', res) }
BangPat x pat -> do
{ (pat', res) <- tc_lpat pat_ty penv pat thing_inside
; return (BangPat x pat', res) }
LazyPat x pat -> do
{ mult_wrap <- checkManyPattern pat_ty
; (pat', (res, pat_ct))
<- tc_lpat pat_ty (makeLazy penv) pat $
captureConstraints thing_inside
; emitConstraints pat_ct
; pat_ty <- readExpType (scaledThing pat_ty)
; _ <- unifyType Nothing (tcTypeKind pat_ty) liftedTypeKind
; return (mkHsWrapPat mult_wrap (LazyPat x pat') pat_ty, res) }
WildPat _ -> do
{ mult_wrap <- checkManyPattern pat_ty
; res <- thing_inside
; pat_ty <- expTypeToType (scaledThing pat_ty)
; return (mkHsWrapPat mult_wrap (WildPat pat_ty) pat_ty, res) }
AsPat x (L nm_loc name) pat -> do
{ mult_wrap <- checkManyPattern pat_ty
; (wrap, bndr_id) <- setSrcSpan nm_loc (tcPatBndr penv name pat_ty)
; (pat', res) <- tcExtendIdEnv1 name bndr_id $
tc_lpat (pat_ty `scaledSet`(mkCheckExpType $ idType bndr_id))
penv pat thing_inside
; pat_ty <- readExpType (scaledThing pat_ty)
; return (mkHsWrapPat (wrap <.> mult_wrap) (AsPat x (L nm_loc bndr_id) pat') pat_ty, res) }
ViewPat _ expr pat -> do
{ mult_wrap <- checkManyPattern pat_ty
; (expr',expr_ty) <- tcInferRho expr
; let expr_orig = lexprCtOrigin expr
herald = text "A view pattern expression expects"
; (expr_wrap1, Scaled _mult inf_arg_ty, inf_res_sigma)
<- matchActualFunTySigma herald expr_orig (Just (unLoc expr)) (1,[]) expr_ty
; expr_wrap2 <- tc_sub_type penv (scaledThing pat_ty) inf_arg_ty
; (pat', res) <- tc_lpat (pat_ty `scaledSet` mkCheckExpType inf_res_sigma) penv pat thing_inside
; let Scaled w h_pat_ty = pat_ty
; pat_ty <- readExpType h_pat_ty
; let expr_wrap2' = mkWpFun expr_wrap2 idHsWrapper
(Scaled w pat_ty) inf_res_sigma doc
expr_wrap = expr_wrap2' <.> expr_wrap1 <.> mult_wrap
doc = text "When checking the view pattern function:" <+> (ppr expr)
; return (ViewPat pat_ty (mkLHsWrap expr_wrap expr') pat', res)}
SigPat _ pat sig_ty -> do
{ (inner_ty, tv_binds, wcs, wrap) <- tcPatSig (inPatBind penv)
sig_ty (scaledThing pat_ty)
; (pat', res) <- tcExtendNameTyVarEnv wcs $
tcExtendNameTyVarEnv tv_binds $
tc_lpat (pat_ty `scaledSet` mkCheckExpType inner_ty) penv pat thing_inside
; pat_ty <- readExpType (scaledThing pat_ty)
; return (mkHsWrapPat wrap (SigPat inner_ty pat' sig_ty) pat_ty, res) }
ListPat Nothing pats -> do
{ (coi, elt_ty) <- matchExpectedPatTy matchExpectedListTy penv (scaledThing pat_ty)
; (pats', res) <- tcMultiple (tc_lpat (pat_ty `scaledSet` mkCheckExpType elt_ty))
penv pats thing_inside
; pat_ty <- readExpType (scaledThing pat_ty)
; return (mkHsWrapPat coi
(ListPat (ListPatTc elt_ty Nothing) pats') pat_ty, res)
}
ListPat (Just e) pats -> do
{ tau_pat_ty <- expTypeToType (scaledThing pat_ty)
; ((pats', res, elt_ty), e')
<- tcSyntaxOpGen ListOrigin e [SynType (mkCheckExpType tau_pat_ty)]
SynList $
\ [elt_ty] _ ->
do { (pats', res) <- tcMultiple (tc_lpat (pat_ty `scaledSet` mkCheckExpType elt_ty))
penv pats thing_inside
; return (pats', res, elt_ty) }
; return (ListPat (ListPatTc elt_ty (Just (tau_pat_ty,e'))) pats', res)
}
TuplePat _ pats boxity -> do
{ let arity = length pats
tc = tupleTyCon boxity arity
; (coi, arg_tys) <- matchExpectedPatTy (matchExpectedTyConApp tc)
penv (scaledThing pat_ty)
; let con_arg_tys = case boxity of Unboxed -> drop arity arg_tys
Boxed -> arg_tys
; (pats', res) <- tc_lpats (map (scaledSet pat_ty . mkCheckExpType) con_arg_tys)
penv pats thing_inside
; dflags <- getDynFlags
; let
unmangled_result = TuplePat con_arg_tys pats' boxity
possibly_mangled_result
| gopt Opt_IrrefutableTuples dflags &&
isBoxed boxity = LazyPat noExtField (noLoc unmangled_result)
| otherwise = unmangled_result
; pat_ty <- readExpType (scaledThing pat_ty)
; ASSERT( con_arg_tys `equalLength` pats )
return (mkHsWrapPat coi possibly_mangled_result pat_ty, res)
}
SumPat _ pat alt arity -> do
{ let tc = sumTyCon arity
; (coi, arg_tys) <- matchExpectedPatTy (matchExpectedTyConApp tc)
penv (scaledThing pat_ty)
;
let con_arg_tys = drop arity arg_tys
; (pat', res) <- tc_lpat (pat_ty `scaledSet` mkCheckExpType (con_arg_tys `getNth` (alt 1)))
penv pat thing_inside
; pat_ty <- readExpType (scaledThing pat_ty)
; return (mkHsWrapPat coi (SumPat con_arg_tys pat' alt arity) pat_ty
, res)
}
ConPat NoExtField con arg_pats ->
tcConPat penv con pat_ty arg_pats thing_inside
LitPat x simple_lit -> do
{ let lit_ty = hsLitType simple_lit
; wrap <- tc_sub_type penv (scaledThing pat_ty) lit_ty
; res <- thing_inside
; pat_ty <- readExpType (scaledThing pat_ty)
; return ( mkHsWrapPat wrap (LitPat x (convertLit simple_lit)) pat_ty
, res) }
NPat _ (L l over_lit) mb_neg eq -> do
{ mult_wrap <- checkManyPattern pat_ty
; let orig = LiteralOrigin over_lit
; ((lit', mb_neg'), eq')
<- tcSyntaxOp orig eq [SynType (scaledThing pat_ty), SynAny]
(mkCheckExpType boolTy) $
\ [neg_lit_ty] _ ->
let new_over_lit lit_ty = newOverloadedLit over_lit
(mkCheckExpType lit_ty)
in case mb_neg of
Nothing -> (, Nothing) <$> new_over_lit neg_lit_ty
Just neg ->
second Just <$>
(tcSyntaxOp orig neg [SynRho] (mkCheckExpType neg_lit_ty) $
\ [lit_ty] _ -> new_over_lit lit_ty)
; res <- thing_inside
; pat_ty <- readExpType (scaledThing pat_ty)
; return (mkHsWrapPat mult_wrap (NPat pat_ty (L l lit') mb_neg' eq') pat_ty, res) }
NPlusKPat _ (L nm_loc name)
(L loc lit) _ ge minus -> do
{ mult_wrap <- checkManyPattern pat_ty
; let pat_exp_ty = scaledThing pat_ty
orig = LiteralOrigin lit
; (lit1', ge')
<- tcSyntaxOp orig ge [SynType pat_exp_ty, SynRho]
(mkCheckExpType boolTy) $
\ [lit1_ty] _ ->
newOverloadedLit lit (mkCheckExpType lit1_ty)
; ((lit2', minus_wrap, bndr_id), minus')
<- tcSyntaxOpGen orig minus [SynType pat_exp_ty, SynRho] SynAny $
\ [lit2_ty, var_ty] _ ->
do { lit2' <- newOverloadedLit lit (mkCheckExpType lit2_ty)
; (wrap, bndr_id) <- setSrcSpan nm_loc $
tcPatBndr penv name (unrestricted $ mkCheckExpType var_ty)
; return (lit2', wrap, bndr_id) }
; pat_ty <- readExpType pat_exp_ty
; unlessM (xoptM LangExt.RebindableSyntax) $
do { icls <- tcLookupClass integralClassName
; instStupidTheta orig [mkClassPred icls [pat_ty]] }
; res <- tcExtendIdEnv1 name bndr_id thing_inside
; let minus'' = case minus' of
NoSyntaxExprTc -> pprPanic "tc_pat NoSyntaxExprTc" (ppr minus')
SyntaxExprTc { syn_expr = minus'_expr
, syn_arg_wraps = minus'_arg_wraps
, syn_res_wrap = minus'_res_wrap }
-> SyntaxExprTc { syn_expr = minus'_expr
, syn_arg_wraps = minus'_arg_wraps
, syn_res_wrap = minus_wrap <.> minus'_res_wrap }
pat' = NPlusKPat pat_ty (L nm_loc bndr_id) (L loc lit1') lit2'
ge' minus''
; return (mkHsWrapPat mult_wrap pat' pat_ty, res) }
SplicePat _ splice -> case splice of
(HsSpliced _ mod_finalizers (HsSplicedPat pat)) -> do
{ addModFinalizersWithLclEnv mod_finalizers
; tc_pat pat_ty penv pat thing_inside }
_ -> panic "invalid splice in splice pat"
tcPatSig :: Bool
-> HsPatSigType GhcRn
-> ExpSigmaType
-> TcM (TcType,
[(Name,TcTyVar)],
[(Name,TcTyVar)],
HsWrapper)
tcPatSig in_pat_bind sig res_ty
= do { (sig_wcs, sig_tvs, sig_ty) <- tcHsPatSigType PatSigCtxt sig
; if null sig_tvs then do {
wrap <- addErrCtxtM (mk_msg sig_ty) $
tcSubTypePat PatSigOrigin PatSigCtxt res_ty sig_ty
; return (sig_ty, [], sig_wcs, wrap)
} else do
{ when in_pat_bind (addErr (patBindSigErr sig_tvs))
; wrap <- addErrCtxtM (mk_msg sig_ty) $
tcSubTypePat PatSigOrigin PatSigCtxt res_ty sig_ty
; return (sig_ty, sig_tvs, sig_wcs, wrap)
} }
where
mk_msg sig_ty tidy_env
= do { (tidy_env, sig_ty) <- zonkTidyTcType tidy_env sig_ty
; res_ty <- readExpType res_ty
; (tidy_env, res_ty) <- zonkTidyTcType tidy_env res_ty
; let msg = vcat [ hang (text "When checking that the pattern signature:")
4 (ppr sig_ty)
, nest 2 (hang (text "fits the type of its context:")
2 (ppr res_ty)) ]
; return (tidy_env, msg) }
patBindSigErr :: [(Name,TcTyVar)] -> SDoc
patBindSigErr sig_tvs
= hang (text "You cannot bind scoped type variable" <> plural sig_tvs
<+> pprQuotedList (map fst sig_tvs))
2 (text "in a pattern binding signature")
tcConPat :: PatEnv -> Located Name
-> Scaled ExpSigmaType
-> HsConPatDetails GhcRn -> TcM a
-> TcM (Pat GhcTc, a)
tcConPat penv con_lname@(L _ con_name) pat_ty arg_pats thing_inside
= do { con_like <- tcLookupConLike con_name
; case con_like of
RealDataCon data_con -> tcDataConPat penv con_lname data_con
pat_ty arg_pats thing_inside
PatSynCon pat_syn -> tcPatSynPat penv con_lname pat_syn
pat_ty arg_pats thing_inside
}
tcDataConPat :: PatEnv -> Located Name -> DataCon
-> Scaled ExpSigmaType
-> HsConPatDetails GhcRn -> TcM a
-> TcM (Pat GhcTc, a)
tcDataConPat penv (L con_span con_name) data_con pat_ty_scaled
arg_pats thing_inside
= do { let tycon = dataConTyCon data_con
(univ_tvs, ex_tvs, eq_spec, theta, arg_tys, _)
= dataConFullSig data_con
header = L con_span (RealDataCon data_con)
; (wrap, ctxt_res_tys) <- matchExpectedConTy penv tycon pat_ty_scaled
; pat_ty <- readExpType (scaledThing pat_ty_scaled)
; setSrcSpan con_span $ addDataConStupidTheta data_con ctxt_res_tys
; let all_arg_tys = eqSpecPreds eq_spec ++ theta ++ (map scaledThing arg_tys)
; checkExistentials ex_tvs all_arg_tys penv
; tenv <- instTyVarsWith PatOrigin univ_tvs ctxt_res_tys
; (tenv, ex_tvs') <- tcInstSuperSkolTyVarsX tenv ex_tvs
; let
arg_tys' = substScaledTys tenv arg_tys
pat_mult = scaledMult pat_ty_scaled
arg_tys_scaled = map (scaleScaled pat_mult) arg_tys'
; traceTc "tcConPat" (vcat [ ppr con_name
, pprTyVars univ_tvs
, pprTyVars ex_tvs
, ppr eq_spec
, ppr theta
, pprTyVars ex_tvs'
, ppr ctxt_res_tys
, ppr arg_tys'
, ppr arg_pats ])
; if null ex_tvs && null eq_spec && null theta
then do {
(arg_pats', res) <- tcConArgs (RealDataCon data_con) arg_tys_scaled
penv arg_pats thing_inside
; let res_pat = ConPat { pat_con = header
, pat_args = arg_pats'
, pat_con_ext = ConPatTc
{ cpt_tvs = [], cpt_dicts = []
, cpt_binds = emptyTcEvBinds
, cpt_arg_tys = ctxt_res_tys
, cpt_wrap = idHsWrapper
}
}
; return (mkHsWrapPat wrap res_pat pat_ty, res) }
else do
{ let theta' = substTheta tenv (eqSpecPreds eq_spec ++ theta)
no_equalities = null eq_spec && not (any isEqPred theta)
skol_info = PatSkol (RealDataCon data_con) mc
mc = case pe_ctxt penv of
LamPat mc -> mc
LetPat {} -> PatBindRhs
; gadts_on <- xoptM LangExt.GADTs
; families_on <- xoptM LangExt.TypeFamilies
; checkTc (no_equalities || gadts_on || families_on)
(text "A pattern match on a GADT requires the" <+>
text "GADTs or TypeFamilies language extension")
; given <- newEvVars theta'
; (ev_binds, (arg_pats', res))
<- checkConstraints skol_info ex_tvs' given $
tcConArgs (RealDataCon data_con) arg_tys_scaled penv arg_pats thing_inside
; let res_pat = ConPat
{ pat_con = header
, pat_args = arg_pats'
, pat_con_ext = ConPatTc
{ cpt_tvs = ex_tvs'
, cpt_dicts = given
, cpt_binds = ev_binds
, cpt_arg_tys = ctxt_res_tys
, cpt_wrap = idHsWrapper
}
}
; return (mkHsWrapPat wrap res_pat pat_ty, res)
} }
tcPatSynPat :: PatEnv -> Located Name -> PatSyn
-> Scaled ExpSigmaType
-> HsConPatDetails GhcRn -> TcM a
-> TcM (Pat GhcTc, a)
tcPatSynPat penv (L con_span _) pat_syn pat_ty arg_pats thing_inside
= do { let (univ_tvs, req_theta, ex_tvs, prov_theta, arg_tys, ty) = patSynSig pat_syn
; (subst, univ_tvs') <- newMetaTyVars univ_tvs
; let all_arg_tys = ty : prov_theta ++ (map scaledThing arg_tys)
; checkExistentials ex_tvs all_arg_tys penv
; (tenv, ex_tvs') <- tcInstSuperSkolTyVarsX subst ex_tvs
; let ty' = substTy tenv ty
arg_tys' = substScaledTys tenv arg_tys
pat_mult = scaledMult pat_ty
arg_tys_scaled = map (scaleScaled pat_mult) arg_tys'
prov_theta' = substTheta tenv prov_theta
req_theta' = substTheta tenv req_theta
; mult_wrap <- checkManyPattern pat_ty
; wrap <- tc_sub_type penv (scaledThing pat_ty) ty'
; traceTc "tcPatSynPat" (ppr pat_syn $$
ppr pat_ty $$
ppr ty' $$
ppr ex_tvs' $$
ppr prov_theta' $$
ppr req_theta' $$
ppr arg_tys')
; prov_dicts' <- newEvVars prov_theta'
; let skol_info = case pe_ctxt penv of
LamPat mc -> PatSkol (PatSynCon pat_syn) mc
LetPat {} -> UnkSkol
; req_wrap <- instCall PatOrigin (mkTyVarTys univ_tvs') req_theta'
; traceTc "instCall" (ppr req_wrap)
; traceTc "checkConstraints {" Outputable.empty
; (ev_binds, (arg_pats', res))
<- checkConstraints skol_info ex_tvs' prov_dicts' $
tcConArgs (PatSynCon pat_syn) arg_tys_scaled penv arg_pats thing_inside
; traceTc "checkConstraints }" (ppr ev_binds)
; let res_pat = ConPat { pat_con = L con_span $ PatSynCon pat_syn
, pat_args = arg_pats'
, pat_con_ext = ConPatTc
{ cpt_tvs = ex_tvs'
, cpt_dicts = prov_dicts'
, cpt_binds = ev_binds
, cpt_arg_tys = mkTyVarTys univ_tvs'
, cpt_wrap = req_wrap
}
}
; pat_ty <- readExpType (scaledThing pat_ty)
; return (mkHsWrapPat (wrap <.> mult_wrap) res_pat pat_ty, res) }
matchExpectedPatTy :: (TcRhoType -> TcM (TcCoercionN, a))
-> PatEnv -> ExpSigmaType -> TcM (HsWrapper, a)
matchExpectedPatTy inner_match (PE { pe_orig = orig }) pat_ty
= do { pat_ty <- expTypeToType pat_ty
; (wrap, pat_rho) <- topInstantiate orig pat_ty
; (co, res) <- inner_match pat_rho
; traceTc "matchExpectedPatTy" (ppr pat_ty $$ ppr wrap)
; return (mkWpCastN (mkTcSymCo co) <.> wrap, res) }
matchExpectedConTy :: PatEnv
-> TyCon
-> Scaled ExpSigmaType
-> TcM (HsWrapper, [TcSigmaType])
matchExpectedConTy (PE { pe_orig = orig }) data_tc exp_pat_ty
| Just (fam_tc, fam_args, co_tc) <- tyConFamInstSig_maybe data_tc
= do { pat_ty <- expTypeToType (scaledThing exp_pat_ty)
; (wrap, pat_rho) <- topInstantiate orig pat_ty
; (subst, tvs') <- newMetaTyVars (tyConTyVars data_tc)
; traceTc "matchExpectedConTy" (vcat [ppr data_tc,
ppr (tyConTyVars data_tc),
ppr fam_tc, ppr fam_args,
ppr exp_pat_ty,
ppr pat_ty,
ppr pat_rho, ppr wrap])
; co1 <- unifyType Nothing (mkTyConApp fam_tc (substTys subst fam_args)) pat_rho
; let tys' = mkTyVarTys tvs'
co2 = mkTcUnbranchedAxInstCo co_tc tys' []
full_co = mkTcSubCo (mkTcSymCo co1) `mkTcTransCo` co2
; return ( mkWpCastR full_co <.> wrap, tys') }
| otherwise
= do { pat_ty <- expTypeToType (scaledThing exp_pat_ty)
; (wrap, pat_rho) <- topInstantiate orig pat_ty
; (coi, tys) <- matchExpectedTyConApp data_tc pat_rho
; return (mkWpCastN (mkTcSymCo coi) <.> wrap, tys) }
tcConArgs :: ConLike -> [Scaled TcSigmaType]
-> Checker (HsConPatDetails GhcRn) (HsConPatDetails GhcTc)
tcConArgs con_like arg_tys penv con_args thing_inside = case con_args of
PrefixCon arg_pats -> do
{ checkTc (con_arity == no_of_args)
(arityErr (text "constructor") con_like con_arity no_of_args)
; let pats_w_tys = zipEqual "tcConArgs" arg_pats arg_tys
; (arg_pats', res) <- tcMultiple tcConArg penv pats_w_tys
thing_inside
; return (PrefixCon arg_pats', res) }
where
con_arity = conLikeArity con_like
no_of_args = length arg_pats
InfixCon p1 p2 -> do
{ checkTc (con_arity == 2)
(arityErr (text "constructor") con_like con_arity 2)
; let [arg_ty1,arg_ty2] = arg_tys
; ([p1',p2'], res) <- tcMultiple tcConArg penv [(p1,arg_ty1),(p2,arg_ty2)]
thing_inside
; return (InfixCon p1' p2', res) }
where
con_arity = conLikeArity con_like
RecCon (HsRecFields rpats dd) -> do
{ (rpats', res) <- tcMultiple tc_field penv rpats thing_inside
; return (RecCon (HsRecFields rpats' dd), res) }
where
tc_field :: Checker (LHsRecField GhcRn (LPat GhcRn))
(LHsRecField GhcTc (LPat GhcTc))
tc_field penv
(L l (HsRecField (L loc (FieldOcc sel (L lr rdr))) pat pun))
thing_inside
= do { sel' <- tcLookupId sel
; pat_ty <- setSrcSpan loc $ find_field_ty sel
(occNameFS $ rdrNameOcc rdr)
; (pat', res) <- tcConArg penv (pat, pat_ty) thing_inside
; return (L l (HsRecField (L loc (FieldOcc sel' (L lr rdr))) pat'
pun), res) }
find_field_ty :: Name -> FieldLabelString -> TcM (Scaled TcType)
find_field_ty sel lbl
= case [ty | (fl, ty) <- field_tys, flSelector fl == sel ] of
[] -> failWith (badFieldCon con_like lbl)
(pat_ty : extras) -> do
traceTc "find_field" (ppr pat_ty <+> ppr extras)
ASSERT( null extras ) (return pat_ty)
field_tys :: [(FieldLabel, Scaled TcType)]
field_tys = zip (conLikeFieldLabels con_like) arg_tys
tcConArg :: Checker (LPat GhcRn, Scaled TcSigmaType) (LPat GhcTc)
tcConArg penv (arg_pat, Scaled arg_mult arg_ty)
= tc_lpat (Scaled arg_mult (mkCheckExpType arg_ty)) penv arg_pat
addDataConStupidTheta :: DataCon -> [TcType] -> TcM ()
addDataConStupidTheta data_con inst_tys
| null stupid_theta = return ()
| otherwise = instStupidTheta origin inst_theta
where
origin = OccurrenceOf (dataConName data_con)
stupid_theta = dataConStupidTheta data_con
univ_tvs = dataConUnivTyVars data_con
tenv = zipTvSubst univ_tvs (takeList univ_tvs inst_tys)
inst_theta = substTheta tenv stupid_theta
maybeWrapPatCtxt :: Pat GhcRn -> (TcM a -> TcM b) -> TcM a -> TcM b
maybeWrapPatCtxt pat tcm thing_inside
| not (worth_wrapping pat) = tcm thing_inside
| otherwise = addErrCtxt msg $ tcm $ popErrCtxt thing_inside
where
worth_wrapping (VarPat {}) = False
worth_wrapping (ParPat {}) = False
worth_wrapping (AsPat {}) = False
worth_wrapping _ = True
msg = hang (text "In the pattern:") 2 (ppr pat)
checkExistentials :: [TyVar]
-> [Type]
-> PatEnv -> TcM ()
checkExistentials ex_tvs tys _
| all (not . (`elemVarSet` tyCoVarsOfTypes tys)) ex_tvs = return ()
checkExistentials _ _ (PE { pe_ctxt = LetPat {}}) = return ()
checkExistentials _ _ (PE { pe_ctxt = LamPat ProcExpr }) = failWithTc existentialProcPat
checkExistentials _ _ (PE { pe_lazy = True }) = failWithTc existentialLazyPat
checkExistentials _ _ _ = return ()
existentialLazyPat :: SDoc
existentialLazyPat
= hang (text "An existential or GADT data constructor cannot be used")
2 (text "inside a lazy (~) pattern")
existentialProcPat :: SDoc
existentialProcPat
= text "Proc patterns cannot use existential or GADT data constructors"
badFieldCon :: ConLike -> FieldLabelString -> SDoc
badFieldCon con field
= hsep [text "Constructor" <+> quotes (ppr con),
text "does not have field", quotes (ppr field)]
polyPatSig :: TcType -> SDoc
polyPatSig sig_ty
= hang (text "Illegal polymorphic type signature in pattern:")
2 (ppr sig_ty)