Repository : ssh://darcs.haskell.org//srv/darcs/ghc On branch : ghc-kinds
http://hackage.haskell.org/trac/ghc/changeset/58b1a1a0f44e3b1fdb7ccc336eaf993e8d2aa081 >--------------------------------------------------------------- commit 58b1a1a0f44e3b1fdb7ccc336eaf993e8d2aa081 Author: Julien Cretin <g...@ia0.eu> Date: Wed Sep 7 17:43:56 2011 +0200 fix double quantification in kind poly data types >--------------------------------------------------------------- compiler/typecheck/TcHsType.lhs | 56 +++++++++++++++++++++++----------- compiler/typecheck/TcTyClsDecls.lhs | 10 ++++-- compiler/types/Unify.lhs | 11 +++---- 3 files changed, 49 insertions(+), 28 deletions(-) diff --git a/compiler/typecheck/TcHsType.lhs b/compiler/typecheck/TcHsType.lhs index a76767a..a543d9c 100644 --- a/compiler/typecheck/TcHsType.lhs +++ b/compiler/typecheck/TcHsType.lhs @@ -20,7 +20,7 @@ module TcHsType ( -- Typechecking kinded types tcHsKindedContext, tcHsKindedType, tcHsBangType, - tcTyVarBndrs, dsHsType, kcHsLPred, dsHsLPred, + tcTyVarBndrs, tcTyVarBndrsKindGen, dsHsType, kcHsLPred, dsHsLPred, tcDataKindSig, ExpKind(..), EkCtxt(..), -- Pattern type signatures @@ -60,6 +60,7 @@ import Outputable import BuildTyCl ( buildPromotedDataTyCon ) import FastString import Control.Monad ( unless, filterM ) +import Data.List ( mapAccumL ) \end{code} @@ -657,7 +658,7 @@ ds_type (HsSpliceTy _ _ kind) ds_type (HsQuasiQuoteTy {}) = panic "ds_type" -- Eliminated by renamer ds_type (HsCoreTy ty) = return ty --- IA0: ds_type (HsLitTy _) = panic "IA0: ds_type" -- IA0: UNDEFINED +-- ds_type (HsLitTy _) = panic "IA0_UNDEFINED: ds_type" ds_type (HsExplicitListTy kind tys) = do kind' <- zonkTcKindToKind kind @@ -783,24 +784,38 @@ tcTyVarBndrs bndrs thing_inside = do zonk (KindedTyVar name _ kind) = do { kind' <- zonkTcKindToKind kind ; return (mkTyVar name kind') } +tcTyVarBndrsKindGen :: [LHsTyVarBndr Name] -> ([KindVar] -> [TyVar] -> TcM r) -> TcM r +tcTyVarBndrsKindGen bndrs thing_inside = do + (kvs, kinds) <- kindGeneralizeKinds $ map (hsTyVarKind.unLoc) bndrs + let tyvars = zipWith mkTyVar (map hsLTyVarName bndrs) kinds + tcExtendTyVarEnv (kvs ++ tyvars) (thing_inside kvs tyvars) + +kindGeneralizeKinds :: [TcKind] -> TcM ([KindVar], [Kind]) +kindGeneralizeKinds kinds = do + kinds' <- mapM zonkTcKind kinds + flexis <- freeFlexisOfTypes kinds' + traceTc "generalizeKind 1" (ppr flexis <+> ppr kinds') + let (_, occs) = mapAccumL tidy_one emptyTidyOccEnv flexis + tidy_one env flexi = tidyOccName env (getOccName (tyVarName flexi)) + kvs <- flip mapM (zip occs flexis) $ \(occ, flexi) -> do + span <- getSrcSpanM + uniq <- newUnique + let name = mkInternalName uniq occ span + kv = mkTcTyVar name (tyVarKind flexi) vanillaSkolemTv + writeMetaTyVar flexi (mkTyVarTy kv) + return kv + let flexiToKind kv = case lookup kv (zip flexis kvs) of + Nothing -> return (mkTyVarTy kv) + Just kv -> return (mkTyVarTy kv) + bodys <- mapM (zonkKind (mkZonkTcTyVar flexiToKind)) kinds' + traceTc "generalizeKind 2" (ppr kvs <+> ppr bodys) + return (kvs, bodys) + kindGeneralizeKind :: TcKind -> TcM ( [KindVar] -- these were flexi kind vars - , Kind ) -- this is the old kind where flexis got zonked + , Kind ) -- this is the old kind where flexis got zonked kindGeneralizeKind kind = do - kind' <- zonkTcKind kind - flexis <- freeFlexisOfType kind' - kvs <- mapM zonkQuantifiedTyVar flexis - body <- zonkKind (mkZonkTcTyVar flexiToKind) kind' - traceTc "IA0_DEBUG generalizeKind" (ppr kvs <+> ppr body) - return (kvs, body) - -flexiToKind :: KindVar -> TcM Kind -flexiToKind kv = do - isFlexi <- isFlexiMetaTyVar kv - if isFlexi - then do - kv' <- zonkQuantifiedTyVar kv - return (mkTyVarTy kv') - else return (mkTyVarTy kv) + (kvs, [kind']) <- kindGeneralizeKinds [kind] + return (kvs, kind') freeFlexisOfType :: Type -> TcM [Var] freeFlexisOfType ty = do @@ -808,6 +823,11 @@ freeFlexisOfType ty = do -- IA0_TODO: remove in scope variables return fs +freeFlexisOfTypes :: [Type] -> TcM [Var] +freeFlexisOfTypes tys = do + fss <- mapM freeFlexisOfType tys + return $ varSetElems $ unionVarSets $ map mkVarSet fss + ----------------------------------- tcDataKindSig :: Maybe Kind -> TcM [TyVar] -- GADT decls can have a (perhaps partial) kind signature diff --git a/compiler/typecheck/TcTyClsDecls.lhs b/compiler/typecheck/TcTyClsDecls.lhs index ab9bb84..ac37e97 100644 --- a/compiler/typecheck/TcTyClsDecls.lhs +++ b/compiler/typecheck/TcTyClsDecls.lhs @@ -614,12 +614,12 @@ tcConDecl :: Bool -- True <=> -XExistentialQuantificaton or -XGADTs tcConDecl existential_ok rep_tycon res_tmpl -- Data types con@(ConDecl {con_name = name, con_qvars = tvs, con_cxt = ctxt , con_details = details, con_res = res_ty }) - = addErrCtxt (dataConCtxt name) $ - tcTyVarBndrs tvs $ \ tvs' -> do + = addErrCtxt (dataConCtxt name) $ + tcTyVarBndrsKindGen tvs $ \ kvs tvs' -> do { ctxt' <- tcHsKindedContext ctxt ; checkTc (existential_ok || conRepresentibleWithH98Syntax con) (badExistential name) - ; (univ_tvs, ex_tvs, eq_preds, res_ty') <- tcResultType res_tmpl tvs' res_ty + ; (univ_tvs, ex_tvs, eq_preds, res_ty') <- tcResultType res_tmpl (kvs ++ tvs') res_ty ; let tc_datacon is_infix field_lbls btys = do { (arg_tys, stricts) <- mapAndUnzipM tcConArg btys @@ -936,10 +936,12 @@ checkValidDataCon tc con tc_kvs = fst $ splitForAllTys (tyConKind tc) res_ty_tmpl = mkFamilyTyConApp tc (mkTyVarTys (tc_kvs ++ tc_tvs)) actual_res_ty = dataConOrigResTy con - ; checkTc (isJust (tcMatchTy (mkVarSet tc_tvs) + ; checkTc (isJust (tcMatchTy (mkVarSet (tc_kvs ++ tc_tvs)) res_ty_tmpl actual_res_ty)) (badDataConTyCon con res_ty_tmpl actual_res_ty) + -- IA0_TODO: we should also check that kind variables + -- are only instantiated with kind variables ; checkValidMonoType (dataConOrigResTy con) -- Disallow MkT :: T (forall a. a->a) -- Reason: it's really the argument of an equality constraint diff --git a/compiler/types/Unify.lhs b/compiler/types/Unify.lhs index 04f5e68..4c37cd2 100644 --- a/compiler/types/Unify.lhs +++ b/compiler/types/Unify.lhs @@ -34,8 +34,6 @@ import ErrUtils import Util import Maybes import FastString - -import Control.Monad (guard) \end{code} @@ -168,7 +166,7 @@ match menv subst (TyVarTy tv1) ty2 | tv1' `elemVarSet` me_tmpls menv = if any (inRnEnvR rn_env) (varSetElems (tyVarsOfType ty2)) then Nothing -- Occurs check - else do { subst1 <- match_kind menv subst tv1 ty2 + else do { subst1 <- match_kind menv subst (tyVarKind tv1) (typeKind ty2) -- Note [Matching kinds] ; return (extendVarEnv subst1 tv1' ty2) } @@ -202,11 +200,12 @@ match _ _ _ _ = Nothing -------------- -match_kind :: MatchEnv -> TvSubstEnv -> TyVar -> Type -> Maybe TvSubstEnv +match_kind :: MatchEnv -> TvSubstEnv -> Kind -> Kind -> Maybe TvSubstEnv -- Match the kind of the template tyvar with the kind of Type -- Note [Matching kinds] -match_kind _ subst tv ty - = guard (typeKind ty `isSubKind` tyVarKind tv) >> return subst +match_kind _ subst k1 k2 + | k2 `isSubKind` k1 = return subst +match_kind menv subst k1 k2 = match menv subst k1 k2 -- Note [Matching kinds] -- ~~~~~~~~~~~~~~~~~~~~~ _______________________________________________ Cvs-ghc mailing list Cvs-ghc@haskell.org http://www.haskell.org/mailman/listinfo/cvs-ghc