summaryrefslogtreecommitdiff
path: root/compiler/types/Kind.lhs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/types/Kind.lhs')
-rw-r--r--compiler/types/Kind.lhs218
1 files changed, 94 insertions, 124 deletions
diff --git a/compiler/types/Kind.lhs b/compiler/types/Kind.lhs
index 3fda25c592..b3684151b1 100644
--- a/compiler/types/Kind.lhs
+++ b/compiler/types/Kind.lhs
@@ -36,18 +36,18 @@ module Kind (
-- ** Predicates on Kinds
isLiftedTypeKind, isUnliftedTypeKind, isOpenTypeKind,
isUbxTupleKind, isArgTypeKind, isConstraintKind,
- isConstraintOrLiftedKind, isKind,
- isSuperKind, isSuperKindTyCon, noHashInKind,
+ isConstraintOrLiftedKind, isKind, isKindVar,
+ isSuperKind, isSuperKindTyCon,
isLiftedTypeKindCon, isConstraintKindCon,
isAnyKind, isAnyKindCon,
+ okArrowArgKind, okArrowResultKind,
- isSubArgTypeKind, tcIsSubArgTypeKind,
- isSubOpenTypeKind, tcIsSubOpenTypeKind,
- isSubKind, tcIsSubKind, defaultKind,
- isSubKindCon, tcIsSubKindCon, isSubOpenTypeKindCon,
+ isSubArgTypeKind, isSubOpenTypeKind,
+ isSubKind, isSubKindCon,
+ tcIsSubKind, tcIsSubKindCon,
+ defaultKind,
-- ** Functions on variables
- isKiVar, splitKiTyVars, partitionKiTyVars,
kiVarsOfKind, kiVarsOfKinds
) where
@@ -59,38 +59,9 @@ import {-# SOURCE #-} Type ( typeKind, substKiWith, eqKind )
import TypeRep
import TysPrim
import TyCon
-import Var
import VarSet
import PrelNames
import Outputable
-
-import Data.List ( partition )
-\end{code}
-
-%************************************************************************
-%* *
- Predicates over Kinds
-%* *
-%************************************************************************
-
-\begin{code}
--------------------
--- Lastly we need a few functions on Kinds
-
-isLiftedTypeKindCon :: TyCon -> Bool
-isLiftedTypeKindCon tc = tc `hasKey` liftedTypeKindTyConKey
-
--- This checks that its argument does not contain # or (#).
--- It is used in tcTyVarBndrs.
-noHashInKind :: Kind -> Bool
-noHashInKind (TyVarTy {}) = True
-noHashInKind (FunTy k1 k2) = noHashInKind k1 && noHashInKind k2
-noHashInKind (ForAllTy _ ki) = noHashInKind ki
-noHashInKind (TyConApp kc kis)
- = not (kc `hasKey` unliftedTypeKindTyConKey)
- && not (kc `hasKey` ubxTupleKindTyConKey)
- && all noHashInKind kis
-noHashInKind _ = panic "noHashInKind"
\end{code}
%************************************************************************
@@ -139,37 +110,34 @@ isUbxTupleKind, isOpenTypeKind, isArgTypeKind, isUnliftedTypeKind,
isConstraintKind, isAnyKind, isConstraintOrLiftedKind :: Kind -> Bool
isOpenTypeKindCon, isUbxTupleKindCon, isArgTypeKindCon,
- isUnliftedTypeKindCon, isSubArgTypeKindCon, tcIsSubArgTypeKindCon,
- isSubOpenTypeKindCon, tcIsSubOpenTypeKindCon, isConstraintKindCon,
- isAnyKindCon :: TyCon -> Bool
+ isUnliftedTypeKindCon, isSubArgTypeKindCon,
+ isSubOpenTypeKindCon, isConstraintKindCon,
+ isLiftedTypeKindCon, isAnyKindCon :: TyCon -> Bool
-isAnyKindCon tc = tyConUnique tc == anyKindTyConKey
+
+isLiftedTypeKindCon tc = tyConUnique tc == liftedTypeKindTyConKey
+isAnyKindCon tc = tyConUnique tc == anyKindTyConKey
+isOpenTypeKindCon tc = tyConUnique tc == openTypeKindTyConKey
+isUbxTupleKindCon tc = tyConUnique tc == ubxTupleKindTyConKey
+isArgTypeKindCon tc = tyConUnique tc == argTypeKindTyConKey
+isUnliftedTypeKindCon tc = tyConUnique tc == unliftedTypeKindTyConKey
+isConstraintKindCon tc = tyConUnique tc == constraintKindTyConKey
isAnyKind (TyConApp tc _) = isAnyKindCon tc
isAnyKind _ = False
-isOpenTypeKindCon tc = tyConUnique tc == openTypeKindTyConKey
-
isOpenTypeKind (TyConApp tc _) = isOpenTypeKindCon tc
isOpenTypeKind _ = False
-isUbxTupleKindCon tc = tyConUnique tc == ubxTupleKindTyConKey
-
isUbxTupleKind (TyConApp tc _) = isUbxTupleKindCon tc
isUbxTupleKind _ = False
-isArgTypeKindCon tc = tyConUnique tc == argTypeKindTyConKey
-
isArgTypeKind (TyConApp tc _) = isArgTypeKindCon tc
isArgTypeKind _ = False
-isUnliftedTypeKindCon tc = tyConUnique tc == unliftedTypeKindTyConKey
-
isUnliftedTypeKind (TyConApp tc _) = isUnliftedTypeKindCon tc
isUnliftedTypeKind _ = False
-isConstraintKindCon tc = tyConUnique tc == constraintKindTyConKey
-
isConstraintKind (TyConApp tc _) = isConstraintKindCon tc
isConstraintKind _ = False
@@ -177,106 +145,120 @@ isConstraintOrLiftedKind (TyConApp tc _)
= isConstraintKindCon tc || isLiftedTypeKindCon tc
isConstraintOrLiftedKind _ = False
--- Subkinding
+--------------------------------------------
+-- Kinding for arrow (->)
+-- Says when a kind is acceptable on lhs or rhs of an arrow
+-- arg -> res
+
+okArrowArgKindCon, okArrowResultKindCon :: TyCon -> Bool
+okArrowArgKindCon kc
+ | isLiftedTypeKindCon kc = True
+ | isUnliftedTypeKindCon kc = True
+ | isConstraintKindCon kc = True
+ | otherwise = False
+
+okArrowResultKindCon kc
+ | okArrowArgKindCon kc = True
+ | isUbxTupleKindCon kc = True
+ | otherwise = False
+
+okArrowArgKind, okArrowResultKind :: Kind -> Bool
+okArrowArgKind (TyConApp kc []) = okArrowArgKindCon kc
+okArrowArgKind _ = False
+
+okArrowResultKind (TyConApp kc []) = okArrowResultKindCon kc
+okArrowResultKind _ = False
+
+-----------------------------------------
+-- Subkinding
-- The tc variants are used during type-checking, where we don't want the
-- Constraint kind to be a subkind of anything
-- After type-checking (in core), Constraint is a subkind of argTypeKind
-isSubOpenTypeKind, tcIsSubOpenTypeKind :: Kind -> Bool
+isSubOpenTypeKind :: Kind -> Bool
-- ^ True of any sub-kind of OpenTypeKind
isSubOpenTypeKind (TyConApp kc []) = isSubOpenTypeKindCon kc
isSubOpenTypeKind _ = False
--- ^ True of any sub-kind of OpenTypeKind
-tcIsSubOpenTypeKind (TyConApp kc []) = tcIsSubOpenTypeKindCon kc
-tcIsSubOpenTypeKind _ = False
-
isSubOpenTypeKindCon kc
- | isSubArgTypeKindCon kc = True
- | isUbxTupleKindCon kc = True
- | isOpenTypeKindCon kc = True
- | otherwise = False
-
-tcIsSubOpenTypeKindCon kc
- | tcIsSubArgTypeKindCon kc = True
- | isUbxTupleKindCon kc = True
- | isOpenTypeKindCon kc = True
- | otherwise = False
+ = isSubArgTypeKindCon kc
+ || isUbxTupleKindCon kc
+ || isOpenTypeKindCon kc
+ || isConstraintKindCon kc -- Needed for error (Num a) "blah"
+ -- and so that (Ord a -> Eq a) is well-kinded
isSubArgTypeKindCon kc
- | isUnliftedTypeKindCon kc = True
- | isLiftedTypeKindCon kc = True
- | isArgTypeKindCon kc = True
- | isConstraintKindCon kc = True
- | otherwise = False
+ = isUnliftedTypeKindCon kc
+ || isLiftedTypeKindCon kc
+ || isArgTypeKindCon kc
-tcIsSubArgTypeKindCon kc
- | isConstraintKindCon kc = False
- | otherwise = isSubArgTypeKindCon kc
-
-isSubArgTypeKind, tcIsSubArgTypeKind :: Kind -> Bool
+isSubArgTypeKind :: Kind -> Bool
-- ^ True of any sub-kind of ArgTypeKind
isSubArgTypeKind (TyConApp kc []) = isSubArgTypeKindCon kc
isSubArgTypeKind _ = False
-tcIsSubArgTypeKind (TyConApp kc []) = tcIsSubArgTypeKindCon kc
-tcIsSubArgTypeKind _ = False
-
--- | Is this a super-kind (i.e. a type-of-kinds)?
-isSuperKind :: Type -> Bool
-isSuperKind (TyConApp skc []) = isSuperKindTyCon skc
-isSuperKind _ = False
-
-isSuperKindTyCon :: TyCon -> Bool
-isSuperKindTyCon tc = tc `hasKey` superKindTyConKey
-
-- | Is this a kind (i.e. a type-of-types)?
isKind :: Kind -> Bool
isKind k = isSuperKind (typeKind k)
-isSubKind, tcIsSubKind :: Kind -> Kind -> Bool
-isSubKind = isSubKind' False
-tcIsSubKind = isSubKind' True
-
--- The first argument denotes whether we are in the type-checking phase or not
-isSubKind' :: Bool -> Kind -> Kind -> Bool
+isSubKind :: Kind -> Kind -> Bool
-- ^ @k1 \`isSubKind\` k2@ checks that @k1@ <: @k2@
-isSubKind' duringTc (FunTy a1 r1) (FunTy a2 r2)
- = (isSubKind' duringTc a2 a1) && (isSubKind' duringTc r1 r2)
+isSuperKindTyCon :: TyCon -> Bool
+isSuperKindTyCon tc = tc `hasKey` superKindTyConKey
+
+isSubKind (FunTy a1 r1) (FunTy a2 r2)
+ = (isSubKind a2 a1) && (isSubKind r1 r2)
-isSubKind' duringTc k1@(TyConApp kc1 k1s) k2@(TyConApp kc2 k2s)
+isSubKind k1@(TyConApp kc1 k1s) k2@(TyConApp kc2 k2s)
| isPromotedTypeTyCon kc1 || isPromotedTypeTyCon kc2
-- handles promoted kinds (List *, Nat, etc.)
- = eqKind k1 k2
+ = eqKind k1 k2
| isSuperKindTyCon kc1 || isSuperKindTyCon kc2
-- handles BOX
- = WARN( not (isSuperKindTyCon kc2 && isSuperKindTyCon kc2
- && null k1s && null k2s),
+ = ASSERT2( isSuperKindTyCon kc2 && isSuperKindTyCon kc2
+ && null k1s && null k2s,
ppr kc1 <+> ppr kc2 )
- kc1 == kc2
+ True -- If one is BOX, the other must be too
| otherwise = -- handles usual kinds (*, #, (#), etc.)
ASSERT2( null k1s && null k2s, ppr k1 <+> ppr k2 )
- if duringTc then kc1 `tcIsSubKindCon` kc2
- else kc1 `isSubKindCon` kc2
+ kc1 `isSubKindCon` kc2
-isSubKind' _duringTc k1 k2 = eqKind k1 k2
+isSubKind k1 k2 = eqKind k1 k2
isSubKindCon :: TyCon -> TyCon -> Bool
-- ^ @kc1 \`isSubKindCon\` kc2@ checks that @kc1@ <: @kc2@
isSubKindCon kc1 kc2
- | kc1 == kc2 = True
- | isSubArgTypeKindCon kc1 && isArgTypeKindCon kc2 = True
- | isSubOpenTypeKindCon kc1 && isOpenTypeKindCon kc2 = True
- | otherwise = False
+ | kc1 == kc2 = True
+ | isArgTypeKindCon kc2 = isSubArgTypeKindCon kc1
+ | isOpenTypeKindCon kc2 = isSubOpenTypeKindCon kc1
+ | otherwise = False
+
+-------------------------
+-- Hack alert: we need a tiny variant for the typechecker
+-- Reason: f :: Int -> (a~b)
+-- g :: forall (c::Constraint). Int -> c
+-- We want to reject these, even though Constraint is
+-- a sub-kind of OpenTypeKind. It must be a sub-kind of OpenTypeKind
+-- *after* the typechecker
+-- a) So that (Ord a -> Eq a) is a legal type
+-- b) So that the simplifer can generate (error (Eq a) "urk")
+--
+-- Easiest way to reject is simply to make Constraint not
+-- below OpenTypeKind when type checking
+
+tcIsSubKind :: Kind -> Kind -> Bool
+tcIsSubKind k1 k2
+ | isConstraintKind k1 = isConstraintKind k2
+ | otherwise = isSubKind k1 k2
tcIsSubKindCon :: TyCon -> TyCon -> Bool
tcIsSubKindCon kc1 kc2
- | kc1 == kc2 = True
- | isConstraintKindCon kc1 || isConstraintKindCon kc2 = False
- | otherwise = isSubKindCon kc1 kc2
+ | isConstraintKindCon kc1 = isConstraintKindCon kc2
+ | otherwise = isSubKindCon kc1 kc2
+-------------------------
defaultKind :: Kind -> Kind
-- ^ Used when generalising: default OpenKind and ArgKind to *.
-- See "Type#kind_subtyping" for more information on what that means
@@ -294,20 +276,8 @@ defaultKind :: Kind -> Kind
-- and the calling conventions differ.
-- This defaulting is done in TcMType.zonkTcTyVarBndr.
defaultKind k
- | tcIsSubOpenTypeKind k = liftedTypeKind
- | otherwise = k
-
-splitKiTyVars :: [TyVar] -> ([KindVar], [TyVar])
--- Precondition: kind variables should precede type variables
--- Postcondition: appending the two result lists gives the input!
-splitKiTyVars = span (isSuperKind . tyVarKind)
-
-partitionKiTyVars :: [TyVar] -> ([KindVar], [TyVar])
-partitionKiTyVars = partition (isSuperKind . tyVarKind)
-
--- Checks if this "type or kind" variable is a kind variable
-isKiVar :: TyVar -> Bool
-isKiVar v = isSuperKind (varType v)
+ | isSubOpenTypeKind k = liftedTypeKind
+ | otherwise = k
-- Returns the free kind variables in a kind
kiVarsOfKind :: Kind -> VarSet