summaryrefslogtreecommitdiff
path: root/compiler/typecheck/TcMType.hs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/typecheck/TcMType.hs')
-rw-r--r--compiler/typecheck/TcMType.hs249
1 files changed, 236 insertions, 13 deletions
diff --git a/compiler/typecheck/TcMType.hs b/compiler/typecheck/TcMType.hs
index 0ca27f57d0..1486d656f4 100644
--- a/compiler/typecheck/TcMType.hs
+++ b/compiler/typecheck/TcMType.hs
@@ -37,6 +37,10 @@ module TcMType (
tauifyExpType, inferResultToType,
--------------------------------
+ -- Getting the kind of a type
+ tcEqTypeM, tcTypeKindM, piResultTysM,
+
+ --------------------------------
-- Creating new evidence variables
newEvVar, newEvVars, newDict,
newWanted, newWanteds, newHoleCt, cloneWanted, cloneWC,
@@ -60,18 +64,21 @@ module TcMType (
freshenTyVarBndrs, freshenCoVarBndrsX,
--------------------------------
+ -- Quantification
+ candidateQTyVarsOfType, candidateQTyVarsOfKind,
+ candidateQTyVarsOfTypes, candidateQTyVarsOfKinds,
+ CandidatesQTvs(..), delCandidates, candidateKindVars,
+ skolemiseQuantifiedTyVar, defaultTyVar,
+ quantifyTyVars,
+
+ --------------------------------
-- Zonking and tidying
zonkTidyTcType, zonkTidyTcTypes, zonkTidyOrigin,
tidyEvVar, tidyCt, tidySkolemInfo,
- zonkTcTyVar, zonkTcTyVars,
+ zonkTcTyVar, zonkTcTyVars,
zonkTcTyVarToTyVar, zonkTyVarTyVarPairs,
zonkTyCoVarsAndFV, zonkTcTypeAndFV,
zonkTyCoVarsAndFVList,
- candidateQTyVarsOfType, candidateQTyVarsOfKind,
- candidateQTyVarsOfTypes, candidateQTyVarsOfKinds,
- CandidatesQTvs(..), delCandidates, candidateKindVars,
- skolemiseQuantifiedTyVar, defaultTyVar,
- quantifyTyVars,
zonkTcTyCoVarBndr, zonkTyConBinders,
zonkTcType, zonkTcTypes, zonkCo,
zonkTyCoVarKind,
@@ -128,6 +135,221 @@ import qualified Data.Semigroup as Semi
{-
************************************************************************
* *
+ tcTypeKind
+* *
+************************************************************************
+-}
+
+tcTypeKindM :: HasDebugCallStack => TcType -> TcM TcKind
+tcTypeKindM (TyConApp tc tys) = return (piResultTys (tyConKind tc) tys)
+tcTypeKindM (LitTy l) = return (typeLiteralKind l)
+tcTypeKindM (CastTy _ty co) = return (pSnd $ coercionKind co)
+tcTypeKindM (CoercionTy co) = return (coercionType co)
+
+tcTypeKindM (FunTy arg res)
+ = do { arg_k <- tcTypeKindM arg
+ ; if tcIsConstraintKind arg_k
+ then do { res_k <- tcTypeKindM res
+ ; if tcIsConstraintKind res_k
+ then return constraintKind
+ else return liftedTypeKind }
+ else return liftedTypeKind }
+
+tcTypeKindM (AppTy fun arg)
+ = go fun [arg]
+ where
+ -- Accumulate the type arugments, so we can call piResultTys,
+ -- rather than a succession of calls to piResultTy (which is
+ -- asymptotically costly as the number of arguments increases)
+ go (AppTy fun arg) args = go fun (arg:args)
+ go fun args = do { fun_k <- tcTypeKindM fun
+ ; piResultTysM fun_k args }
+
+tcTypeKindM ty@(ForAllTy {})
+ = do { body_k <- tcTypeKindM body
+ ; if tcIsConstraintKind body_k
+ then return constraintKind
+ else case occCheckExpand tvs body_k of -- We must make sure tv does
+ Just k' -> return k' -- not occur in kind
+ Nothing -> pprPanic "tcTypeKindM"
+ (ppr ty $$ ppr tvs $$ ppr body <+> dcolon <+> ppr body_k) }
+ where
+ (tvs, body) = splitTyVarForAllTys ty
+
+tcTypeKindM (TyVarTy tv)
+ | isMetaTyVar tv
+ = do { maybe_ty <- readMetaTyVar tv
+ ; case maybe_ty of
+ Indirect ty -> tcTypeKindM ty
+ Flexi -> return (tyVarKind tv) }
+ | otherwise
+ = return (tyVarKind tv)
+
+piResultTysM :: HasDebugCallStack => TcType -> [TcType] -> TcM TcType
+piResultTysM ty orig_args = go init_subst ty orig_args
+ where
+ init_subst = mkEmptyTCvSubst $ mkInScopeSet (tyCoVarsOfTypes (ty:orig_args))
+
+ go :: TCvSubst -> TcType -> [TcType] -> TcM TcType
+ go subst ty []
+ = return (substTy subst ty) -- substTy has a fast-path for empty substitutions
+
+ go subst ty all_args@(arg:args)
+ | Just ty' <- tcView ty
+ = go subst ty' all_args
+
+ | FunTy _ res <- ty
+ = go subst res args
+
+ | ForAllTy (Bndr tv _) res <- ty
+ = go (extendTCvSubst subst tv arg) res args
+
+ | TyVarTy tv <- ty
+ , isMetaTyVar tv
+ = do { maybe_ty <- readMetaTyVar tv
+ ; case maybe_ty of
+ Indirect ty -> go subst ty all_args
+ Flexi -> try_subst subst ty all_args }
+
+ | otherwise
+ = try_subst subst ty all_args
+
+ try_subst subst ty args
+ | not (isEmptyTCvSubst subst) -- See Note [Care with kind instantiation]
+ = go init_subst (substTy subst ty) args
+
+ | otherwise
+ = -- We have not run out of arguments, but the function doesn't
+ -- have the right kind to apply to them; so panic.
+ -- Without the explicit isEmptyVarEnv test, an ill-kinded type
+ -- would give an infniite loop, which is very unhelpful
+ -- c.f. Trac #15473
+ pprPanic "piResultTysM" (ppr ty $$ ppr orig_args $$ ppr args)
+
+
+-- | A monadic version of tcEqType
+-- If it returns True, the two types are definitely equal
+-- If not, they might still be equal, after zonking
+-- Reason for this one-sided conservative-ness: tcEqTypeM is used only
+-- for fast-path checks, and we don't want the full glory of RnEnv2,
+-- which requires us to find the free vars to find the in-scope set,
+-- which requires zonking... and is almost never necessary
+tcEqTypeM :: TcType -> TcType -> TcM Bool
+tcEqTypeM t1 t2
+ = do { k1 <- tcTypeKindM t1
+ ; k2 <- tcTypeKindM t2
+ ; tc_eq_type_m k1 k2 `scAndM` tc_eq_type_m t1 t2 }
+
+tc_eq_type_m :: TcType -> TcType -> TcM Bool
+tc_eq_type_m orig_ty1 orig_ty2
+ = go orig_ty1 orig_ty2
+ where
+ go :: TcType -> TcType -> TcM Bool
+ go t1 t2 | Just t1' <- tcView t1 = go t1' t2
+ go t1 t2 | Just t2' <- tcView t2 = go t1 t2'
+
+ go (TyVarTy tv1) t2 = go_tv tv1 t2
+ go t1 (TyVarTy tv2) = go_tv tv2 t1
+
+ go (LitTy lit1) (LitTy lit2)
+ = return (lit1 == lit2)
+
+ go t1@(ForAllTy {}) t2 = return (tcEqTypeNoKindCheck t1 t2)
+ go t1 t2@(ForAllTy {}) = return (tcEqTypeNoKindCheck t1 t2)
+
+ -- Make sure we handle all FunTy cases since falling through to the
+ -- AppTy case means that tcRepSplitAppTy_maybe may see an unzonked
+ -- kind variable, which causes things to blow up.
+ go (FunTy arg1 res1) (FunTy arg2 res2)
+ = go arg1 arg2 `scAndM` go res1 res2
+ go ty (FunTy arg res) = eqFunTy arg res ty
+ go (FunTy arg res) ty = eqFunTy arg res ty
+
+ -- See Note [Equality on AppTys] in Type
+ go (AppTy s1 t1) ty2
+ | Just (s2, t2) <- repSplitAppTy_maybe ty2
+ = go s1 s2 `scAndM` go t1 t2
+ go ty1 (AppTy s2 t2)
+ | Just (s1, t1) <- repSplitAppTy_maybe ty1
+ = go s1 s2 `scAndM` go t1 t2
+
+ go (TyConApp tc1 ts1) (TyConApp tc2 ts2)
+ | tc1 == tc2 = gos ts1 ts2
+ | otherwise = return False
+
+ go (CastTy t1 _) t2 = go t1 t2
+ go t1 (CastTy t2 _) = go t1 t2
+ go (CoercionTy {}) (CoercionTy {}) = return True
+
+ go _ _ = return False
+
+ --------
+ gos [] [] = return True
+ gos (t1:ts1) (t2:ts2) = go t1 t2 `scAndM` gos ts1 ts2
+ gos _ _ = return False
+
+ --------
+ go_tv :: TcTyVar -> TcType -> TcM Bool
+ go_tv tv1 t2
+ | isMetaTyVar tv1
+ = do { mb_t1 <- readMetaTyVar tv1
+ ; case mb_t1 of
+ Indirect t1 -> go t1 t2
+ Flexi -> go_tv1 tv1 t2 }
+ | otherwise
+ = go_tv1 tv1 t2
+
+ --------
+ go_tv1 :: TcTyVar -> TcType -> TcM Bool
+ -- tv1 is not a filled-in meta-tyvar
+ go_tv1 tv1 (TyVarTy tv2)
+ | isMetaTyVar tv2
+ = do { mb_t2 <- readMetaTyVar tv2
+ ; case mb_t2 of
+ Indirect t2 -> go_tv1 tv1 t2
+ Flexi -> go_tv2 tv1 tv2 }
+ | otherwise
+ = go_tv2 tv1 tv2
+
+ go_tv1 _ _ = return False -- TyVar vs non-TyVar
+
+ --------
+ go_tv2 :: TcTyVar -> TcTyVar -> TcM Bool
+ -- Neither is a filled-in meta-tyvar
+ go_tv2 tv1 tv2 = return (tv1 == tv2)
+
+ --------
+ -- @eqFunTy arg res ty@ is True when @ty@ equals @FunTy arg res@. This is
+ -- sometimes hard to know directly because @ty@ might have some casts
+ -- obscuring the FunTy. And 'splitAppTy' is difficult because we can't
+ -- always extract a RuntimeRep (see Note [xyz]) if the kind of the arg or
+ -- res is unzonked/unflattened. Thus this function, which handles this
+ -- corner case.
+ eqFunTy :: Type -> Type -> Type -> TcM Bool
+ -- Last arg is /not/ FunTy
+ eqFunTy arg res ty@(AppTy{}) = get_args ty []
+ where
+ get_args :: Type -> [Type] -> TcM Bool
+ get_args (AppTy f x) args = get_args f (x:args)
+ get_args (CastTy t _) args = get_args t args
+ get_args (TyConApp tc tys) args
+ | tc == funTyCon
+ , [_, _, arg', res'] <- tys ++ args
+ = go arg arg' <&&> go res res'
+ get_args _ _ = return False
+ eqFunTy _ _ _ = return False
+
+scAndM :: TcM Bool -> TcM Bool -> TcM Bool
+-- A short-circuiting 'and' for monadic computations
+-- If the first returns False, it does not do the second at all
+-- (Whereas <&&> does the seecond regardless.)
+scAndM mb1 mb2 = do { b1 <- mb1
+ ; if b1 then mb2
+ else return False }
+
+{-
+************************************************************************
+* *
Kind variables
* *
************************************************************************
@@ -684,7 +906,8 @@ newFskTyVar fam_ty
, mtv_ref = ref
, mtv_tclvl = tclvl }
name = mkMetaTyVarName uniq (fsLit "fsk")
- ; return (mkTcTyVar name (tcTypeKind fam_ty) details) }
+ ; fam_ty_kind <- tcTypeKindM fam_ty
+ ; return (mkTcTyVar name fam_ty_kind details) }
newFmvTyVar :: TcType -> TcM TcTyVar
-- Very like newMetaTyVar, except sets mtv_tclvl to one less
@@ -697,7 +920,8 @@ newFmvTyVar fam_ty
, mtv_ref = ref
, mtv_tclvl = tclvl }
name = mkMetaTyVarName uniq (fsLit "s")
- ; return (mkTcTyVar name (tcTypeKind fam_ty) details) }
+ ; fam_ty_kind <- tcTypeKindM fam_ty
+ ; return (mkTcTyVar name fam_ty_kind details) }
newMetaDetails :: MetaInfo -> TcM TcTyVarDetails
newMetaDetails info
@@ -784,10 +1008,9 @@ writeMetaTyVarRef tyvar ref ty
= do { meta_details <- readMutVar ref;
-- Zonk kinds to allow the error check to work
; zonked_tv_kind <- zonkTcType tv_kind
- ; zonked_ty <- zonkTcType ty
- ; let zonked_ty_kind = tcTypeKind zonked_ty -- Need to zonk even before typeKind;
- -- otherwise, we can panic in piResultTy
- kind_check_ok = tcIsConstraintKind zonked_tv_kind
+ ; ty_kind <- tcTypeKindM ty
+ ; zonked_ty_kind <- zonkTcType ty_kind
+ ; let kind_check_ok = tcIsConstraintKind zonked_tv_kind
|| tcEqKind zonked_ty_kind zonked_tv_kind
-- Hack alert! tcIsConstraintKind: see TcHsType
-- Note [Extra-constraint holes in partial type signatures]
@@ -2199,4 +2422,4 @@ formatLevPolyErr ty
, text "Kind:" <+> pprWithTYPE tidy_ki ])
where
(tidy_env, tidy_ty) = tidyOpenType emptyTidyEnv ty
- tidy_ki = tidyType tidy_env (tcTypeKind ty)
+ tidy_ki = tidyType tidy_env (typeKind ty)