[Git][ghc/ghc][wip/sand-witch/DIB-INSTANCES] Remove arity inference in type declarations (#23514)

Andrei Borzenkov (@sand-witch) gitlab at gitlab.haskell.org
Wed Jun 14 13:53:08 UTC 2023



Andrei Borzenkov pushed to branch wip/sand-witch/DIB-INSTANCES at Glasgow Haskell Compiler / GHC


Commits:
4eaa6859 by Andrei Borzenkov at 2023-06-14T17:50:40+04:00
Remove arity inference in type declarations (#23514)

Arity inference in type declarations was introduced
as a workaround for the lack of @k-binders.

They were added in 4aea0a72040, so I simplified all
of this by simply removing arity inference altogether.

This is part of GHC Proposal #425 "Invisible binders in type
declarations".

- - - - -


18 changed files:

- compiler/GHC/Core/Type.hs
- compiler/GHC/Iface/Syntax.hs
- compiler/GHC/Tc/Gen/HsType.hs
- compiler/GHC/Tc/Gen/Splice.hs
- libraries/template-haskell/Language/Haskell/TH/Syntax.hs
- + testsuite/tests/rename/should_compile/T23514b.hs
- testsuite/tests/rename/should_compile/all.T
- + testsuite/tests/rename/should_fail/T23514a.hs
- + testsuite/tests/rename/should_fail/T23514a.stderr
- testsuite/tests/rename/should_fail/all.T
- testsuite/tests/saks/should_compile/T16724.stdout
- testsuite/tests/saks/should_compile/saks020.hs
- testsuite/tests/saks/should_compile/saks030.hs
- testsuite/tests/saks/should_compile/saks032.hs
- testsuite/tests/typecheck/should_fail/T18640a.hs
- testsuite/tests/typecheck/should_fail/T18640a.stderr
- testsuite/tests/typecheck/should_fail/T18640c.hs
- testsuite/tests/typecheck/should_fail/T18640c.stderr


Changes:

=====================================
compiler/GHC/Core/Type.hs
=====================================
@@ -60,7 +60,7 @@ module GHC.Core.Type (
         mkTyConBindersPreferAnon,
         mkPiTy, mkPiTys,
         piResultTy, piResultTys,
-        applyTysX, dropForAlls,
+        applyTysX, dropForAlls, dropInvisForAlls,
         mkFamilyTyConApp,
         buildSynTyCon,
 
@@ -1937,6 +1937,14 @@ dropForAlls ty = go ty
     go ty | Just ty' <- coreView ty = go ty'
     go res                         = res
 
+-- | Drops all invisible ForAllTys
+dropInvisForAlls :: Type -> Type
+dropInvisForAlls ty = go ty
+  where
+    go (ForAllTy (Bndr _ Invisible{}) res) = go res
+    go ty | Just ty' <- coreView ty        = go ty'
+    go res                                 = res
+
 -- | Attempts to take a forall type apart, but only if it's a proper forall,
 -- with a named binder
 splitForAllTyCoVar_maybe :: Type -> Maybe (TyCoVar, Type)


=====================================
compiler/GHC/Iface/Syntax.hs
=====================================
@@ -863,12 +863,7 @@ pprIfaceDecl ss (IfaceData { ifName = tycon, ifCType = ctype,
     cons       = visibleIfConDecls condecls
     pp_where   = ppWhen (gadt && not (null cons)) $ text "where"
     pp_cons    = ppr_trim (map show_con cons) :: [SDoc]
-    pp_kind    = ppUnless (if ki_sig_printable
-                              then isIfaceRhoType kind
-                                      -- Even in the presence of a standalone kind signature, a non-tau
-                                      -- result kind annotation cannot be discarded as it determines the arity.
-                                      -- See Note [Arity inference in kcCheckDeclHeader_sig] in GHC.Tc.Gen.HsType
-                              else isIfaceLiftedTypeKind kind)
+    pp_kind    = ppUnless (ki_sig_printable || isIfaceLiftedTypeKind kind)
                           (dcolon <+> ppr kind)
 
     pp_lhs = case parent of


=====================================
compiler/GHC/Tc/Gen/HsType.hs
=====================================
@@ -2557,35 +2557,25 @@ kcCheckDeclHeader_sig sig_kind name flav
                    -- extended with both 'implicit_tcv_prs' and 'explicit_tv_prs'.
                  ; ctx_k <- kc_res_ki
 
-                 -- Work out extra_arity, the number of extra invisible binders from
-                 -- the kind signature that should be part of the TyCon's arity.
-                 -- See Note [Arity inference in kcCheckDeclHeader_sig]
-                 ; let n_invis_tcbs = countWhile isInvisibleTyConBinder excess_sig_tcbs
-                       invis_arity = case ctx_k of
-                          AnyKind    -> n_invis_tcbs -- No kind signature, so make all the invisible binders
-                                                     -- the signature into part of the arity of the TyCon
-                          OpenKind   -> n_invis_tcbs -- Result kind is (TYPE rr), so again make all the
-                                                     -- invisible binders part of the arity of the TyCon
-                          TheKind ki -> 0 `max` (n_invis_tcbs - invisibleTyBndrCount ki)
-
-                 ; let (invis_tcbs, resid_tcbs) = splitAt invis_arity excess_sig_tcbs
-                 ; let sig_res_kind' = mkTyConKind resid_tcbs sig_res_kind
-
-                 ; traceTc "kcCheckDeclHeader_sig 2" $ vcat [ ppr excess_sig_tcbs
-                                                            , ppr invis_arity, ppr invis_tcbs
-                                                            , ppr n_invis_tcbs ]
+                 ; let sig_res_kind' = mkTyConKind excess_sig_tcbs sig_res_kind
+
+                 ; traceTc "kcCheckDeclHeader_sig 2" (ppr excess_sig_tcbs)
 
                  -- Unify res_ki (from the type declaration) with the residual kind from
                  -- the kind signature. Don't forget to apply the skolemising 'subst' first.
                  ; case ctx_k of
                       AnyKind -> return ()   -- No signature
-                      _ -> do { res_ki <- newExpectedKind ctx_k
-                              ; discardResult (unifyKind Nothing sig_res_kind' res_ki) }
+                      OpenKind ->
+                        do { res_ki <- newExpectedKind ctx_k
+                           ; discardResult (unifyKind Nothing (dropInvisForAlls sig_res_kind') res_ki) }
+                      TheKind _ ->
+                        do { res_ki <- newExpectedKind ctx_k
+                           ; discardResult (unifyKind Nothing sig_res_kind' res_ki) }
 
                  -- Add more binders for data/newtype, so the result kind has no arrows
                  -- See Note [Datatype return kinds]
-                 ; if null resid_tcbs || not (needsEtaExpansion flav)
-                   then return (invis_tcbs,      sig_res_kind')
+                 ; if null excess_sig_tcbs || not (needsEtaExpansion flav)
+                   then return ([],      sig_res_kind')
                    else return (excess_sig_tcbs, sig_res_kind)
           }
 
@@ -2780,86 +2770,6 @@ Basic plan is this:
     part of the signature (k -> Type) with the kind signature of the decl,
     (j -> Type).  This unification, done in kcCheckDeclHeader, needs TcTyVars.
 
-  * The tricky extra_arity part is described in
-    Note [Arity inference in kcCheckDeclHeader_sig]
-
-Note [Arity inference in kcCheckDeclHeader_sig]
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-Consider these declarations:
-  type family S1 :: forall k2. k1 -> k2 -> Type
-  type family S2 (a :: k1) (b :: k2) :: Type
-
-Both S1 and S2 can be given the same standalone kind signature:
-  type S1 :: forall k1 k2. k1 -> k2 -> Type
-  type S2 :: forall k1 k2. k1 -> k2 -> Type
-
-And, indeed, tyConKind S1 == tyConKind S2. However,
-tyConBinders and tyConResKind for S1 and S2 are different:
-
-  tyConBinders S1  ==  [spec k1]
-  tyConResKind S1  ==  forall k2. k1 -> k2 -> Type
-  tyConKind    S1  ==  forall k1 k2. k1 -> k2 -> Type
-
-  tyConBinders S2  ==  [spec k1, spec k2, anon-vis (a :: k1), anon-vis (b :: k2)]
-  tyConResKind S2  ==  Type
-  tyConKind    S1  ==  forall k1 k2. k1 -> k2 -> Type
-
-This difference determines the /arity/:
-  tyConArity tc == length (tyConBinders tc)
-That is, the arity of S1 is 1, while the arity of S2 is 4.
-
-'kcCheckDeclHeader_sig' needs to infer the desired arity, to split the
-standalone kind signature into binders and the result kind. It does so
-in two rounds:
-
-1. matchUpSigWithDecl matches up
-   - the [TyConBinder] from (applying splitTyConKind to) the kind signature
-   - with the [LHsTyVarBndr] from the type declaration.
-   That may leave some excess TyConBinder: in the case of S2 there are
-   no excess TyConBinders, but in the case of S1 there are two (since
-   there are no LHsTYVarBndrs.
-
-2. Split off further TyConBinders (in the case of S1, one more) to
-   make it possible to unify the residual return kind with the
-   signature in the type declaration.  More precisely, split off such
-   enough invisible that the remainder of the standalone kind
-   signature and the user-written result kind signature have the same
-   number of invisible quantifiers.
-
-As another example consider the following declarations:
-
-    type F :: Type -> forall j. j -> forall k1 k2. (k1, k2) -> Type
-    type family F a b
-
-    type G :: Type -> forall j. j -> forall k1 k2. (k1, k2) -> Type
-    type family G a b :: forall r2. (r1, r2) -> Type
-
-For both F and G, the signature (after splitTyConKind) has
-  sig_tcbs :: [TyConBinder]
-    = [ anon-vis (@a_aBq), spec (@j_auA), anon-vis (@(b_aBr :: j_auA))
-      , spec (@k1_auB), spec (@k2_auC)
-      , anon-vis (@(c_aBs :: (k1_auB, k2_auC)))]
-
-matchUpSigWithDecl will consume the first three of these, passing on
-  excess_sig_tcbs
-    = [ spec (@k1_auB), spec (@k2_auC)
-      , anon-vis (@(c_aBs :: (k1_auB, k2_auC)))]
-
-For F, there is no result kind signature in the declaration for F, so
-we absorb all invisible binders into F's arity. The resulting arity of
-F is 3+2=5.
-
-Now, in the case of G, we have a result kind sig 'forall r2. (r2,r2)->Type'.
-This has one invisible binder, so we split of enough extra binders from
-our excess_sig_tcbs to leave just one to match 'r2'.
-
-    res_ki  =  forall    r2. (r1, r2) -> Type
-    kisig   =  forall k1 k2. (k1, k2) -> Type
-                     ^^^
-                     split off this one.
-
-The resulting arity of G is 3+1=4.
-
 Note [discardResult in kcCheckDeclHeader_sig]
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 We use 'unifyKind' to check inline kind annotations in declaration headers


=====================================
compiler/GHC/Tc/Gen/Splice.hs
=====================================
@@ -796,7 +796,7 @@ tcTExpTy m_ty exp_ty
           TcRnTHError $ TypedTHError $ TypedTHWithPolyType exp_ty
        ; codeCon <- tcLookupTyCon codeTyConName
        ; let rep = getRuntimeRep exp_ty
-       ; return (mkTyConApp codeCon [rep, m_ty, exp_ty]) }
+       ; return (mkTyConApp codeCon [m_ty, rep, exp_ty]) }
 
 quotationCtxtDoc :: LHsExpr GhcRn -> SDoc
 quotationCtxtDoc br_body


=====================================
libraries/template-haskell/Language/Haskell/TH/Syntax.hs
=====================================
@@ -378,8 +378,11 @@ The splice will evaluate to (MkAge 3) and you can't add that to
 4::Int. So you can't coerce a (Code Q Age) to a (Code Q Int). -}
 
 -- Code constructor
-
+#if __GLASGOW_HASKELL__ >= 907
+type Code :: (Kind.Type -> Kind.Type) -> forall r. TYPE r -> Kind.Type
+#else
 type Code :: (Kind.Type -> Kind.Type) -> TYPE r -> Kind.Type
+#endif
 type role Code representational nominal   -- See Note [Role of TExp]
 newtype Code m a = Code
   { examineCode :: m (TExp a) -- ^ Underlying monadic value


=====================================
testsuite/tests/rename/should_compile/T23514b.hs
=====================================
@@ -0,0 +1,9 @@
+{-# LANGUAGE TypeFamilies, DataKinds #-}
+module T23514b where
+
+import GHC.Types
+
+type F :: Type -> forall k. Maybe k
+type family F x @k where
+  F Int @Type = Just Bool
+  F Int       = Just Either


=====================================
testsuite/tests/rename/should_compile/all.T
=====================================
@@ -212,3 +212,4 @@ test('T22122', [expect_broken(22122), extra_files(['T22122_aux.hs'])], multimod_
 test('T23240', [req_th, extra_files(['T23240_aux.hs'])], multimod_compile, ['T23240', '-v0'])
 test('T23318', normal, compile, ['-Wduplicate-exports'])
 test('T23434', normal, compile, [''])
+test('T23514b', normal, compile, [''])


=====================================
testsuite/tests/rename/should_fail/T23514a.hs
=====================================
@@ -0,0 +1,9 @@
+{-# LANGUAGE TypeFamilies, DataKinds #-}
+module T23514a where
+
+import GHC.Types
+
+type F :: Type -> forall k. Maybe k
+type family F x where
+  F Int @Type = Just Bool
+  F Int       = Just Either


=====================================
testsuite/tests/rename/should_fail/T23514a.stderr
=====================================
@@ -0,0 +1,6 @@
+
+T23514a.hs:9:17: error: [GHC-83865]
+    • Expected kind ‘forall k. Maybe k’,
+        but ‘Just Either’ has kind ‘Maybe (* -> * -> *)’
+    • In the type ‘Just Either’
+      In the type family declaration for ‘F’


=====================================
testsuite/tests/rename/should_fail/all.T
=====================================
@@ -199,3 +199,4 @@ test('RnUnexpectedStandaloneDeriving', normal, compile_fail, [''])
 test('RnStupidThetaInGadt', normal, compile_fail, [''])
 test('PackageImportsDisabled', normal, compile_fail, [''])
 test('ImportLookupIllegal', normal, compile_fail, [''])
+test('T23514a', normal, compile_fail, [''])


=====================================
testsuite/tests/saks/should_compile/T16724.stdout
=====================================
@@ -1,6 +1,6 @@
 type T1 :: forall k (a :: k). Type
-type family T1 @k @a
+type family T1
   	-- Defined at T16724.hs:11:1
 type T2 :: forall {k} (a :: k). Type
-type family T2 @{k} @a
+type family T2
   	-- Defined at T16724.hs:15:1


=====================================
testsuite/tests/saks/should_compile/saks020.hs
=====================================
@@ -6,4 +6,4 @@ module SAKS_020 where
 import Data.Kind (Type)
 
 type T :: forall k. k -> forall j. j -> Type
-data T (x :: hk) :: hj -> Type
+data T (x :: hk) @hj :: hj -> Type


=====================================
testsuite/tests/saks/should_compile/saks030.hs
=====================================
@@ -10,7 +10,7 @@ import Data.Type.Equality
 type T1 :: forall k (a :: k). Bool
 type T2 :: k -> Bool
 
-type family T1 where
+type family T1 @k @a where
   T1 @Bool @True  = False
   T1 @Bool @False = True
 


=====================================
testsuite/tests/saks/should_compile/saks032.hs
=====================================
@@ -18,4 +18,4 @@ type F1 :: Type -> forall j. j -> forall k1 k2. (k1, k2) -> Type
 type family F1 a b
 
 type F2 :: Type -> forall j. j -> forall k1 k2. (k1, k2) -> Type
-type family F2 a b :: forall r2. (r1, r2) -> Type
+type family F2 a b @r1 :: forall r2. (r1, r2) -> Type


=====================================
testsuite/tests/typecheck/should_fail/T18640a.hs
=====================================
@@ -8,4 +8,4 @@ module T18640a where
 import Data.Kind
 
 type F2 :: forall a b. Type -> a
-type family F2 :: forall b. Type -> Type where
+type family F2 @a :: forall b. Type -> Type where


=====================================
testsuite/tests/typecheck/should_fail/T18640a.stderr
=====================================
@@ -5,5 +5,5 @@ T18640a.hs:11:1: error: [GHC-25897]
         Actual: forall (b :: k). * -> a
       ‘a’ is a rigid type variable bound by
         the type family declaration for ‘F2’
-        at T18640a.hs:10:19
+        at T18640a.hs:11:17
     • In the type family declaration for ‘F2’


=====================================
testsuite/tests/typecheck/should_fail/T18640c.hs
=====================================
@@ -11,4 +11,4 @@ type F1 :: forall k -> Type
 type family F1 k :: Type
 
 type F2 :: forall x. forall k -> x
-type F2 = F1
+type F2 k = F1 k


=====================================
testsuite/tests/typecheck/should_fail/T18640c.stderr
=====================================
@@ -1,10 +1,8 @@
 
-T18640c.hs:14:11: error: [GHC-25897]
-    • Couldn't match kind ‘x’ with ‘*’
-      Expected kind ‘forall (k1 :: k) -> x’,
-        but ‘F1’ has kind ‘forall (k1 :: k) -> *’
+T18640c.hs:14:13: error: [GHC-25897]
+    • Expected kind ‘x’, but ‘F1 k’ has kind ‘*’
       ‘x’ is a rigid type variable bound by
         the type synonym declaration for ‘F2’
         at T18640c.hs:13:19
-    • In the type ‘F1’
+    • In the type ‘F1 k’
       In the type declaration for ‘F2’



View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/4eaa68595592067eadbcae9c37ff2597bf3fa29b

-- 
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/4eaa68595592067eadbcae9c37ff2597bf3fa29b
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/20230614/eba149ec/attachment-0001.html>


More information about the ghc-commits mailing list