[Git][ghc/ghc][wip/T18939] Use tcSplitForAllInvisTyVars (not tcSplitForAllTyVars) in more places
Ryan Scott
gitlab at gitlab.haskell.org
Fri Nov 13 18:40:46 UTC 2020
Ryan Scott pushed to branch wip/T18939 at Glasgow Haskell Compiler / GHC
Commits:
e5dabf55 by Ryan Scott at 2020-11-13T13:40:02-05:00
Use tcSplitForAllInvisTyVars (not tcSplitForAllTyVars) in more places
The use of `tcSplitForAllTyVars` in `tcDataFamInstHeader` was the immediate
cause of #18939, and replacing it with a new `tcSplitForAllInvisTyVars`
function (which behaves like `tcSplitForAllTyVars` but only splits invisible
type variables) fixes the issue. However, this led me to realize that _most_
uses of `tcSplitForAllTyVars` in GHC really ought to be
`tcSplitForAllInvisTyVars` instead. While I was in town, I opted to replace
most uses of `tcSplitForAllTys` with `tcSplitForAllTysInvis` to reduce the
likelihood of such bugs in the future.
I say "most uses" above since there is one notable place where we _do_ want
to use `tcSplitForAllTyVars`: in `GHC.Tc.Validity.forAllTyErr`, which produces
the "`Illegal polymorphic type`" error message if you try to use a higher-rank
`forall` without having `RankNTypes` enabled. Here, we really do want to split
all `forall`s, not just invisible ones, or we run the risk of giving an
inaccurate error message in the newly added `T18939_Fail` test case.
I debated at some length whether I wanted to name the new function
`tcSplitForAllInvisTyVars` or `tcSplitForAllTyVarsInvisible`, but in the end,
I decided that I liked the former better. For consistency's sake, I opted to
rename the existing `splitPiTysInvisible` and `splitPiTysInvisibleN` functions
to `splitInvisPiTys` and `splitPiTysInvisN`, respectively, so that they use the
same naming convention. As a consequence, this ended up requiring a `haddock`
submodule bump.
Fixes #18939.
- - - - -
15 changed files:
- compiler/GHC/Core/Type.hs
- compiler/GHC/HsToCore/Foreign/Decl.hs
- compiler/GHC/Runtime/Heap/Inspect.hs
- compiler/GHC/Tc/Gen/HsType.hs
- compiler/GHC/Tc/TyCl/Instance.hs
- compiler/GHC/Tc/Utils/Backpack.hs
- compiler/GHC/Tc/Utils/Instantiate.hs
- compiler/GHC/Tc/Utils/TcType.hs
- compiler/GHC/Tc/Validity.hs
- + testsuite/tests/typecheck/should_compile/T18939_Compile.hs
- testsuite/tests/typecheck/should_compile/all.T
- + testsuite/tests/typecheck/should_fail/T18939_Fail.hs
- + testsuite/tests/typecheck/should_fail/T18939_Fail.stderr
- testsuite/tests/typecheck/should_fail/all.T
- utils/haddock
Changes:
=====================================
compiler/GHC/Core/Type.hs
=====================================
@@ -76,7 +76,7 @@ module GHC.Core.Type (
coAxNthLHS,
stripCoercionTy,
- splitPiTysInvisible, splitPiTysInvisibleN,
+ splitInvisPiTys, splitInvisPiTysN,
invisibleTyBndrCount,
filterOutInvisibleTypes, filterOutInferredTypes,
partitionInvisibleTypes, partitionInvisibles,
@@ -1559,7 +1559,7 @@ splitForAllTyCoVars ty = split ty ty []
split orig_ty ty tvs | Just ty' <- coreView ty = split orig_ty ty' tvs
split orig_ty _ tvs = (reverse tvs, orig_ty)
--- | Splits the longest initial sequence of ForAllTys' that satisfy
+-- | Splits the longest initial sequence of 'ForAllTy's that satisfy
-- @argf_pred@, returning the binders transformed by @argf_pred@
splitSomeForAllTyCoVarBndrs :: (ArgFlag -> Maybe af) -> Type -> ([VarBndr TyCoVar af], Type)
splitSomeForAllTyCoVarBndrs argf_pred ty = split ty ty []
@@ -1716,12 +1716,12 @@ invisibleTyBndrCount :: Type -> Int
-- Includes invisible predicate arguments; e.g. for
-- e.g. forall {k}. (k ~ *) => k -> k
-- returns 2 not 1
-invisibleTyBndrCount ty = length (fst (splitPiTysInvisible ty))
+invisibleTyBndrCount ty = length (fst (splitInvisPiTys ty))
--- Like splitPiTys, but returns only *invisible* binders, including constraints
--- Stops at the first visible binder
-splitPiTysInvisible :: Type -> ([TyCoBinder], Type)
-splitPiTysInvisible ty = split ty ty []
+-- | Like 'splitPiTys', but returns only *invisible* binders, including constraints.
+-- Stops at the first visible binder.
+splitInvisPiTys :: Type -> ([TyCoBinder], Type)
+splitInvisPiTys ty = split ty ty []
where
split _ (ForAllTy b res) bs
| Bndr _ vis <- b
@@ -1732,11 +1732,11 @@ splitPiTysInvisible ty = split ty ty []
| Just ty' <- coreView ty = split orig_ty ty' bs
split orig_ty _ bs = (reverse bs, orig_ty)
-splitPiTysInvisibleN :: Int -> Type -> ([TyCoBinder], Type)
--- Same as splitPiTysInvisible, but stop when
--- - you have found 'n' TyCoBinders,
+splitInvisPiTysN :: Int -> Type -> ([TyCoBinder], Type)
+-- ^ Same as 'splitInvisPiTys', but stop when
+-- - you have found @n@ 'TyCoBinder's,
-- - or you run out of invisible binders
-splitPiTysInvisibleN n ty = split n ty ty []
+splitInvisPiTysN n ty = split n ty ty []
where
split n orig_ty ty bs
| n == 0 = (reverse bs, orig_ty)
=====================================
compiler/GHC/HsToCore/Foreign/Decl.hs
=====================================
@@ -316,7 +316,7 @@ dsPrimCall :: Id -> Coercion -> ForeignCall
dsPrimCall fn_id co fcall = do
let
ty = coercionLKind co
- (tvs, fun_ty) = tcSplitForAllTyVars ty
+ (tvs, fun_ty) = tcSplitForAllInvisTyVars ty
(arg_tys, io_res_ty) = tcSplitFunTys fun_ty
args <- newSysLocalsDs arg_tys -- no FFI levity-polymorphism
@@ -489,7 +489,7 @@ dsFExportDynamic id co0 cconv = do
where
ty = coercionLKind co0
- (tvs,sans_foralls) = tcSplitForAllTyVars ty
+ (tvs,sans_foralls) = tcSplitForAllInvisTyVars ty
([Scaled arg_mult arg_ty], fn_res_ty) = tcSplitFunTys sans_foralls
Just (io_tc, res_ty) = tcSplitIOType_maybe fn_res_ty
-- Must have an IO type; hence Just
=====================================
compiler/GHC/Runtime/Heap/Inspect.hs
=====================================
@@ -1389,4 +1389,4 @@ quantifyType ty = ( filter isTyVar $
tyCoVarsOfTypeWellScoped rho
, rho)
where
- (_tvs, rho) = tcSplitForAllTyVars ty
+ (_tvs, rho) = tcSplitForAllInvisTyVars ty
=====================================
compiler/GHC/Tc/Gen/HsType.hs
=====================================
@@ -2568,13 +2568,13 @@ kcCheckDeclHeader_sig kisig name flav
split_invis :: Kind -> Maybe Kind -> ([TyCoBinder], Kind)
split_invis sig_ki Nothing =
-- instantiate all invisible binders
- splitPiTysInvisible sig_ki
+ splitInvisPiTys sig_ki
split_invis sig_ki (Just res_ki) =
-- subtraction a la checkExpectedKind
let n_res_invis_bndrs = invisibleTyBndrCount res_ki
n_sig_invis_bndrs = invisibleTyBndrCount sig_ki
n_inst = n_sig_invis_bndrs - n_res_invis_bndrs
- in splitPiTysInvisibleN n_inst sig_ki
+ in splitInvisPiTysN n_inst sig_ki
-- A quantifier from a kind signature zipped with a user-written binder for it.
data ZippedBinder =
=====================================
compiler/GHC/Tc/TyCl/Instance.hs
=====================================
@@ -950,7 +950,7 @@ tcDataFamInstHeader mb_clsinfo fam_tc outer_bndrs fixity
tc_kind_sig (Just hs_kind)
= do { sig_kind <- tcLHsKindSig data_ctxt hs_kind
; lvl <- getTcLevel
- ; let (tvs, inner_kind) = tcSplitForAllTyVars sig_kind
+ ; let (tvs, inner_kind) = tcSplitForAllInvisTyVars sig_kind
; (subst, _tvs') <- tcInstSkolTyVarsAt lvl False emptyTCvSubst tvs
-- Perhaps surprisingly, we don't need the skolemised tvs themselves
; return (substTy subst inner_kind) }
=====================================
compiler/GHC/Tc/Utils/Backpack.hs
=====================================
@@ -223,8 +223,8 @@ check_inst sig_inst = do
skol_info = InstSkol
-- Based off of tcSplitDFunTy
(tvs, theta, pred) =
- case tcSplitForAllTyVars ty of { (tvs, rho) ->
- case splitFunTys rho of { (theta, pred) ->
+ case tcSplitForAllInvisTyVars ty of { (tvs, rho) ->
+ case splitFunTys rho of { (theta, pred) ->
(tvs, theta, pred) }}
origin = InstProvidedOrigin (tcg_semantic_mod tcg_env) sig_inst
(skol_subst, tvs_skols) <- tcInstSkolTyVars tvs -- Skolemize
=====================================
compiler/GHC/Tc/Utils/Instantiate.hs
=====================================
@@ -464,7 +464,7 @@ tcInstType inst_tyvars id
subst' = extendTCvInScopeSet subst (tyCoVarsOfType rho)
; return (tv_prs, substTheta subst' theta, substTy subst' tau) }
where
- (tyvars, rho) = tcSplitForAllTyVars (idType id)
+ (tyvars, rho) = tcSplitForAllInvisTyVars (idType id)
(theta, tau) = tcSplitPhiTy rho
tcInstTypeBndrs :: Id -> TcM ([(Name, InvisTVBinder)], TcThetaType, TcType)
=====================================
compiler/GHC/Tc/Utils/TcType.hs
=====================================
@@ -60,7 +60,7 @@ module GHC.Tc.Utils.TcType (
-- These are important because they do not look through newtypes
getTyVar,
tcSplitForAllTyVarBinder_maybe,
- tcSplitForAllTyVars, tcSplitSomeForAllTyVars,
+ tcSplitForAllTyVars, tcSplitForAllInvisTyVars, tcSplitSomeForAllTyVars,
tcSplitForAllReqTVBinders, tcSplitForAllInvisTVBinders,
tcSplitPiTys, tcSplitPiTy_maybe, tcSplitForAllTyVarBinders,
tcSplitPhiTy, tcSplitPredFunTy_maybe,
@@ -1223,12 +1223,17 @@ tcSplitForAllTyVarBinder_maybe (ForAllTy tv ty) = ASSERT( isTyVarBinder tv ) Jus
tcSplitForAllTyVarBinder_maybe _ = Nothing
-- | Like 'tcSplitPiTys', but splits off only named binders,
--- returning just the tycovars.
+-- returning just the tyvars.
tcSplitForAllTyVars :: Type -> ([TyVar], Type)
tcSplitForAllTyVars ty
= ASSERT( all isTyVar (fst sty) ) sty
where sty = splitForAllTyCoVars ty
+-- | Like 'tcSplitForAllTyVars', but only splits 'ForAllTy's with 'Invisible'
+-- type variable binders.
+tcSplitForAllInvisTyVars :: Type -> ([TyVar], Type)
+tcSplitForAllInvisTyVars ty = tcSplitSomeForAllTyVars isInvisibleArgFlag ty
+
-- | Like 'tcSplitForAllTyVars', but only splits a 'ForAllTy' if @argf_pred argf@
-- is 'True', where @argf@ is the visibility of the @ForAllTy@'s binder and
-- @argf_pred@ is a predicate over visibilities provided as an argument to this
@@ -1284,9 +1289,11 @@ tcSplitPhiTy ty
Just (pred, ty) -> split ty (pred:ts)
Nothing -> (reverse ts, ty)
--- | Split a sigma type into its parts.
+-- | Split a sigma type into its parts. This only splits /invisible/ type
+-- variable binders, as these are the only forms of binder that the typechecker
+-- will implicitly instantiate.
tcSplitSigmaTy :: Type -> ([TyVar], ThetaType, Type)
-tcSplitSigmaTy ty = case tcSplitForAllTyVars ty of
+tcSplitSigmaTy ty = case tcSplitForAllInvisTyVars ty of
(tvs, rho) -> case tcSplitPhiTy rho of
(theta, tau) -> (tvs, theta, tau)
@@ -1469,9 +1476,9 @@ tcSplitDFunTy :: Type -> ([TyVar], [Type], Class, [Type])
-- the latter specifically stops at PredTy arguments,
-- and we don't want to do that here
tcSplitDFunTy ty
- = case tcSplitForAllTyVars ty of { (tvs, rho) ->
- case splitFunTys rho of { (theta, tau) ->
- case tcSplitDFunHead tau of { (clas, tys) ->
+ = case tcSplitForAllInvisTyVars ty of { (tvs, rho) ->
+ case splitFunTys rho of { (theta, tau) ->
+ case tcSplitDFunHead tau of { (clas, tys) ->
(tvs, map scaledThing theta, clas, tys) }}}
tcSplitDFunHead :: Type -> (Class, [Type])
@@ -1489,7 +1496,7 @@ tcSplitMethodTy :: Type -> ([TyVar], PredType, Type)
-- tcSplitMethodTy just peels off the outer forall and
-- that first predicate
tcSplitMethodTy ty
- | (sel_tyvars,sel_rho) <- tcSplitForAllTyVars ty
+ | (sel_tyvars,sel_rho) <- tcSplitForAllInvisTyVars ty
, Just (first_pred, local_meth_ty) <- tcSplitPredFunTy_maybe sel_rho
= (sel_tyvars, first_pred, local_meth_ty)
| otherwise
=====================================
compiler/GHC/Tc/Validity.hs
=====================================
@@ -924,7 +924,7 @@ forAllTyErr env rank ty
, vcat [ hang herald 2 (ppr_tidy env ty)
, suggestion ] )
where
- (tvs, _theta, _tau) = tcSplitSigmaTy ty
+ (tvs, _rho) = tcSplitForAllTyVars ty
herald | null tvs = text "Illegal qualified type:"
| otherwise = text "Illegal polymorphic type:"
suggestion = case rank of
=====================================
testsuite/tests/typecheck/should_compile/T18939_Compile.hs
=====================================
@@ -0,0 +1,11 @@
+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE PolyKinds #-}
+{-# LANGUAGE RankNTypes #-}
+{-# LANGUAGE StandaloneKindSignatures #-}
+{-# LANGUAGE TypeFamilies #-}
+module T18939_Compile where
+
+import Data.Kind
+
+data family Hm :: forall a -> a -> Type
+data instance Hm :: forall a -> a -> Type
=====================================
testsuite/tests/typecheck/should_compile/all.T
=====================================
@@ -726,6 +726,7 @@ test('T18323', normal, compile, [''])
test('T18585', normal, compile, [''])
test('T18831', normal, compile, [''])
test('T18920', normal, compile, [''])
+test('T18939_Compile', normal, compile, [''])
test('T15942', normal, compile, [''])
test('ClassDefaultInHsBoot', [extra_files(['ClassDefaultInHsBootA1.hs','ClassDefaultInHsBootA2.hs','ClassDefaultInHsBootA2.hs-boot','ClassDefaultInHsBootA3.hs'])], multimod_compile, ['ClassDefaultInHsBoot', '-v0'])
test('T17186', normal, compile, [''])
=====================================
testsuite/tests/typecheck/should_fail/T18939_Fail.hs
=====================================
@@ -0,0 +1,5 @@
+{-# LANGUAGE ExplicitForAll #-}
+{-# LANGUAGE PolyKinds #-}
+module T18939_Fail where
+
+data F (f :: forall a -> a)
=====================================
testsuite/tests/typecheck/should_fail/T18939_Fail.stderr
=====================================
@@ -0,0 +1,5 @@
+
+T18939_Fail.hs:5:1: error:
+ ⢠Illegal polymorphic type: forall a -> a
+ Perhaps you intended to use RankNTypes
+ ⢠In the data type declaration for âFâ
=====================================
testsuite/tests/typecheck/should_fail/all.T
=====================================
@@ -583,6 +583,7 @@ test('T18714', normal, compile_fail, [''])
test('T18723a', normal, compile_fail, [''])
test('T18723b', normal, compile_fail, [''])
test('T18723c', normal, compile_fail, [''])
+test('T18939_Fail', normal, compile_fail, [''])
test('too-many', normal, compile_fail, [''])
test('T18640a', normal, compile_fail, [''])
test('T18640b', normal, compile_fail, [''])
=====================================
utils/haddock
=====================================
@@ -1 +1 @@
-Subproject commit ad9cbad7312a64e6757c32bd9488c55ba4f2fec9
+Subproject commit 4d0498d503bd51b7d7626497580232685a2691a1
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/e5dabf5534b55a340df10ed486fdb6afb054457d
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/e5dabf5534b55a340df10ed486fdb6afb054457d
You're receiving this email because of your account on gitlab.haskell.org.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.haskell.org/pipermail/ghc-commits/attachments/20201113/49577807/attachment-0001.html>
More information about the ghc-commits
mailing list