[commit: ghc] master: Expand type synonyms when Linting a forall (9d600ea)
git at git.haskell.org
git at git.haskell.org
Mon Jun 4 15:54:25 UTC 2018
Repository : ssh://git@git.haskell.org/ghc
On branch : master
Link : http://ghc.haskell.org/trac/ghc/changeset/9d600ea68c283b0d38ac663c3cc48baba6b94f57/ghc
>---------------------------------------------------------------
commit 9d600ea68c283b0d38ac663c3cc48baba6b94f57
Author: Simon Peyton Jones <simonpj at microsoft.com>
Date: Fri Jun 1 16:36:57 2018 +0100
Expand type synonyms when Linting a forall
Trac #14939 showed a type like
type Alg cls ob = ob
f :: forall (cls :: * -> Constraint) (b :: Alg cls *). b
where the kind of the forall looks like (Alg cls *), with a
free cls. This tripped up Core Lint.
I fixed this by making Core Lint a bit more forgiving, expanding
type synonyms if necessary.
I'm worried that this might not be the whole story; notably
typeKind looks suspect. But it certainly fixes this problem.
>---------------------------------------------------------------
9d600ea68c283b0d38ac663c3cc48baba6b94f57
compiler/coreSyn/CoreLint.hs | 37 ++++++++++++++++++++++++++++++-------
compiler/types/Type.hs | 4 +++-
testsuite/tests/polykinds/T14939.hs | 19 +++++++++++++++++++
testsuite/tests/polykinds/all.T | 1 +
4 files changed, 53 insertions(+), 8 deletions(-)
diff --git a/compiler/coreSyn/CoreLint.hs b/compiler/coreSyn/CoreLint.hs
index d92082c..517b1be 100644
--- a/compiler/coreSyn/CoreLint.hs
+++ b/compiler/coreSyn/CoreLint.hs
@@ -1296,7 +1296,8 @@ lintInTy ty
= addLoc (InType ty) $
do { ty' <- applySubstTy ty
; k <- lintType ty'
- ; lintKind k
+ -- No need to lint k, because lintType
+ -- guarantees that k is linted
; return (ty', k) }
checkTyCon :: TyCon -> LintM ()
@@ -1355,12 +1356,19 @@ lintType ty@(FunTy t1 t2)
lintType t@(ForAllTy (TvBndr tv _vis) ty)
= do { lintL (isTyVar tv) (text "Covar bound in type:" <+> ppr t)
; lintTyBndr tv $ \tv' ->
- do { k <- lintType ty
- ; lintL (not (tv' `elemVarSet` tyCoVarsOfType k))
- (text "Variable escape in forall:" <+> ppr t)
- ; lintL (classifiesTypeWithValues k)
- (text "Non-* and non-# kind in forall:" <+> ppr t)
- ; return k }}
+ do { k <- lintType ty
+ ; lintL (classifiesTypeWithValues k)
+ (text "Non-* and non-# kind in forall:" <+> ppr t)
+ ; if (not (tv' `elemVarSet` tyCoVarsOfType k))
+ then return k
+ else
+ do { -- See Note [Stupid type synonyms]
+ let k' = expandTypeSynonyms k
+ ; lintL (not (tv' `elemVarSet` tyCoVarsOfType k'))
+ (hang (text "Variable escape in forall:")
+ 2 (vcat [ text "type:" <+> ppr t
+ , text "kind:" <+> ppr k' ]))
+ ; return k' }}}
lintType ty@(LitTy l) = lintTyLit l >> return (typeKind ty)
@@ -1374,6 +1382,21 @@ lintType (CoercionTy co)
= do { (k1, k2, ty1, ty2, r) <- lintCoercion co
; return $ mkHeteroCoercionType r k1 k2 ty1 ty2 }
+{- Note [Stupid type synonyms]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Consider (Trac #14939)
+ type Alg cls ob = ob
+ f :: forall (cls :: * -> Constraint) (b :: Alg cls *). b
+
+Here 'cls' appears free in b's kind, which would usually be illegal
+(becuase in (forall a. ty), ty's kind should not mention 'a'). But
+#in this case (Alg cls *) = *, so all is well. Currently we allow
+this, and make Lint expand synonyms where necessary to make it so.
+
+c.f. TcUnify.occCheckExpand and CoreUtils.coreAltsType which deal
+with the same problem. A single systematic solution eludes me.
+-}
+
-----------------
lintTySynApp :: Bool -> Type -> TyCon -> [Type] -> LintM LintedKind
-- See Note [Linting type synonym applications]
diff --git a/compiler/types/Type.hs b/compiler/types/Type.hs
index 1e0ce99..9963208 100644
--- a/compiler/types/Type.hs
+++ b/compiler/types/Type.hs
@@ -2311,10 +2311,12 @@ typeKind (TyConApp tc tys) = piResultTys (tyConKind tc) tys
typeKind (AppTy fun arg) = typeKind_apps fun [arg]
typeKind (LitTy l) = typeLiteralKind l
typeKind (FunTy {}) = liftedTypeKind
-typeKind (ForAllTy _ ty) = typeKind ty
typeKind (TyVarTy tyvar) = tyVarKind tyvar
typeKind (CastTy _ty co) = pSnd $ coercionKind co
typeKind (CoercionTy co) = coercionType co
+typeKind (ForAllTy _ ty) = typeKind ty -- Urk. See Note [Stupid type synonyms]
+ -- in CoreLint. Maybe we should do
+ -- something similar here...
typeKind_apps :: HasDebugCallStack => Type -> [Type] -> Kind
-- The sole purpose of the function is to accumulate
diff --git a/testsuite/tests/polykinds/T14939.hs b/testsuite/tests/polykinds/T14939.hs
new file mode 100644
index 0000000..eb3c700
--- /dev/null
+++ b/testsuite/tests/polykinds/T14939.hs
@@ -0,0 +1,19 @@
+{-# Language RankNTypes, ConstraintKinds, TypeInType, GADTs #-}
+
+module T14939 where
+
+import Data.Kind
+
+type Cat ob = ob -> ob -> Type
+
+type Alg cls ob = ob
+
+newtype Frí (cls::Type -> Constraint) :: (Type -> Alg cls Type) where
+ Frí :: { with :: forall x. cls x => (a -> x) -> x }
+ -> Frí cls a
+
+data AlgCat (cls::Type -> Constraint) :: Cat (Alg cls Type) where
+ AlgCat :: (cls a, cls b) => (a -> b) -> AlgCat cls a b
+
+leftAdj :: AlgCat cls (Frí cls a) b -> (a -> b)
+leftAdj (AlgCat f) a = undefined
\ No newline at end of file
diff --git a/testsuite/tests/polykinds/all.T b/testsuite/tests/polykinds/all.T
index 788832d..4fe88b2 100644
--- a/testsuite/tests/polykinds/all.T
+++ b/testsuite/tests/polykinds/all.T
@@ -192,3 +192,4 @@ test('SigTvKinds3', normal, compile_fail, [''])
test('T15116', normal, compile_fail, [''])
test('T15116a', normal, compile_fail, [''])
test('T15170', normal, compile, [''])
+test('T14939', normal, compile, ['-O'])
More information about the ghc-commits
mailing list