Check that type variable does not reference itself in its kind signature
authorJohn Leo <leo@halfaya.org>
Tue, 10 Jan 2017 18:36:17 +0000 (13:36 -0500)
committerBen Gamari <ben@smart-cactus.org>
Tue, 10 Jan 2017 18:37:18 +0000 (13:37 -0500)
This fixes #11592.

Test Plan: validate

Reviewers: simonpj, austin, bgamari, goldfire

Reviewed By: goldfire

Subscribers: thomie

Differential Revision: https://phabricator.haskell.org/D2914

GHC Trac Issues: #11592

compiler/rename/RnTypes.hs
testsuite/tests/rename/should_fail/T11592.hs [new file with mode: 0644]
testsuite/tests/rename/should_fail/T11592.stderr [new file with mode: 0644]
testsuite/tests/rename/should_fail/all.T

index f3fcf88..ec00511 100644 (file)
@@ -918,19 +918,19 @@ bindLHsTyVarBndr :: HsDocContext
 bindLHsTyVarBndr doc mb_assoc kv_names tv_names hs_tv_bndr thing_inside
   = case hs_tv_bndr of
       L loc (UserTyVar lrdr@(L lv rdr)) ->
-        do { check_dup loc rdr
+        do { check_dup loc rdr []
            ; nm <- newTyVarNameRn mb_assoc lrdr
            ; bindLocalNamesFV [nm] $
              thing_inside [] emptyNameSet (L loc (UserTyVar (L lv nm))) }
       L loc (KindedTyVar lrdr@(L lv rdr) kind) ->
-        do { check_dup lv rdr
+        do { free_kvs <- freeKiTyVarsAllVars <$> extractHsTyRdrTyVars kind
+           ; check_dup lv rdr (map unLoc free_kvs)
 
              -- check for -XKindSignatures
            ; sig_ok <- xoptM LangExt.KindSignatures
            ; unless sig_ok (badKindSigErr doc kind)
 
              -- deal with kind vars in the user-written kind
-           ; free_kvs <- freeKiTyVarsAllVars <$> extractHsTyRdrTyVars kind
            ; bindImplicitKvs doc mb_assoc free_kvs tv_names $
              \ new_kv_nms other_kv_nms ->
              do { (kind', fvs1) <- rnLHsKind doc kind
@@ -943,9 +943,15 @@ bindLHsTyVarBndr doc mb_assoc kv_names tv_names hs_tv_bndr thing_inside
       -- make sure that the RdrName isn't in the sets of
       -- names. We can't just check that it's not in scope at all
       -- because we might be inside an associated class.
-    check_dup :: SrcSpan -> RdrName -> RnM ()
-    check_dup loc rdr
-      = do { m_name <- lookupLocalOccRn_maybe rdr
+    check_dup :: SrcSpan -> RdrName -> [RdrName] -> RnM ()
+    check_dup loc rdr kindFreeVars
+      = do { -- Disallow use of a type variable name in its
+             -- kind signature (#11592).
+             when (rdr `elem` kindFreeVars) $
+             addErrAt loc (vcat [ ki_ty_self_err rdr
+                                , pprHsDocContext doc ])
+
+           ; m_name <- lookupLocalOccRn_maybe rdr
            ; whenIsJust m_name $ \name ->
         do { when (name `elemNameSet` kv_names) $
              addErrAt loc (vcat [ ki_ty_err_msg name
@@ -957,6 +963,10 @@ bindLHsTyVarBndr doc mb_assoc kv_names tv_names hs_tv_bndr thing_inside
                       text "used as a kind variable before being bound" $$
                       text "as a type variable. Perhaps reorder your variables?"
 
+    ki_ty_self_err n = text "Variable" <+> quotes (ppr n) <+>
+                       text "is used in the kind signature of its" $$
+                       text "declaration as a type variable."
+
 
 bindImplicitKvs :: HsDocContext
                 -> Maybe a
diff --git a/testsuite/tests/rename/should_fail/T11592.hs b/testsuite/tests/rename/should_fail/T11592.hs
new file mode 100644 (file)
index 0000000..b963cdf
--- /dev/null
@@ -0,0 +1,10 @@
+{-# LANGUAGE TypeInType #-}
+
+module Bug11592 where
+
+data A (a :: a) = MkA String
+
+data B b (a :: a b) = MkB String
+data C b (a :: b a) = MkC String
+
+data D b c (a :: c a b) = MkD String
diff --git a/testsuite/tests/rename/should_fail/T11592.stderr b/testsuite/tests/rename/should_fail/T11592.stderr
new file mode 100644 (file)
index 0000000..bffea1c
--- /dev/null
@@ -0,0 +1,19 @@
+T11592.hs:5:9:
+    Variable ‘a’ is used in the kind signature of its
+    declaration as a type variable.
+    the data type declaration for ‘A’
+
+T11592.hs:7:11:
+    Variable ‘a’ is used in the kind signature of its
+    declaration as a type variable.
+    the data type declaration for ‘B’
+
+T11592.hs:8:11:
+    Variable ‘a’ is used in the kind signature of its
+    declaration as a type variable.
+    the data type declaration for ‘C’
+
+T11592.hs:10:13:
+    Variable ‘a’ is used in the kind signature of its
+    declaration as a type variable.
+    the data type declaration for ‘D’
index d42ca56..05fc5e4 100644 (file)
@@ -142,4 +142,5 @@ test('T11663', normal, compile_fail, [''])
 test('T12229', normal, compile, [''])
 test('T12681', normal, multimod_compile_fail, ['T12681','-v0'])
 test('T12686', normal, compile_fail, [''])
+test('T11592', normal, compile_fail, [''])
 test('T12879', normal, compile_fail, [''])