summaryrefslogtreecommitdiff
path: root/compiler/iface
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/iface')
-rw-r--r--compiler/iface/IfaceSyn.hs110
-rw-r--r--compiler/iface/IfaceType.hs94
2 files changed, 158 insertions, 46 deletions
diff --git a/compiler/iface/IfaceSyn.hs b/compiler/iface/IfaceSyn.hs
index 688998f96d..f86ca458d7 100644
--- a/compiler/iface/IfaceSyn.hs
+++ b/compiler/iface/IfaceSyn.hs
@@ -69,6 +69,7 @@ import TyCon ( Role (..), Injectivity(..), tyConBndrVisArgFlag )
import Util( dropList, filterByList, notNull, unzipWith )
import DataCon (SrcStrictness(..), SrcUnpackedness(..))
import Lexeme (isLexSym)
+import TysWiredIn ( constraintKindTyConName )
import Control.Monad
import System.IO.Unsafe
@@ -730,6 +731,14 @@ pprClassRoles ss clas binders roles =
binders
roles
+pprClassStandaloneKindSig :: ShowSub -> IfaceTopBndr -> IfaceKind -> SDoc
+pprClassStandaloneKindSig ss clas =
+ pprStandaloneKindSig (pprPrefixIfDeclBndr (ss_how_much ss) (occName clas))
+
+constraintIfaceKind :: IfaceKind
+constraintIfaceKind =
+ IfaceTyConApp (IfaceTyCon constraintKindTyConName (IfaceTyConInfo NotPromoted IfaceNormalTyCon)) IA_Nil
+
pprIfaceDecl :: ShowSub -> IfaceDecl -> SDoc
-- NB: pprIfaceDecl is also used for pretty-printing TyThings in GHCi
-- See Note [Pretty-printing TyThings] in PprTyThing
@@ -741,10 +750,12 @@ pprIfaceDecl ss (IfaceData { ifName = tycon, ifCType = ctype,
ifBinders = binders })
| gadt = vcat [ pp_roles
+ , pp_ki_sig
, pp_nd <+> pp_lhs <+> pp_kind <+> pp_where
, nest 2 (vcat pp_cons)
, nest 2 $ ppShowIface ss pp_extra ]
| otherwise = vcat [ pp_roles
+ , pp_ki_sig
, hang (pp_nd <+> pp_lhs) 2 (add_bars pp_cons)
, nest 2 $ ppShowIface ss pp_extra ]
where
@@ -759,26 +770,45 @@ 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
- | isIfaceLiftedTypeKind kind = empty
- | otherwise = dcolon <+> ppr kind
+ pp_kind = ppUnless (if ki_sig_printable
+ then isIfaceTauType 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 kcDeclHeader_sig] in TcHsType
+ else isIfaceLiftedTypeKind kind)
+ (dcolon <+> ppr kind)
pp_lhs = case parent of
- IfNoParent -> pprIfaceDeclHead context ss tycon binders Nothing
+ IfNoParent -> pprIfaceDeclHead suppress_bndr_sig context ss tycon binders
IfDataInstance{}
-> text "instance" <+> pp_data_inst_forall
<+> pprIfaceTyConParent parent
pp_roles
| is_data_instance = empty
- | otherwise = pprRoles (== Representational)
- (pprPrefixIfDeclBndr
- (ss_how_much ss)
- (occName tycon))
- binders roles
+ | otherwise = pprRoles (== Representational) name_doc binders roles
-- Don't display roles for data family instances (yet)
-- See discussion on #8672.
+ ki_sig_printable =
+ -- If we print a standalone kind signature for a data instance, we leak
+ -- the internal constructor name:
+ --
+ -- type T15827.R:Dka :: forall k. k -> *
+ -- data instance forall k (a :: k). D a = MkD (Proxy a)
+ --
+ -- This T15827.R:Dka is a compiler-generated type constructor for the
+ -- data instance.
+ not is_data_instance
+
+ pp_ki_sig = ppWhen ki_sig_printable $
+ pprStandaloneKindSig name_doc (mkIfaceTyConKind binders kind)
+
+ -- See Note [Suppressing binder signatures] in IfaceType
+ suppress_bndr_sig = SuppressBndrSig ki_sig_printable
+
+ name_doc = pprPrefixIfDeclBndr (ss_how_much ss) (occName tycon)
+
add_bars [] = Outputable.empty
add_bars (c:cs) = sep ((equals <+> c) : map (vbar <+>) cs)
@@ -801,8 +831,11 @@ pprIfaceDecl ss (IfaceClass { ifName = clas
, ifBinders = binders
, ifBody = IfAbstractClass })
= vcat [ pprClassRoles ss clas binders roles
- , text "class" <+> pprIfaceDeclHead [] ss clas binders Nothing
- <+> pprFundeps fds ]
+ , pprClassStandaloneKindSig ss clas (mkIfaceTyConKind binders constraintIfaceKind)
+ , text "class" <+> pprIfaceDeclHead suppress_bndr_sig [] ss clas binders <+> pprFundeps fds ]
+ where
+ -- See Note [Suppressing binder signatures] in IfaceType
+ suppress_bndr_sig = SuppressBndrSig True
pprIfaceDecl ss (IfaceClass { ifName = clas
, ifRoles = roles
@@ -815,8 +848,8 @@ pprIfaceDecl ss (IfaceClass { ifName = clas
ifMinDef = minDef
}})
= vcat [ pprClassRoles ss clas binders roles
- , text "class" <+> pprIfaceDeclHead context ss clas binders Nothing
- <+> pprFundeps fds <+> pp_where
+ , pprClassStandaloneKindSig ss clas (mkIfaceTyConKind binders constraintIfaceKind)
+ , text "class" <+> pprIfaceDeclHead suppress_bndr_sig context ss clas binders <+> pprFundeps fds <+> pp_where
, nest 2 (vcat [ vcat asocs, vcat dsigs
, ppShowAllSubs ss (pprMinDef minDef)])]
where
@@ -842,31 +875,46 @@ pprIfaceDecl ss (IfaceClass { ifName = clas
(\_ def -> cparen (isLexSym def) (ppr def)) 0 minDef <+>
text "#-}"
+ -- See Note [Suppressing binder signatures] in IfaceType
+ suppress_bndr_sig = SuppressBndrSig True
+
pprIfaceDecl ss (IfaceSynonym { ifName = tc
, ifBinders = binders
, ifSynRhs = mono_ty
, ifResKind = res_kind})
- = hang (text "type" <+> pprIfaceDeclHead [] ss tc binders Nothing <+> equals)
- 2 (sep [ pprIfaceForAll tvs, pprIfaceContextArr theta, ppr tau
- , ppUnless (isIfaceLiftedTypeKind res_kind) (dcolon <+> ppr res_kind) ])
+ = vcat [ pprStandaloneKindSig name_doc (mkIfaceTyConKind binders res_kind)
+ , hang (text "type" <+> pprIfaceDeclHead suppress_bndr_sig [] ss tc binders <+> equals)
+ 2 (sep [ pprIfaceForAll tvs, pprIfaceContextArr theta, ppr tau
+ , ppUnless (isIfaceLiftedTypeKind res_kind) (dcolon <+> ppr res_kind) ])
+ ]
where
(tvs, theta, tau) = splitIfaceSigmaTy mono_ty
+ name_doc = pprPrefixIfDeclBndr (ss_how_much ss) (occName tc)
+
+ -- See Note [Suppressing binder signatures] in IfaceType
+ suppress_bndr_sig = SuppressBndrSig True
pprIfaceDecl ss (IfaceFamily { ifName = tycon
, ifFamFlav = rhs, ifBinders = binders
, ifResKind = res_kind
, ifResVar = res_var, ifFamInj = inj })
| IfaceDataFamilyTyCon <- rhs
- = text "data family" <+> pprIfaceDeclHead [] ss tycon binders Nothing
+ = vcat [ pprStandaloneKindSig name_doc (mkIfaceTyConKind binders res_kind)
+ , text "data family" <+> pprIfaceDeclHead suppress_bndr_sig [] ss tycon binders
+ ]
| otherwise
- = hang (text "type family"
- <+> pprIfaceDeclHead [] ss tycon binders (Just res_kind)
- <+> ppShowRhs ss (pp_where rhs))
- 2 (pp_inj res_var inj <+> ppShowRhs ss (pp_rhs rhs))
- $$
- nest 2 (ppShowRhs ss (pp_branches rhs))
+ = vcat [ pprStandaloneKindSig name_doc (mkIfaceTyConKind binders res_kind)
+ , hang (text "type family"
+ <+> pprIfaceDeclHead suppress_bndr_sig [] ss tycon binders
+ <+> ppShowRhs ss (pp_where rhs))
+ 2 (pp_inj res_var inj <+> ppShowRhs ss (pp_rhs rhs))
+ $$
+ nest 2 (ppShowRhs ss (pp_branches rhs))
+ ]
where
+ name_doc = pprPrefixIfDeclBndr (ss_how_much ss) (occName tycon)
+
pp_where (IfaceClosedSynFamilyTyCon {}) = text "where"
pp_where _ = empty
@@ -900,6 +948,9 @@ pprIfaceDecl ss (IfaceFamily { ifName = tycon
$$ ppShowIface ss (text "axiom" <+> ppr ax)
pp_branches _ = Outputable.empty
+ -- See Note [Suppressing binder signatures] in IfaceType
+ suppress_bndr_sig = SuppressBndrSig True
+
pprIfaceDecl _ (IfacePatSyn { ifName = name,
ifPatUnivBndrs = univ_bndrs, ifPatExBndrs = ex_bndrs,
ifPatProvCtxt = prov_ctxt, ifPatReqCtxt = req_ctxt,
@@ -948,6 +999,9 @@ pprRoles suppress_if tyCon bndrs roles
in ppUnless (all suppress_if froles || null froles) $
text "type role" <+> tyCon <+> hsep (map ppr froles)
+pprStandaloneKindSig :: SDoc -> IfaceType -> SDoc
+pprStandaloneKindSig tyCon ty = text "type" <+> tyCon <+> text "::" <+> ppr ty
+
pprInfixIfDeclBndr :: ShowHowMuch -> OccName -> SDoc
pprInfixIfDeclBndr (ShowSome _ (AltPpr (Just ppr_bndr))) name
= pprInfixVar (isSymOcc name) (ppr_bndr name)
@@ -998,16 +1052,16 @@ pprIfaceTyConParent IfNoParent
pprIfaceTyConParent (IfDataInstance _ tc tys)
= pprIfaceTypeApp topPrec tc tys
-pprIfaceDeclHead :: IfaceContext -> ShowSub -> Name
+pprIfaceDeclHead :: SuppressBndrSig
+ -> IfaceContext -> ShowSub -> Name
-> [IfaceTyConBinder] -- of the tycon, for invisible-suppression
- -> Maybe IfaceKind
-> SDoc
-pprIfaceDeclHead context ss tc_occ bndrs m_res_kind
+pprIfaceDeclHead suppress_sig context ss tc_occ bndrs
= sdocWithDynFlags $ \ dflags ->
sep [ pprIfaceContextArr context
, pprPrefixIfDeclBndr (ss_how_much ss) (occName tc_occ)
- <+> pprIfaceTyConBinders (suppressIfaceInvisibles dflags bndrs bndrs)
- , maybe empty (\res_kind -> dcolon <+> pprIfaceType res_kind) m_res_kind ]
+ <+> pprIfaceTyConBinders suppress_sig
+ (suppressIfaceInvisibles dflags bndrs bndrs) ]
pprIfaceConDecl :: ShowSub -> Bool
-> IfaceTopBndr
diff --git a/compiler/iface/IfaceType.hs b/compiler/iface/IfaceType.hs
index 9e7021bcc9..e3362b7a68 100644
--- a/compiler/iface/IfaceType.hs
+++ b/compiler/iface/IfaceType.hs
@@ -24,6 +24,7 @@ module IfaceType (
IfaceForAllBndr, ArgFlag(..), AnonArgFlag(..),
ForallVisFlag(..), ShowForAllFlag(..),
mkIfaceForAllTvBndr,
+ mkIfaceTyConKind,
ifForAllBndrVar, ifForAllBndrName, ifaceBndrName,
ifTyConBinderVar, ifTyConBinderName,
@@ -35,6 +36,8 @@ module IfaceType (
appArgsIfaceTypes, appArgsIfaceTypesArgFlags,
-- Printing
+ SuppressBndrSig(..),
+ UseBndrParens(..),
pprIfaceType, pprParendIfaceType, pprPrecIfaceType,
pprIfaceContext, pprIfaceContextArr,
pprIfaceIdBndr, pprIfaceLamBndr, pprIfaceTvBndr, pprIfaceTyConBinders,
@@ -44,6 +47,7 @@ module IfaceType (
pprIfaceCoercion, pprParendIfaceCoercion,
splitIfaceSigmaTy, pprIfaceTypeApp, pprUserIfaceForAll,
pprIfaceCoTcApp, pprTyTcApp, pprIfacePrefixApp,
+ isIfaceTauType,
suppressIfaceInvisibles,
stripIfaceInvisVars,
@@ -106,6 +110,10 @@ ifaceBndrName :: IfaceBndr -> IfLclName
ifaceBndrName (IfaceTvBndr bndr) = ifaceTvBndrName bndr
ifaceBndrName (IfaceIdBndr bndr) = ifaceIdBndrName bndr
+ifaceBndrType :: IfaceBndr -> IfaceType
+ifaceBndrType (IfaceIdBndr (_, t)) = t
+ifaceBndrType (IfaceTvBndr (_, t)) = t
+
type IfaceLamBndr = (IfaceBndr, IfaceOneShot)
data IfaceOneShot -- See Note [Preserve OneShotInfo] in CoreTicy
@@ -164,6 +172,15 @@ type IfaceForAllBndr = VarBndr IfaceBndr ArgFlag
mkIfaceForAllTvBndr :: ArgFlag -> IfaceTvBndr -> IfaceForAllBndr
mkIfaceForAllTvBndr vis var = Bndr (IfaceTvBndr var) vis
+-- | Build the 'tyConKind' from the binders and the result kind.
+-- Keep in sync with 'mkTyConKind' in types/TyCon.
+mkIfaceTyConKind :: [IfaceTyConBinder] -> IfaceKind -> IfaceKind
+mkIfaceTyConKind bndrs res_kind = foldr mk res_kind bndrs
+ where
+ mk :: IfaceTyConBinder -> IfaceKind -> IfaceKind
+ mk (Bndr tv (AnonTCB af)) k = IfaceFunTy af (ifaceBndrType tv) k
+ mk (Bndr tv (NamedTCB vis)) k = IfaceForAllTy (Bndr tv vis) k
+
-- | Stores the arguments in a type application as a list.
-- See @Note [Suppressing invisible arguments]@.
data IfaceAppArgs
@@ -686,11 +703,17 @@ pprIfacePrefixApp ctxt_prec pp_fun pp_tys
| otherwise = maybeParen ctxt_prec appPrec $
hang pp_fun 2 (sep pp_tys)
+isIfaceTauType :: IfaceType -> Bool
+isIfaceTauType (IfaceForAllTy _ _) = False
+isIfaceTauType (IfaceFunTy InvisArg _ _) = False
+isIfaceTauType _ = True
+
-- ----------------------------- Printing binders ------------------------------------
instance Outputable IfaceBndr where
ppr (IfaceIdBndr bndr) = pprIfaceIdBndr bndr
- ppr (IfaceTvBndr bndr) = char '@' <+> pprIfaceTvBndr False bndr
+ ppr (IfaceTvBndr bndr) = char '@' <+> pprIfaceTvBndr bndr (SuppressBndrSig False)
+ (UseBndrParens False)
pprIfaceBndrs :: [IfaceBndr] -> SDoc
pprIfaceBndrs bs = sep (map ppr bs)
@@ -702,31 +725,60 @@ pprIfaceLamBndr (b, IfaceOneShot) = ppr b <> text "[OneShot]"
pprIfaceIdBndr :: IfaceIdBndr -> SDoc
pprIfaceIdBndr (name, ty) = parens (ppr name <+> dcolon <+> ppr ty)
-pprIfaceTvBndr :: Bool -> IfaceTvBndr -> SDoc
-pprIfaceTvBndr use_parens (tv, ki)
+{- Note [Suppressing binder signatures]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+When printing the binders in a 'forall', we want to keep the kind annotations:
+
+ forall (a :: k). blah
+ ^^^^
+ good
+
+On the other hand, when we print the binders of a data declaration in :info,
+the kind information would be redundant due to the standalone kind signature:
+
+ type F :: Symbol -> Type
+ type F (s :: Symbol) = blah
+ ^^^^^^^^^
+ redundant
+
+Here we'd like to omit the kind annotation:
+
+ type F :: Symbol -> Type
+ type F s = blah
+-}
+
+-- | Do we want to suppress kind annotations on binders?
+-- See Note [Suppressing binder signatures]
+newtype SuppressBndrSig = SuppressBndrSig Bool
+
+newtype UseBndrParens = UseBndrParens Bool
+
+pprIfaceTvBndr :: IfaceTvBndr -> SuppressBndrSig -> UseBndrParens -> SDoc
+pprIfaceTvBndr (tv, ki) (SuppressBndrSig suppress_sig) (UseBndrParens use_parens)
+ | suppress_sig = ppr tv
| isIfaceLiftedTypeKind ki = ppr tv
| otherwise = maybe_parens (ppr tv <+> dcolon <+> ppr ki)
where
maybe_parens | use_parens = parens
| otherwise = id
-pprIfaceTyConBinders :: [IfaceTyConBinder] -> SDoc
-pprIfaceTyConBinders = sep . map go
+pprIfaceTyConBinders :: SuppressBndrSig -> [IfaceTyConBinder] -> SDoc
+pprIfaceTyConBinders suppress_sig = sep . map go
where
go :: IfaceTyConBinder -> SDoc
go (Bndr (IfaceIdBndr bndr) _) = pprIfaceIdBndr bndr
go (Bndr (IfaceTvBndr bndr) vis) =
-- See Note [Pretty-printing invisible arguments]
case vis of
- AnonTCB VisArg -> ppr_bndr True
- AnonTCB InvisArg -> char '@' <> braces (ppr_bndr False)
+ AnonTCB VisArg -> ppr_bndr (UseBndrParens True)
+ AnonTCB InvisArg -> char '@' <> braces (ppr_bndr (UseBndrParens False))
-- The above case is rare. (See Note [AnonTCB InvisArg] in TyCon.)
-- Should we print these differently?
- NamedTCB Required -> ppr_bndr True
- NamedTCB Specified -> char '@' <> ppr_bndr True
- NamedTCB Inferred -> char '@' <> braces (ppr_bndr False)
+ NamedTCB Required -> ppr_bndr (UseBndrParens True)
+ NamedTCB Specified -> char '@' <> ppr_bndr (UseBndrParens True)
+ NamedTCB Inferred -> char '@' <> braces (ppr_bndr (UseBndrParens False))
where
- ppr_bndr use_parens = pprIfaceTvBndr use_parens bndr
+ ppr_bndr = pprIfaceTvBndr bndr suppress_sig
instance Binary IfaceBndr where
put_ bh (IfaceIdBndr aa) = do
@@ -1045,13 +1097,19 @@ pprIfaceForAllCoBndrs :: [(IfLclName, IfaceCoercion)] -> SDoc
pprIfaceForAllCoBndrs bndrs = hsep $ map pprIfaceForAllCoBndr bndrs
pprIfaceForAllBndr :: IfaceForAllBndr -> SDoc
-pprIfaceForAllBndr (Bndr (IfaceTvBndr tv) Inferred)
- = sdocWithDynFlags $ \dflags ->
- if gopt Opt_PrintExplicitForalls dflags
- then braces $ pprIfaceTvBndr False tv
- else pprIfaceTvBndr True tv
-pprIfaceForAllBndr (Bndr (IfaceTvBndr tv) _) = pprIfaceTvBndr True tv
-pprIfaceForAllBndr (Bndr (IfaceIdBndr idv) _) = pprIfaceIdBndr idv
+pprIfaceForAllBndr bndr =
+ case bndr of
+ Bndr (IfaceTvBndr tv) Inferred ->
+ sdocWithDynFlags $ \dflags ->
+ if gopt Opt_PrintExplicitForalls dflags
+ then braces $ pprIfaceTvBndr tv suppress_sig (UseBndrParens False)
+ else pprIfaceTvBndr tv suppress_sig (UseBndrParens True)
+ Bndr (IfaceTvBndr tv) _ ->
+ pprIfaceTvBndr tv suppress_sig (UseBndrParens True)
+ Bndr (IfaceIdBndr idv) _ -> pprIfaceIdBndr idv
+ where
+ -- See Note [Suppressing binder signatures] in IfaceType
+ suppress_sig = SuppressBndrSig False
pprIfaceForAllCoBndr :: (IfLclName, IfaceCoercion) -> SDoc
pprIfaceForAllCoBndr (tv, kind_co)