X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=ghc%2Fcompiler%2Ftypecheck%2FTcRules.lhs;h=50175334e7bfc8a4e9ad9efc51cfd2545020b025;hb=ac10f8408520a30e8437496d320b8b86afda2e8f;hp=1d9edb8beebcd652c84e8acdc6197fd24d282f4a;hpb=6c872fff42025a842e8500ddbb13fdcca60eaf75;p=ghc-hetmet.git diff --git a/ghc/compiler/typecheck/TcRules.lhs b/ghc/compiler/typecheck/TcRules.lhs index 1d9edb8..5017533 100644 --- a/ghc/compiler/typecheck/TcRules.lhs +++ b/ghc/compiler/typecheck/TcRules.lhs @@ -8,70 +8,46 @@ module TcRules ( tcRules ) where #include "HsVersions.h" -import HsSyn ( HsDecl(..), RuleDecl(..), RuleBndr(..), HsTyVar(..) ) -import HsCore ( UfRuleBody(..) ) -import RnHsSyn ( RenamedHsDecl ) -import TcHsSyn ( TypecheckedRuleDecl, mkHsLet ) -import TcMonad -import TcSimplify ( tcSimplifyToDicts, tcSimplifyAndCheck ) -import TcType ( zonkTcTypes, newTyVarTy_OpenKind ) -import TcIfaceSig ( tcCoreExpr, tcCoreLamBndrs, tcVar ) -import TcMonoType ( tcHsSigType, tcHsTyVar, checkSigTyVars ) -import TcExpr ( tcExpr ) -import TcEnv ( tcExtendLocalValEnv, newLocalId, - tcExtendTyVarEnv - ) -import Inst ( LIE, emptyLIE, plusLIEs, instToId ) -import Id ( idType, idName, mkVanillaId ) -import VarSet -import Type ( tyVarsOfTypes ) -import Bag ( bagToList ) +import HsSyn ( RuleDecl(..), LRuleDecl, RuleBndr(..), mkHsDictLet ) +import TcRnMonad +import TcSimplify ( tcSimplifyToDicts, tcSimplifyInferCheck ) +import TcMType ( newFlexiTyVarTy, zonkQuantifiedTyVar, tcSkolSigTyVars ) +import TcType ( tyVarsOfTypes, openTypeKind, SkolemInfo(..), substTyWith, mkTyVarTys ) +import TcHsType ( UserTypeCtxt(..), tcHsPatSigType ) +import TcExpr ( tcMonoExpr ) +import TcEnv ( tcExtendIdEnv, tcExtendTyVarEnv ) +import Inst ( instToId ) +import Id ( idType, mkLocalId ) +import Name ( Name ) +import SrcLoc ( noLoc, unLoc ) import Outputable -import Util \end{code} \begin{code} -tcRules :: [RenamedHsDecl] -> TcM s (LIE, [TypecheckedRuleDecl]) -tcRules decls = mapAndUnzipTc tcRule [rule | RuleD rule <- decls] `thenTc` \ (lies, rules) -> - returnTc (plusLIEs lies, rules) - -tcRule (IfaceRuleDecl fun (UfRuleBody name vars args rhs) src_loc) - = tcAddSrcLoc src_loc $ - tcAddErrCtxt (ruleCtxt name) $ - tcVar fun `thenTc` \ fun' -> - tcCoreLamBndrs vars $ \ vars' -> - mapTc tcCoreExpr args `thenTc` \ args' -> - tcCoreExpr rhs `thenTc` \ rhs' -> - returnTc (emptyLIE, IfaceRuleDecl fun' (CoreRuleBody name vars' args' rhs') src_loc) - -tcRule (RuleDecl name sig_tvs vars lhs rhs src_loc) - = tcAddSrcLoc src_loc $ - tcAddErrCtxt (ruleCtxt name) $ - newTyVarTy_OpenKind `thenNF_Tc` \ rule_ty -> +tcRules :: [LRuleDecl Name] -> TcM [LRuleDecl TcId] +tcRules decls = mappM (wrapLocM tcRule) decls + +tcRule :: RuleDecl Name -> TcM (RuleDecl TcId) +tcRule (HsRule name act vars lhs rhs) + = addErrCtxt (ruleCtxt name) $ + traceTc (ptext SLIT("---- Rule ------") + <+> ppr name) `thenM_` + newFlexiTyVarTy openTypeKind `thenM` \ rule_ty -> -- Deal with the tyvars mentioned in signatures - -- Yuk to the UserTyVar - mapNF_Tc (tcHsTyVar . UserTyVar) sig_tvs `thenNF_Tc` \ sig_tyvars -> - tcExtendTyVarEnv sig_tyvars ( - - -- Ditto forall'd variables - mapNF_Tc new_id vars `thenNF_Tc` \ ids -> - tcExtendLocalValEnv [(idName id, id) | id <- ids] $ - + tcRuleBndrs vars (\ ids -> -- Now LHS and RHS - tcExpr lhs rule_ty `thenTc` \ (lhs', lhs_lie) -> - tcExpr rhs rule_ty `thenTc` \ (rhs', rhs_lie) -> - - returnTc (ids, lhs', rhs', lhs_lie, rhs_lie) - ) `thenTc` \ (ids, lhs', rhs', lhs_lie, rhs_lie) -> + getLIE (tcMonoExpr lhs rule_ty) `thenM` \ (lhs', lhs_lie) -> + getLIE (tcMonoExpr rhs rule_ty) `thenM` \ (rhs', rhs_lie) -> + returnM (ids, lhs', rhs', lhs_lie, rhs_lie) + ) `thenM` \ (ids, lhs', rhs', lhs_lie, rhs_lie) -> -- Check that LHS has no overloading at all - tcSimplifyToDicts lhs_lie `thenTc` \ (lhs_dicts, lhs_binds) -> - checkSigTyVars sig_tyvars `thenTc_` + getLIE (tcSimplifyToDicts lhs_lie) `thenM` \ (lhs_binds, lhs_dicts) -> -- Gather the template variables and tyvars let - tpl_ids = map instToId (bagToList lhs_dicts) ++ ids + tpl_ids = map instToId lhs_dicts ++ ids -- IMPORTANT! We *quantify* over any dicts that appear in the LHS -- Reason: @@ -83,30 +59,58 @@ tcRule (RuleDecl name sig_tvs vars lhs rhs src_loc) -- b) We'd like to make available the dictionaries bound -- on the LHS in the RHS, so quantifying over them is good -- See the 'lhs_dicts' in tcSimplifyAndCheck for the RHS - in - -- Gather type variables to quantify over - zonkTcTypes (rule_ty : map idType tpl_ids) `thenNF_Tc` \ zonked_tys -> - let - tpl_tvs = tyVarsOfTypes zonked_tys + -- We initially quantify over any tyvars free in *either* the rule + -- *or* the bound variables. The latter is important. Consider + -- ss (x,(y,z)) = (x,z) + -- RULE: forall v. fst (ss v) = fst v + -- The type of the rhs of the rule is just a, but v::(a,(b,c)) + -- + -- We also need to get the free tyvars of the LHS; but we do that + -- during zonking (see TcHsSyn.zonkRule) + -- + forall_tvs = tyVarsOfTypes (rule_ty : map idType tpl_ids) in - -- RHS can be a bit more lenient. In particular, -- we let constant dictionaries etc float outwards - tcSimplifyAndCheck (text "tcRule") tpl_tvs - lhs_dicts rhs_lie `thenTc` \ (lie', rhs_binds) -> - - returnTc (lie', RuleDecl name (varSetElems tpl_tvs) - (map RuleBndr tpl_ids) -- yuk - (mkHsLet lhs_binds lhs') - (mkHsLet rhs_binds rhs') - src_loc) + -- + -- NB: tcSimplifyInferCheck zonks the forall_tvs, and + -- knocks out any that are constrained by the environment + tcSimplifyInferCheck (text "tcRule") + forall_tvs + lhs_dicts rhs_lie `thenM` \ (forall_tvs1, rhs_binds) -> + mappM zonkQuantifiedTyVar forall_tvs1 `thenM` \ forall_tvs2 -> + -- This zonk is exactly the same as the one in TcBinds.tcBindWithSigs + + returnM (HsRule name act + (map (RuleBndr . noLoc) (forall_tvs2 ++ tpl_ids)) -- yuk + (mkHsDictLet lhs_binds lhs') + (mkHsDictLet rhs_binds rhs')) where - new_id (RuleBndr var) = newTyVarTy_OpenKind `thenNF_Tc` \ ty -> - returnNF_Tc (mkVanillaId var ty) - new_id (RuleBndrSig var rn_ty) = tcHsSigType rn_ty `thenTc` \ ty -> - returnNF_Tc (mkVanillaId var ty) + +tcRuleBndrs [] thing_inside = thing_inside [] +tcRuleBndrs (RuleBndr var : vars) thing_inside + = do { ty <- newFlexiTyVarTy openTypeKind + ; let id = mkLocalId (unLoc var) ty + ; tcExtendIdEnv [id] $ + tcRuleBndrs vars (\ids -> thing_inside (id:ids)) } +tcRuleBndrs (RuleBndrSig var rn_ty : vars) thing_inside +-- e.g x :: a->a +-- The tyvar 'a' is brought into scope first, just as if you'd written +-- a::*, x :: a->a + = do { let ctxt = RuleSigCtxt (unLoc var) + ; (tyvars, ty) <- tcHsPatSigType ctxt rn_ty + ; let skol_tvs = tcSkolSigTyVars (SigSkol ctxt) tyvars + id_ty = substTyWith tyvars (mkTyVarTys skol_tvs) ty + id = mkLocalId (unLoc var) id_ty + ; tcExtendTyVarEnv skol_tvs $ + tcExtendIdEnv [id] $ + tcRuleBndrs vars (\ids -> thing_inside (id:ids)) } ruleCtxt name = ptext SLIT("When checking the transformation rule") <+> - doubleQuotes (ptext name) + doubleQuotes (ftext name) \end{code} + + + +