summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRyan Scott <ryan.gl.scott@gmail.com>2019-02-05 08:50:59 -0500
committerMarge Bot <ben+marge-bot@smart-cactus.org>2019-02-06 05:32:34 -0500
commitc07e7ecbdfc05429fb6ce84c547c0365d2754db7 (patch)
tree75afd449b634e779004de566f791049a66849527
parent9292a183fd031d81ac7027eb95dd5a46249845f8 (diff)
downloadhaskell-c07e7ecbdfc05429fb6ce84c547c0365d2754db7.tar.gz
Fix #16287 by checking for more unsaturated synonym arguments
Trac #16287 shows that we were checking for unsaturated type synonym arguments (in `:kind`) when the argument was to a type synonym, but _not_ when the argument was to some other form of type constructor, such as a data type. The solution is to use the machinery that rejects unsaturated type synonym arguments (previously confined to `check_syn_tc_app`) to `check_arg_type`, which checks these other forms of arguments. While I was in town, I cleaned up `check_syn_tc_app` a bit to only invoke `check_arg_type` so as to minimize the number of different code paths that that function could go down.
-rw-r--r--compiler/typecheck/TcValidity.hs47
-rw-r--r--testsuite/tests/ghci/should_fail/T16287.script10
-rw-r--r--testsuite/tests/ghci/should_fail/T16287.stderr12
-rw-r--r--testsuite/tests/ghci/should_fail/all.T1
4 files changed, 46 insertions, 24 deletions
diff --git a/compiler/typecheck/TcValidity.hs b/compiler/typecheck/TcValidity.hs
index ca58877bcb..218f539c68 100644
--- a/compiler/typecheck/TcValidity.hs
+++ b/compiler/typecheck/TcValidity.hs
@@ -599,13 +599,13 @@ check_type _ (TyVarTy _) = return ()
check_type ve (AppTy ty1 ty2)
= do { check_type ve ty1
- ; check_arg_type ve ty2 }
+ ; check_arg_type False ve ty2 }
check_type ve ty@(TyConApp tc tys)
| isTypeSynonymTyCon tc || isTypeFamilyTyCon tc
= check_syn_tc_app ve ty tc tys
| isUnboxedTupleTyCon tc = check_ubx_tuple ve ty tys
- | otherwise = mapM_ (check_arg_type ve) tys
+ | otherwise = mapM_ (check_arg_type False ve) tys
check_type _ (LitTy {}) = return ()
@@ -693,14 +693,8 @@ check_syn_tc_app (ve@ValidityEnv{ ve_ctxt = ctxt, ve_expand = expand })
tc_arity = tyConArity tc
check_arg :: ExpandMode -> KindOrType -> TcM ()
- check_arg expand
- | isTypeFamilyTyCon tc
- = check_arg_type ve'
- | otherwise
- = check_type (ve'{ve_rank = synArgMonoType})
- where
- ve' :: ValidityEnv
- ve' = ve{ve_ctxt = arg_ctxt, ve_expand = expand}
+ check_arg expand =
+ check_arg_type (isTypeSynonymTyCon tc) (ve{ve_expand = expand})
check_args_only, check_expansion_only :: ExpandMode -> TcM ()
check_args_only expand = mapM_ (check_arg expand) tys
@@ -713,15 +707,6 @@ check_syn_tc_app (ve@ValidityEnv{ ve_ctxt = ctxt, ve_expand = expand })
check_type (ve{ve_expand = expand}) ty'
Nothing -> pprPanic "check_syn_tc_app" (ppr ty)
- arg_ctxt :: UserTypeCtxt
- arg_ctxt
- | GhciCtxt _ <- ctxt = GhciCtxt False
- -- When checking an argument, set the field of GhciCtxt to False to
- -- indicate that we are no longer in an outermost position (and thus
- -- unsaturated synonyms are no longer allowed).
- -- See Note [Unsaturated type synonyms in GHCi]
- | otherwise = ctxt
-
{-
Note [Unsaturated type synonyms in GHCi]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -774,7 +759,9 @@ check_ubx_tuple (ve@ValidityEnv{ve_tidy_env = env}) ty tys
; mapM_ (check_type (ve{ve_rank = rank'})) tys }
----------------------------------------
-check_arg_type :: ValidityEnv -> KindOrType -> TcM ()
+check_arg_type
+ :: Bool -- ^ Is this the argument to a type synonym?
+ -> ValidityEnv -> KindOrType -> TcM ()
-- The sort of type that can instantiate a type variable,
-- or be the argument of a type constructor.
-- Not an unboxed tuple, but now *can* be a forall (since impredicativity)
@@ -793,11 +780,14 @@ check_arg_type :: ValidityEnv -> KindOrType -> TcM ()
-- But not in user code.
-- Anyway, they are dealt with by a special case in check_tau_type
-check_arg_type _ (CoercionTy {}) = return ()
+check_arg_type _ _ (CoercionTy {}) = return ()
-check_arg_type (ve@ValidityEnv{ve_rank = rank}) ty
+check_arg_type type_syn (ve@ValidityEnv{ve_ctxt = ctxt, ve_rank = rank}) ty
= do { impred <- xoptM LangExt.ImpredicativeTypes
; let rank' = case rank of -- Predictive => must be monotype
+ -- Rank-n arguments to type synonyms are OK, provided
+ -- that LiberalTypeSynonyms is enabled.
+ _ | type_syn -> synArgMonoType
MustBeMonoType -> MustBeMonoType -- Monotype, regardless
_other | impred -> ArbitraryRank
| otherwise -> tyConArgMonoType
@@ -805,8 +795,17 @@ check_arg_type (ve@ValidityEnv{ve_rank = rank}) ty
-- so that we don't suggest -XImpredicativeTypes in
-- (Ord (forall a.a)) => a -> a
-- and so that if it Must be a monotype, we check that it is!
-
- ; check_type (ve{ve_rank = rank'}) ty }
+ ctxt' :: UserTypeCtxt
+ ctxt'
+ | GhciCtxt _ <- ctxt = GhciCtxt False
+ -- When checking an argument, set the field of GhciCtxt to
+ -- False to indicate that we are no longer in an outermost
+ -- position (and thus unsaturated synonyms are no longer
+ -- allowed).
+ -- See Note [Unsaturated type synonyms in GHCi]
+ | otherwise = ctxt
+
+ ; check_type (ve{ve_ctxt = ctxt', ve_rank = rank'}) ty }
----------------------------------------
forAllTyErr :: TidyEnv -> Rank -> Type -> (TidyEnv, SDoc)
diff --git a/testsuite/tests/ghci/should_fail/T16287.script b/testsuite/tests/ghci/should_fail/T16287.script
new file mode 100644
index 0000000000..9976832cca
--- /dev/null
+++ b/testsuite/tests/ghci/should_fail/T16287.script
@@ -0,0 +1,10 @@
+:set -XPolyKinds -XRankNTypes -XTypeFamilies
+import Data.Kind
+type F1 a = a
+type family F2 :: k
+data T1 :: (Type -> Type) -> Type
+data T2 :: (forall k. k) -> Type
+:kind T1 F1
+:kind T2 F2
+:kind Maybe (T1 F1)
+:kind Maybe (T2 F2)
diff --git a/testsuite/tests/ghci/should_fail/T16287.stderr b/testsuite/tests/ghci/should_fail/T16287.stderr
new file mode 100644
index 0000000000..13f0852144
--- /dev/null
+++ b/testsuite/tests/ghci/should_fail/T16287.stderr
@@ -0,0 +1,12 @@
+
+<interactive>:1:1: error:
+ The type synonym ‘F1’ should have 1 argument, but has been given none
+
+<interactive>:1:1: error:
+ The type family ‘F2’ should have no arguments, but has been given none
+
+<interactive>:1:1: error:
+ The type synonym ‘F1’ should have 1 argument, but has been given none
+
+<interactive>:1:1: error:
+ The type family ‘F2’ should have no arguments, but has been given none
diff --git a/testsuite/tests/ghci/should_fail/all.T b/testsuite/tests/ghci/should_fail/all.T
index 5e0a18c5b8..da01a98e3e 100644
--- a/testsuite/tests/ghci/should_fail/all.T
+++ b/testsuite/tests/ghci/should_fail/all.T
@@ -3,3 +3,4 @@ test('T10549a', [], ghci_script, ['T10549a.script'])
test('T14608', [], ghci_script, ['T14608.script'])
test('T15055', normalise_version('ghc'), ghci_script, ['T15055.script'])
test('T16013', [], ghci_script, ['T16013.script'])
+test('T16287', [], ghci_script, ['T16287.script'])