import TcMonad
import TcUnify ( tcSub, tcGen, (<$>),
- unifyTauTy, unifyFunTy, unifyListTy, unifyTupleTy
- )
+ unifyTauTy, unifyFunTy, unifyListTy, unifyPArrTy,
+ unifyTupleTy )
import BasicTypes ( RecFlag(..), isMarkedStrict )
import Inst ( InstOrigin(..),
LIE, mkLIE, emptyLIE, unitLIE, plusLIE, plusLIEs,
newOverloadedLit, newMethod, newIPDict,
- newDicts,
- instToId, tcInstId
+ newDicts, newMethodWithGivenTy,
+ instToId, tcInstCall
)
import TcBinds ( tcBindsAndThen )
import TcEnv ( tcLookupClass, tcLookupGlobalId, tcLookupGlobal_maybe,
import TcMonoType ( tcHsSigType, UserTypeCtxt(..) )
import TcPat ( badFieldCon )
import TcSimplify ( tcSimplifyIPs )
-import TcMType ( tcInstTyVars, newTyVarTy, newTyVarTys, zonkTcType )
-import TcType ( TcType, TcSigmaType, TcPhiType,
- tcSplitFunTys, tcSplitTyConApp,
+import TcMType ( tcInstTyVars, tcInstType, newHoleTyVarTy,
+ newTyVarTy, newTyVarTys, zonkTcType )
+import TcType ( TcType, TcSigmaType, TcPhiType, TyVarDetails(VanillaTv),
+ tcSplitFunTys, tcSplitTyConApp, mkTyVarTys,
isSigmaTy, mkFunTy, mkAppTy, mkTyConTy,
mkTyConApp, mkClassPred, tcFunArgTy,
- tyVarsOfTypes,
+ tyVarsOfTypes, isLinearPred,
liftedTypeKind, openTypeKind, mkArrowKind,
tcSplitSigmaTy, tcTyConAppTyCon,
tidyOpenType
import Name ( Name )
import TyCon ( TyCon, tyConTyVars, isAlgTyCon, tyConDataCons )
import Subst ( mkTopTyVarSubst, substTheta, substTy )
-import VarSet ( elemVarSet )
-import TysWiredIn ( boolTy, mkListTy, listTyCon )
+import VarSet ( emptyVarSet, elemVarSet )
+import TysWiredIn ( boolTy, mkListTy, mkPArrTy, listTyCon, parrTyCon )
import PrelNames ( cCallableClassName,
cReturnableClassName,
enumFromName, enumFromThenName,
enumFromToName, enumFromThenToName,
+ enumFromToPName, enumFromThenToPName,
thenMName, failMName, returnMName, ioTyConName
)
import Outputable
= tcMonoExpr expr expected_ty
| otherwise
- = tcGen expected_ty (tcMonoExpr expr) `thenTc` \ (gen_fn, expr', lie) ->
+ = tcGen expected_ty emptyVarSet (
+ tcMonoExpr expr
+ ) `thenTc` \ (gen_fn, expr', lie) ->
returnTc (gen_fn <$> expr', lie)
\end{code}
\begin{code}
tcMonoExpr in_expr@(ExprWithTySig expr poly_ty) res_ty
= tcHsSigType ExprSigCtxt poly_ty `thenTc` \ sig_tc_ty ->
- tcAddErrCtxt (exprSigCtxt in_expr) $
tcExpr expr sig_tc_ty `thenTc` \ (expr', lie1) ->
- tcSub res_ty sig_tc_ty `thenTc` \ (co_fn, lie2) ->
- returnTc (co_fn <$> expr', lie1 `plusLIE` lie2)
+
+ -- Must instantiate the outer for-alls of sig_tc_ty
+ -- else we risk instantiating a ? res_ty to a forall-type
+ -- which breaks the invariant that tcMonoExpr only returns phi-types
+ tcAddErrCtxt (exprSigCtxt in_expr) $
+ tcInstCall SignatureOrigin sig_tc_ty `thenNF_Tc` \ (inst_fn, lie2, inst_sig_ty) ->
+ tcSub res_ty inst_sig_ty `thenTc` \ (co_fn, lie3) ->
+
+ returnTc (co_fn <$> inst_fn expr', lie1 `plusLIE` lie2 `plusLIE` lie3)
\end{code}
= tcAddErrCtxt (listCtxt expr) $
tcMonoExpr expr elt_ty
+tcMonoExpr in_expr@(ExplicitPArr _ exprs) res_ty -- maybe empty
+ = unifyPArrTy res_ty `thenTc` \ elt_ty ->
+ mapAndUnzipTc (tc_elt elt_ty) exprs `thenTc` \ (exprs', lies) ->
+ returnTc (ExplicitPArr elt_ty exprs', plusLIEs lies)
+ where
+ tc_elt elt_ty expr
+ = tcAddErrCtxt (parrCtxt expr) $
+ tcMonoExpr expr elt_ty
+
tcMonoExpr (ExplicitTuple exprs boxity) res_ty
= unifyTupleTy boxity (length exprs) res_ty `thenTc` \ arg_tys ->
mapAndUnzipTc (\ (expr, arg_ty) -> tcMonoExpr expr arg_ty)
data_cons = tyConDataCons tycon
(con_tyvars, _, _, _, _, _) = dataConSig (head data_cons)
in
- tcInstTyVars con_tyvars `thenNF_Tc` \ (_, result_inst_tys, _) ->
+ tcInstTyVars VanillaTv con_tyvars `thenNF_Tc` \ (_, result_inst_tys, _) ->
-- STEP 2
-- Check that at least one constructor has all the named fields
mk_inst_ty (tyvar, result_inst_ty)
| tyvar `elemVarSet` common_tyvars = returnNF_Tc result_inst_ty -- Same as result type
- | otherwise = newTyVarTy liftedTypeKind -- Fresh type
+ | otherwise = newTyVarTy liftedTypeKind -- Fresh type
in
mapNF_Tc mk_inst_ty (zip con_tyvars result_inst_tys) `thenNF_Tc` \ inst_tys ->
returnTc (ArithSeqOut (HsVar (instToId eft))
(FromThenTo expr1' expr2' expr3'),
lie1 `plusLIE` lie2 `plusLIE` lie3 `plusLIE` unitLIE eft)
+
+tcMonoExpr in_expr@(PArrSeqIn seq@(FromTo expr1 expr2)) res_ty
+ = tcAddErrCtxt (parrSeqCtxt in_expr) $
+ unifyPArrTy res_ty `thenTc` \ elt_ty ->
+ tcMonoExpr expr1 elt_ty `thenTc` \ (expr1',lie1) ->
+ tcMonoExpr expr2 elt_ty `thenTc` \ (expr2',lie2) ->
+ tcLookupGlobalId enumFromToPName `thenNF_Tc` \ sel_id ->
+ newMethod (PArrSeqOrigin seq) sel_id [elt_ty] `thenNF_Tc` \ enum_from_to ->
+
+ returnTc (PArrSeqOut (HsVar (instToId enum_from_to))
+ (FromTo expr1' expr2'),
+ lie1 `plusLIE` lie2 `plusLIE` unitLIE enum_from_to)
+
+tcMonoExpr in_expr@(PArrSeqIn seq@(FromThenTo expr1 expr2 expr3)) res_ty
+ = tcAddErrCtxt (parrSeqCtxt in_expr) $
+ unifyPArrTy res_ty `thenTc` \ elt_ty ->
+ tcMonoExpr expr1 elt_ty `thenTc` \ (expr1',lie1) ->
+ tcMonoExpr expr2 elt_ty `thenTc` \ (expr2',lie2) ->
+ tcMonoExpr expr3 elt_ty `thenTc` \ (expr3',lie3) ->
+ tcLookupGlobalId enumFromThenToPName `thenNF_Tc` \ sel_id ->
+ newMethod (PArrSeqOrigin seq) sel_id [elt_ty] `thenNF_Tc` \ eft ->
+
+ returnTc (PArrSeqOut (HsVar (instToId eft))
+ (FromThenTo expr1' expr2' expr3'),
+ lie1 `plusLIE` lie2 `plusLIE` lie3 `plusLIE` unitLIE eft)
+
+tcMonoExpr (PArrSeqIn _) _
+ = panic "TcExpr.tcMonoExpr: Infinite parallel array!"
+ -- the parser shouldn't have generated it and the renamer shouldn't have
+ -- let it through
\end{code}
%************************************************************************
%* *
%************************************************************************
+tcId instantiates an occurrence of an Id.
+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)}
+
+The -fno-method-sharing flag controls what happens so far as the LIE
+is concerned. The default case is that for an overloaded function we
+generate a "method" Id, and add the Method Inst to the LIE. So you get
+something like
+ f :: Num a => a -> a
+ f = /\a (d:Num a) -> let m = (+) a d in \ (x:a) -> m x x
+If you specify -fno-method-sharing, the dictionary application
+isn't shared, so we get
+ f :: Num a => a -> a
+ f = /\a (d:Num a) (x:a) -> (+) a d x x
+This gets a bit less sharing, but
+ a) it's better for RULEs involving overloaded functions
+ b) perhaps fewer separated lambdas
+
\begin{code}
tcId :: Name -> NF_TcM (TcExpr, LIE, TcType)
tcId name -- Look up the Id and instantiate its type
= tcLookupId name `thenNF_Tc` \ id ->
- tcInstId id
+ loop (OccurrenceOf id) (HsVar id) emptyLIE (idType id)
+ where
+ loop orig (HsVar fun_id) lie fun_ty
+ | want_method_inst fun_ty
+ = tcInstType VanillaTv fun_ty `thenNF_Tc` \ (tyvars, theta, tau) ->
+ newMethodWithGivenTy orig fun_id
+ (mkTyVarTys tyvars) theta tau `thenNF_Tc` \ meth ->
+ loop orig (HsVar (instToId meth))
+ (unitLIE meth `plusLIE` lie) tau
+
+ loop orig fun lie fun_ty
+ | isSigmaTy fun_ty
+ = tcInstCall orig fun_ty `thenNF_Tc` \ (inst_fn, inst_lie, tau) ->
+ loop orig (inst_fn fun) (inst_lie `plusLIE` lie) tau
+
+ | otherwise
+ = returnNF_Tc (fun, lie, fun_ty)
+
+ want_method_inst fun_ty
+ | opt_NoMethodSharing = False
+ | otherwise = case tcSplitSigmaTy fun_ty of
+ (_,[],_) -> False -- Not overloaded
+ (_,theta,_) -> not (any isLinearPred theta)
+ -- This is a slight hack.
+ -- If f :: (%x :: T) => Int -> Int
+ -- Then if we have two separate calls, (f 3, f 4), we cannot
+ -- make a method constraint that then gets shared, thus:
+ -- let m = f %x in (m 3, m 4)
+ -- because that loses the linearity of the constraint.
+ -- The simplest thing to do is never to construct a method constraint
+ -- in the first place that has a linear implicit parameter in it.
\end{code}
Typecheck expression which in most cases will be an Id.
+The expression can return a higher-ranked type, such as
+ (forall a. a->a) -> Int
+so we must create a HoleTyVarTy to pass in as the expected tyvar.
\begin{code}
tcExpr_id :: RenamedHsExpr -> TcM (TcExpr, LIE, TcType)
tcExpr_id (HsVar name) = tcId name
-tcExpr_id expr = newTyVarTy openTypeKind `thenNF_Tc` \ id_ty ->
+tcExpr_id expr = newHoleTyVarTy `thenNF_Tc` \ id_ty ->
tcMonoExpr expr id_ty `thenTc` \ (expr', lie_id) ->
returnTc (expr', lie_id, id_ty)
\end{code}
%************************************************************************
\begin{code}
+-- I don't like this lumping together of do expression and list/array
+-- comprehensions; creating the monad instances is entirely pointless in the
+-- latter case; I'll leave the list case as it is for the moment, but handle
+-- arrays extra (would be better to handle arrays and lists together, though)
+-- -=chak
+--
+tcDoStmts PArrComp stmts src_loc res_ty
+ =
+ ASSERT( not (null stmts) )
+ tcAddSrcLoc src_loc $
+
+ unifyPArrTy res_ty `thenTc` \elt_ty ->
+ let tc_ty = mkTyConTy parrTyCon
+ m_ty = (mkPArrTy, elt_ty)
+ in
+ tcStmts (DoCtxt PArrComp) m_ty stmts `thenTc` \(stmts', stmts_lie) ->
+ returnTc (HsDoOut PArrComp stmts'
+ undefined undefined undefined -- don't touch!
+ res_ty src_loc,
+ stmts_lie)
+
tcDoStmts do_or_lc stmts src_loc res_ty
= -- get the Monad and MonadZero classes
-- create type consisting of a fresh monad tyvar
-- If it's a comprehension we're dealing with,
-- force it to be a list comprehension.
-- (as of Haskell 98, monad comprehensions are no more.)
+ -- Similarily, array comprehensions must involve parallel arrays types
+ -- -=chak
(case do_or_lc of
ListComp -> unifyListTy res_ty `thenTc` \ elt_ty ->
returnNF_Tc (mkTyConTy listTyCon, (mkListTy, elt_ty))
+ PArrComp -> panic "TcExpr.tcDoStmts: How did we get here?!?"
+
_ -> newTyVarTy (mkArrowKind liftedTypeKind liftedTypeKind) `thenNF_Tc` \ m_ty ->
newTyVarTy liftedTypeKind `thenNF_Tc` \ elt_ty ->
unifyTauTy res_ty (mkAppTy m_ty elt_ty) `thenTc_`
arithSeqCtxt expr
= hang (ptext SLIT("In an arithmetic sequence:")) 4 (ppr expr)
+parrSeqCtxt expr
+ = hang (ptext SLIT("In a parallel array sequence:")) 4 (ppr expr)
+
caseCtxt expr
= hang (ptext SLIT("In the case expression:")) 4 (ppr expr)
= hang (ptext SLIT("In the scrutinee of a case expression:")) 4 (ppr expr)
exprSigCtxt expr
- = hang (ptext SLIT("In an expression with a type signature:"))
+ = hang (ptext SLIT("When checking the type signature of the expression:"))
4 (ppr expr)
listCtxt expr
= hang (ptext SLIT("In the list element:")) 4 (ppr expr)
+parrCtxt expr
+ = hang (ptext SLIT("In the parallel array element:")) 4 (ppr expr)
+
predCtxt expr
= hang (ptext SLIT("In the predicate expression:")) 4 (ppr expr)