diff options
author | Vladislav Zavialov <vlad.z.4096@gmail.com> | 2018-06-14 15:02:36 -0400 |
---|---|---|
committer | Richard Eisenberg <rae@cs.brynmawr.edu> | 2018-06-14 15:05:32 -0400 |
commit | d650729f9a0f3b6aa5e6ef2d5fba337f6f70fa60 (patch) | |
tree | ac224609397d4b7ca7072fc87739d2522be7675b /compiler/rename | |
parent | 4672e2ebf040feffde4e7e2d79c479e4c0c3efaf (diff) | |
download | haskell-d650729f9a0f3b6aa5e6ef2d5fba337f6f70fa60.tar.gz |
Embrace -XTypeInType, add -XStarIsType
Summary:
Implement the "Embrace Type :: Type" GHC proposal,
.../ghc-proposals/blob/master/proposals/0020-no-type-in-type.rst
GHC 8.0 included a major change to GHC's type system: the Type :: Type
axiom. Though casual users were protected from this by hiding its
features behind the -XTypeInType extension, all programs written in GHC
8+ have the axiom behind the scenes. In order to preserve backward
compatibility, various legacy features were left unchanged. For example,
with -XDataKinds but not -XTypeInType, GADTs could not be used in types.
Now these restrictions are lifted and -XTypeInType becomes a redundant
flag that will be eventually deprecated.
* Incorporate the features currently in -XTypeInType into the
-XPolyKinds and -XDataKinds extensions.
* Introduce a new extension -XStarIsType to control how to parse * in
code and whether to print it in error messages.
Test Plan: Validate
Reviewers: goldfire, hvr, bgamari, alanz, simonpj
Reviewed By: goldfire, simonpj
Subscribers: rwbarton, thomie, mpickering, carter
GHC Trac Issues: #15195
Differential Revision: https://phabricator.haskell.org/D4748
Diffstat (limited to 'compiler/rename')
-rw-r--r-- | compiler/rename/RnEnv.hs | 43 | ||||
-rw-r--r-- | compiler/rename/RnSource.hs | 4 | ||||
-rw-r--r-- | compiler/rename/RnTypes.hs | 186 |
3 files changed, 38 insertions, 195 deletions
diff --git a/compiler/rename/RnEnv.hs b/compiler/rename/RnEnv.hs index 6d940299e4..3c0d8f5327 100644 --- a/compiler/rename/RnEnv.hs +++ b/compiler/rename/RnEnv.hs @@ -13,7 +13,7 @@ module RnEnv ( lookupLocatedOccRn, lookupOccRn, lookupOccRn_maybe, lookupLocalOccRn_maybe, lookupInfoOccRn, lookupLocalOccThLvl_maybe, lookupLocalOccRn, - lookupTypeOccRn, lookupKindOccRn, + lookupTypeOccRn, lookupGlobalOccRn, lookupGlobalOccRn_maybe, lookupOccRn_overloaded, lookupGlobalOccRn_overloaded, lookupExactOcc, @@ -824,20 +824,6 @@ lookupLocalOccRn rdr_name Just name -> return name Nothing -> unboundName WL_LocalOnly rdr_name } -lookupKindOccRn :: RdrName -> RnM Name --- Looking up a name occurring in a kind -lookupKindOccRn rdr_name - | isVarOcc (rdrNameOcc rdr_name) -- See Note [Promoted variables in types] - = badVarInType rdr_name - | otherwise - = do { typeintype <- xoptM LangExt.TypeInType - ; if | typeintype -> lookupTypeOccRn rdr_name - -- With -XNoTypeInType, treat any usage of * in kinds as in scope - -- this is a dirty hack, but then again so was the old * kind. - | isStar rdr_name -> return starKindTyConName - | isUniStar rdr_name -> return unicodeStarKindTyConName - | otherwise -> lookupOccRn rdr_name } - -- lookupPromotedOccRn looks up an optionally promoted RdrName. lookupTypeOccRn :: RdrName -> RnM Name -- see Note [Demotion] @@ -846,16 +832,18 @@ lookupTypeOccRn rdr_name = badVarInType rdr_name | otherwise = do { mb_name <- lookupOccRn_maybe rdr_name - ; case mb_name of { - Just name -> return name ; - Nothing -> do { dflags <- getDynFlags - ; lookup_demoted rdr_name dflags } } } + ; case mb_name of + Just name -> return name + Nothing -> lookup_demoted rdr_name } -lookup_demoted :: RdrName -> DynFlags -> RnM Name -lookup_demoted rdr_name dflags +lookup_demoted :: RdrName -> RnM Name +lookup_demoted rdr_name | Just demoted_rdr <- demoteRdrName rdr_name -- Maybe it's the name of a *data* constructor = do { data_kinds <- xoptM LangExt.DataKinds + ; type_operators <- xoptM LangExt.TypeOperators + ; star_is_type <- xoptM LangExt.StarIsType + ; let star_info = starInfo (type_operators, star_is_type) rdr_name ; if data_kinds then do { mb_demoted_name <- lookupOccRn_maybe demoted_rdr ; case mb_demoted_name of @@ -873,7 +861,7 @@ lookup_demoted rdr_name dflags mb_demoted_name <- discardErrs $ lookupOccRn_maybe demoted_rdr ; let suggestion | isJust mb_demoted_name = suggest_dk - | otherwise = star_info + | otherwise = star_info ; unboundNameX WL_Any rdr_name suggestion } } | otherwise @@ -889,17 +877,6 @@ lookup_demoted rdr_name dflags , text "instead of" , quotes (ppr name) <> dot ] - star_info - | isStar rdr_name || isUniStar rdr_name - = if xopt LangExt.TypeInType dflags - then text "NB: With TypeInType, you must import" <+> - ppr rdr_name <+> text "from Data.Kind" - else empty - - | otherwise - = empty - - badVarInType :: RdrName -> RnM Name badVarInType rdr_name = do { addErr (text "Illegal promoted term variable in a type:" diff --git a/compiler/rename/RnSource.hs b/compiler/rename/RnSource.hs index a53adf2cba..50841af818 100644 --- a/compiler/rename/RnSource.hs +++ b/compiler/rename/RnSource.hs @@ -1509,9 +1509,7 @@ rnTyClDecl (DataDecl { tcdLName = tycon, tcdTyVars = tyvars, ; bindHsQTyVars doc Nothing Nothing kvs tyvars $ \ tyvars' no_rhs_kvs -> do { (defn', fvs) <- rnDataDefn doc defn -- See Note [Complete user-supplied kind signatures] in HsDecls - ; typeintype <- xoptM LangExt.TypeInType - ; let cusk = hsTvbAllKinded tyvars' && - (not typeintype || no_rhs_kvs) + ; let cusk = hsTvbAllKinded tyvars' && no_rhs_kvs rn_info = DataDeclRn { tcdDataCusk = cusk , tcdFVs = fvs } ; traceRn "rndata" (ppr tycon <+> ppr cusk <+> ppr no_rhs_kvs) diff --git a/compiler/rename/RnTypes.hs b/compiler/rename/RnTypes.hs index 1f08856142..3d60a9f6c3 100644 --- a/compiler/rename/RnTypes.hs +++ b/compiler/rename/RnTypes.hs @@ -53,7 +53,6 @@ import TcRnMonad import RdrName import PrelNames import TysPrim ( funTyConName ) -import TysWiredIn ( starKindTyConName, unicodeStarKindTyConName ) import Name import SrcLoc import NameSet @@ -341,9 +340,6 @@ rnImplicitBndrs bind_free_tvs ; traceRn "checkMixedVars2" $ vcat [ text "kvs_with_dups" <+> ppr kvs_with_dups , text "tvs_with_dups" <+> ppr tvs_with_dups ] - ; checkMixedVars kvs_with_dups tvs_with_dups - -- E.g. Either (Proxy (a :: k)) k - -- Here 'k' is used at kind level and type level ; bindLocalNamesFV vars $ thing_inside vars } @@ -395,35 +391,6 @@ f :: forall a. a -> (() => b) binds "a" and "b" This situation is now considered to be an error. See rnHsTyKi for case HsForAllTy Qualified. -Note [Dealing with *] -~~~~~~~~~~~~~~~~~~~~~ -As a legacy from the days when types and kinds were different, we use -the type * to mean what we now call GHC.Types.Type. The problem is that -* should associate just like an identifier, *not* a symbol. -Running example: the user has written - - T (Int, Bool) b + c * d - -At this point, we have a bunch of stretches of types - - [[T, (Int, Bool), b], [c], [d]] - -these are the [[LHsType Name]] and a bunch of operators - - [GHC.TypeLits.+, GHC.Types.*] - -Note that the * is GHC.Types.*. So, we want to rearrange to have - - [[T, (Int, Bool), b], [c, *, d]] - -and - - [GHC.TypeLits.+] - -as our lists. We can then do normal fixity resolution on these. The fixities -must come along for the ride just so that the list stays in sync with the -operators. - Note [QualTy in kinds] ~~~~~~~~~~~~~~~~~~~~~~ I was wondering whether QualTy could occur only at TypeLevel. But no, @@ -525,7 +492,7 @@ rnLHsTyKi env (L loc ty) rnHsTyKi :: RnTyKiEnv -> HsType GhcPs -> RnM (HsType GhcRn, FreeVars) rnHsTyKi env ty@(HsForAllTy { hst_bndrs = tyvars, hst_body = tau }) - = do { checkTypeInType env ty + = do { checkPolyKinds env ty ; bindLHsTyVarBndrs (rtke_ctxt env) (Just $ inTypeDoc ty) Nothing tyvars $ \ tyvars' -> do { (tau', fvs) <- rnLHsTyKi env tau @@ -534,7 +501,7 @@ rnHsTyKi env ty@(HsForAllTy { hst_bndrs = tyvars, hst_body = tau }) , fvs) } } rnHsTyKi env ty@(HsQualTy { hst_ctxt = lctxt, hst_body = tau }) - = do { checkTypeInType env ty -- See Note [QualTy in kinds] + = do { checkPolyKinds env ty -- See Note [QualTy in kinds] ; (ctxt', fvs1) <- rnTyKiContext env lctxt ; (tau', fvs2) <- rnLHsTyKi env tau ; return (HsQualTy { hst_xqual = noExt, hst_ctxt = ctxt' @@ -569,6 +536,7 @@ rnHsTyKi env (HsParTy _ ty) rnHsTyKi env (HsBangTy _ b ty) = do { (ty', fvs) <- rnLHsTyKi env ty ; return (HsBangTy noExt b ty', fvs) } + rnHsTyKi env ty@(HsRecTy _ flds) = do { let ctxt = rtke_ctxt env ; fls <- get_fields ctxt @@ -601,7 +569,7 @@ rnHsTyKi env listTy@(HsListTy _ ty) ; return (HsListTy noExt ty', fvs) } rnHsTyKi env t@(HsKindSig _ ty k) - = do { checkTypeInType env t + = do { checkPolyKinds env t ; kind_sigs_ok <- xoptM LangExt.KindSignatures ; unless kind_sigs_ok (badKindSigErr (rtke_ctxt env) ty) ; (ty', fvs1) <- rnLHsTyKi env ty @@ -629,70 +597,13 @@ rnHsTyKi env tyLit@(HsTyLit _ t) = do { data_kinds <- xoptM LangExt.DataKinds ; unless data_kinds (addErr (dataKindsErr env tyLit)) ; when (negLit t) (addErr negLitErr) - ; checkTypeInType env tyLit + ; checkPolyKinds env tyLit ; return (HsTyLit noExt t, emptyFVs) } where negLit (HsStrTy _ _) = False negLit (HsNumTy _ i) = i < 0 negLitErr = text "Illegal literal in type (type literals must not be negative):" <+> ppr tyLit -rnHsTyKi env overall_ty@(HsAppsTy _ tys) - = do { -- Step 1: Break up the HsAppsTy into symbols and non-symbol regions - let (non_syms, syms) = splitHsAppsTy tys - - -- Step 2: rename the pieces - ; (syms1, fvs1) <- mapFvRn (rnHsTyOp env overall_ty) syms - ; (non_syms1, fvs2) <- (mapFvRn . mapFvRn) (rnLHsTyKi env) non_syms - - -- Step 3: deal with *. See Note [Dealing with *] - ; let (non_syms2, syms2) = deal_with_star [] [] non_syms1 syms1 - - -- Step 4: collapse the non-symbol regions with HsAppTy - ; non_syms3 <- mapM deal_with_non_syms non_syms2 - - -- Step 5: assemble the pieces, using mkHsOpTyRn - ; L _ res_ty <- build_res_ty non_syms3 syms2 - - -- all done. Phew. - ; return (res_ty, fvs1 `plusFV` fvs2) } - where - -- See Note [Dealing with *] - deal_with_star :: [[LHsType GhcRn]] -> [Located Name] - -> [[LHsType GhcRn]] -> [Located Name] - -> ([[LHsType GhcRn]], [Located Name]) - deal_with_star acc1 acc2 - (non_syms1 : non_syms2 : non_syms) (L loc star : ops) - | star `hasKey` starKindTyConKey || star `hasKey` unicodeStarKindTyConKey - = deal_with_star acc1 acc2 - ((non_syms1 ++ L loc (HsTyVar noExt NotPromoted (L loc star)) - : non_syms2) : non_syms) - ops - deal_with_star acc1 acc2 (non_syms1 : non_syms) (op1 : ops) - = deal_with_star (non_syms1 : acc1) (op1 : acc2) non_syms ops - deal_with_star acc1 acc2 [non_syms] [] - = (reverse (non_syms : acc1), reverse acc2) - deal_with_star _ _ _ _ - = pprPanic "deal_with_star" (ppr overall_ty) - - -- collapse [LHsType GhcRn] to LHsType GhcRn by making applications - -- monadic only for failure - deal_with_non_syms :: [LHsType GhcRn] -> RnM (LHsType GhcRn) - deal_with_non_syms (non_sym : non_syms) = return $ mkHsAppTys non_sym non_syms - deal_with_non_syms [] = failWith (emptyNonSymsErr overall_ty) - - -- assemble a right-biased OpTy for use in mkHsOpTyRn - build_res_ty :: [LHsType GhcRn] -> [Located Name] -> RnM (LHsType GhcRn) - build_res_ty (arg1 : args) (op1 : ops) - = do { rhs <- build_res_ty args ops - ; fix <- lookupTyFixityRn op1 - ; res <- mkHsOpTyRn (\t1 t2 -> HsOpTy noExt t1 op1 t2) (unLoc op1) - fix arg1 rhs - ; let loc = combineSrcSpans (getLoc arg1) (getLoc rhs) - ; return (L loc res) - } - build_res_ty [arg] [] = return arg - build_res_ty _ _ = pprPanic "build_op_ty" (ppr overall_ty) - rnHsTyKi env (HsAppTy _ ty1 ty2) = do { (ty1', fvs1) <- rnLHsTyKi env ty1 ; (ty2', fvs2) <- rnLHsTyKi env ty2 @@ -704,11 +615,14 @@ rnHsTyKi env t@(HsIParamTy _ n ty) ; return (HsIParamTy noExt n ty', fvs) } rnHsTyKi env t@(HsEqTy _ ty1 ty2) - = do { checkTypeInType env t + = do { checkPolyKinds env t ; (ty1', fvs1) <- rnLHsTyKi env ty1 ; (ty2', fvs2) <- rnLHsTyKi env ty2 ; return (HsEqTy noExt ty1' ty2', fvs1 `plusFV` fvs2) } +rnHsTyKi _ (HsStarTy _ isUni) + = return (HsStarTy noExt isUni, emptyFVs) + rnHsTyKi _ (HsSpliceTy _ sp) = rnSpliceType sp @@ -723,14 +637,14 @@ rnHsTyKi _ (XHsType (NHsCoreTy ty)) -- but I don't think it matters rnHsTyKi env ty@(HsExplicitListTy _ ip tys) - = do { checkTypeInType env ty + = do { checkPolyKinds env ty ; data_kinds <- xoptM LangExt.DataKinds ; unless data_kinds (addErr (dataKindsErr env ty)) ; (tys', fvs) <- mapFvRn (rnLHsTyKi env) tys ; return (HsExplicitListTy noExt ip tys', fvs) } rnHsTyKi env ty@(HsExplicitTupleTy _ tys) - = do { checkTypeInType env ty + = do { checkPolyKinds env ty ; data_kinds <- xoptM LangExt.DataKinds ; unless data_kinds (addErr (dataKindsErr env ty)) ; (tys', fvs) <- mapFvRn (rnLHsTyKi env) tys @@ -747,9 +661,7 @@ rnHsTyKi env (HsWildCardTy _) -------------- rnTyVar :: RnTyKiEnv -> RdrName -> RnM Name rnTyVar env rdr_name - = do { name <- if isRnKindLevel env - then lookupKindOccRn rdr_name - else lookupTypeOccRn rdr_name + = do { name <- lookupTypeOccRn rdr_name ; checkNamedWildCard env name ; return name } @@ -766,10 +678,7 @@ rnHsTyOp :: Outputable a rnHsTyOp env overall_ty (L loc op) = do { ops_ok <- xoptM LangExt.TypeOperators ; op' <- rnTyVar env op - ; unless (ops_ok - || op' == starKindTyConName - || op' == unicodeStarKindTyConName - || op' `hasKey` eqTyConKey) $ + ; unless (ops_ok || op' `hasKey` eqTyConKey) $ addErr (opTyErr op overall_ty) ; let l_op' = L loc op' ; return (l_op', unitFV op') } @@ -844,18 +753,18 @@ rnAnonWildCard ; return (AnonWildCard (L loc name)) } --------------- --- | Ensures either that we're in a type or that -XTypeInType is set -checkTypeInType :: Outputable ty +-- | Ensures either that we're in a type or that -XPolyKinds is set +checkPolyKinds :: Outputable ty => RnTyKiEnv -> ty -- ^ type -> RnM () -checkTypeInType env ty +checkPolyKinds env ty | isRnKindLevel env - = do { type_in_type <- xoptM LangExt.TypeInType - ; unless type_in_type $ + = do { polykinds <- xoptM LangExt.PolyKinds + ; unless polykinds $ addErr (text "Illegal kind:" <+> ppr ty $$ - text "Did you mean to enable TypeInType?") } -checkTypeInType _ _ = return () + text "Did you mean to enable PolyKinds?") } +checkPolyKinds _ _ = return () notInKinds :: Outputable ty => RnTyKiEnv @@ -863,7 +772,7 @@ notInKinds :: Outputable ty -> RnM () notInKinds env ty | isRnKindLevel env - = addErr (text "Illegal kind (even with TypeInType enabled):" <+> ppr ty) + = addErr (text "Illegal kind:" <+> ppr ty) notInKinds _ _ = return () {- ***************************************************** @@ -942,7 +851,6 @@ bindHsQTyVars doc mb_in_doc mb_assoc body_kv_occs hsq_bndrs thing_inside , text "bndr_kv_occs" <+> ppr bndr_kv_occs , text "wubble" <+> ppr ((kv_occs \\ bndrs) \\ bndr_kv_occs) ] - ; checkMixedVars kv_occs bndrs ; implicit_kv_nms <- mapM (newTyVarNameRn mb_assoc) implicit_kvs @@ -1050,20 +958,14 @@ In implementation terms Note [Variables used as both types and kinds] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -In (checkMixedVars kvs tvs), we bind the type variables tvs, and kvs is the -set of free variables of the kinds in the scope of the binding. Here is one -typical example: +We bind the type variables tvs, and kvs is the set of free variables of the +kinds in the scope of the binding. Here is one typical example: forall a b. a -> (b::k) -> (c::a) Here, tvs will be {a,b}, and kvs {k,a}. -Without -XTypeInType we want to complain that `a` is used both -as a type and a kind. - -Specifically, check that there is no overlap between kvs and tvs -See typecheck/should_fail/T11963 for examples. -We must also make sure that kvs includes all of variables in the kinds of type +We must make sure that kvs includes all of variables in the kinds of type variable bindings. For instance: forall k (a :: k). Proxy a @@ -1071,8 +973,7 @@ variable bindings. For instance: If we only look in the body of the `forall` type, we will mistakenly conclude that kvs is {}. But in fact, the type variable `k` is also used as a kind variable in (a :: k), later in the binding. (This mistake lead to #14710.) -So tvs is {k,a} and kvs is {k}, so we must also reject this without the use -of -XTypeInType. +So tvs is {k,a} and kvs is {k}. NB: we do this only at the binding site of 'tvs'. -} @@ -1140,7 +1041,6 @@ collectAnonWildCards lty = go lty where go (L _ ty) = case ty of HsWildCardTy (AnonWildCard (L _ wc)) -> [wc] - HsAppsTy _ tys -> gos (mapMaybe (prefix_types_only . unLoc) tys) HsAppTy _ ty1 ty2 -> go ty1 `mappend` go ty2 HsFunTy _ ty1 ty2 -> go ty1 `mappend` go ty2 HsListTy _ ty -> go ty @@ -1165,14 +1065,11 @@ collectAnonWildCards lty = go lty HsSpliceTy{} -> mempty HsTyLit{} -> mempty HsTyVar{} -> mempty + HsStarTy{} -> mempty XHsType{} -> mempty gos = mconcat . map go - prefix_types_only (HsAppPrefix _ ty) = Just ty - prefix_types_only (HsAppInfix _ _) = Nothing - prefix_types_only (XAppType _) = Nothing - collectAnonWildCardsBndrs :: [LHsTyVarBndr GhcRn] -> [Name] collectAnonWildCardsBndrs ltvs = concatMap (go . unLoc) ltvs where @@ -1587,10 +1484,6 @@ opTyErr op overall_ty | otherwise = text "Use TypeOperators to allow operators in types" -emptyNonSymsErr :: HsType GhcPs -> SDoc -emptyNonSymsErr overall_ty - = text "Operator applied to too few arguments:" <+> ppr overall_ty - {- ************************************************************************ * * @@ -1829,7 +1722,6 @@ extract_lty t_or_k (L _ ty) acc HsRecTy _ flds -> foldrM (extract_lty t_or_k . cd_fld_type . unLoc) acc flds - HsAppsTy _ tys -> extract_apps t_or_k tys acc HsAppTy _ ty1 ty2 -> extract_lty t_or_k ty1 =<< extract_lty t_or_k ty2 acc HsListTy _ ty -> extract_lty t_or_k ty acc @@ -1849,6 +1741,7 @@ extract_lty t_or_k (L _ ty) acc HsExplicitListTy _ _ tys -> extract_ltys t_or_k tys acc HsExplicitTupleTy _ tys -> extract_ltys t_or_k tys acc HsTyLit _ _ -> return acc + HsStarTy _ _ -> return acc HsKindSig _ ty ki -> extract_lty t_or_k ty =<< extract_lkind ki acc HsForAllTy { hst_bndrs = tvs, hst_body = ty } @@ -1861,16 +1754,6 @@ extract_lty t_or_k (L _ ty) acc -- We deal with these separately in rnLHsTypeWithWildCards HsWildCardTy {} -> return acc -extract_apps :: TypeOrKind - -> [LHsAppType GhcPs] -> FreeKiTyVars -> RnM FreeKiTyVars -extract_apps t_or_k tys acc = foldrM (extract_app t_or_k) acc tys - -extract_app :: TypeOrKind -> LHsAppType GhcPs - -> FreeKiTyVarsWithDups -> RnM FreeKiTyVarsWithDups -extract_app t_or_k (L _ (HsAppInfix _ tv)) acc = extract_tv t_or_k tv acc -extract_app t_or_k (L _ (HsAppPrefix _ ty)) acc = extract_lty t_or_k ty acc -extract_app _ (L _ (XAppType _ )) _ = panic "extract_app" - extractHsTvBndrs :: [LHsTyVarBndr GhcPs] -> FreeKiTyVarsWithDups -- Free in body -> RnM FreeKiTyVarsWithDups -- Free in result @@ -1906,7 +1789,6 @@ extract_hs_tv_bndrs tv_bndrs , text "body_kvs" <+> ppr body_kvs , text "all_kv_occs" <+> ppr all_kv_occs , text "tv_bndr_rdrs" <+> ppr tv_bndr_rdrs ] - ; checkMixedVars all_kv_occs tv_bndr_rdrs ; return $ FKTV (filterOut (`elemRdr` tv_bndr_rdrs) all_kv_occs @@ -1940,17 +1822,3 @@ nubL = nubBy eqLocated elemRdr :: Located RdrName -> [Located RdrName] -> Bool elemRdr x = any (eqLocated x) - --- Check for type variables that are also used as kinds without the use of --- -XTypeInType. See Note [Variables used as both types and kinds]. -checkMixedVars :: [Located RdrName] -> [Located RdrName] -> RnM () -checkMixedVars kvs tvs - = do { type_in_type <- xoptM LangExt.TypeInType - ; unless type_in_type $ - mapM_ check kvs } - where - check kv = when (kv `elemRdr` tvs) $ - addErrAt (getLoc kv) $ - vcat [ text "Variable" <+> quotes (ppr kv) - <+> text "used as both a kind and a type" - , text "Did you intend to use TypeInType?" ] |