summaryrefslogtreecommitdiff
path: root/compiler
diff options
context:
space:
mode:
Diffstat (limited to 'compiler')
-rw-r--r--compiler/basicTypes/BasicTypes.hs57
-rw-r--r--compiler/hsSyn/HsTypes.hs4
-rw-r--r--compiler/iface/IfaceType.hs87
-rw-r--r--compiler/typecheck/TcErrors.hs2
-rw-r--r--compiler/typecheck/TcType.hs2
-rw-r--r--compiler/types/TyCoRep.hs32
-rw-r--r--compiler/types/Type.hs3
7 files changed, 124 insertions, 63 deletions
diff --git a/compiler/basicTypes/BasicTypes.hs b/compiler/basicTypes/BasicTypes.hs
index b67e6628ee..90a043de76 100644
--- a/compiler/basicTypes/BasicTypes.hs
+++ b/compiler/basicTypes/BasicTypes.hs
@@ -700,13 +700,68 @@ data TyPrec -- See Note [Precedence in types] in TyCoRep.hs
| FunPrec -- Function args; no parens for tycon apps
| TyOpPrec -- Infix operator
| TyConPrec -- Tycon args; no parens for atomic
- deriving( Eq, Ord )
+
+instance Eq TyPrec where
+ (==) a b = case compare a b of
+ EQ -> True
+ _ -> False
+
+instance Ord TyPrec where
+ compare TopPrec TopPrec = EQ
+ compare TopPrec _ = LT
+
+ compare FunPrec TopPrec = GT
+ compare FunPrec FunPrec = EQ
+ compare FunPrec TyOpPrec = EQ -- See Note [Type operator precedence]
+ compare FunPrec TyConPrec = LT
+
+ compare TyOpPrec TopPrec = GT
+ compare TyOpPrec FunPrec = EQ -- See Note [Type operator precedence]
+ compare TyOpPrec TyOpPrec = EQ
+ compare TyOpPrec TyConPrec = LT
+
+ compare TyConPrec TyConPrec = EQ
+ compare TyConPrec _ = GT
maybeParen :: TyPrec -> TyPrec -> SDoc -> SDoc
maybeParen ctxt_prec inner_prec pretty
| ctxt_prec < inner_prec = pretty
| otherwise = parens pretty
+{- Note [Precedence in types]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Many pretty-printing functions have type
+ ppr_ty :: TyPrec -> Type -> SDoc
+
+The TyPrec gives the binding strength of the context. For example, in
+ T ty1 ty2
+we will pretty-print 'ty1' and 'ty2' with the call
+ (ppr_ty TyConPrec ty)
+to indicate that the context is that of an argument of a TyConApp.
+
+We use this consistently for Type and HsType.
+
+Note [Type operator precedence]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+We don't keep the fixity of type operators in the operator. So the
+pretty printer follows the following precedence order:
+
+ TyConPrec Type constructor application
+ TyOpPrec/FunPrec Operator application and function arrow
+
+We have FunPrec and TyOpPrec to represent the precedence of function
+arrow and type operators respectively, but currently we implement
+FunPred == TyOpPrec, so that we don't distinguish the two. Reason:
+it's hard to parse a type like
+ a ~ b => c * d -> e - f
+
+By treating TyOpPrec = FunPrec we end up with more parens
+ (a ~ b) => (c * d) -> (e - f)
+
+But the two are different constructors of TyPrec so we could make
+(->) bind more or less tightly if we wanted.
+-}
+
{-
************************************************************************
* *
diff --git a/compiler/hsSyn/HsTypes.hs b/compiler/hsSyn/HsTypes.hs
index 8ea6b0b3a0..2144a28597 100644
--- a/compiler/hsSyn/HsTypes.hs
+++ b/compiler/hsSyn/HsTypes.hs
@@ -1286,7 +1286,7 @@ ppr_mono_ty _ (HsListTy ty) = brackets (ppr_mono_lty TopPrec ty)
ppr_mono_ty _ (HsPArrTy ty) = paBrackets (ppr_mono_lty TopPrec ty)
ppr_mono_ty prec (HsIParamTy n ty) = maybeParen prec FunPrec (ppr n <+> dcolon <+> ppr_mono_lty TopPrec ty)
ppr_mono_ty _ (HsSpliceTy s _) = pprSplice s
-ppr_mono_ty _ (HsCoreTy ty) = ppr ty
+ppr_mono_ty prec (HsCoreTy ty) = pprPrecType prec ty
ppr_mono_ty _ (HsExplicitListTy Promoted _ tys)
= quote $ brackets (interpp'SP tys)
ppr_mono_ty _ (HsExplicitListTy NotPromoted _ tys)
@@ -1300,7 +1300,7 @@ ppr_mono_ty ctxt_prec (HsEqTy ty1 ty2)
ppr_mono_lty TyOpPrec ty1 <+> char '~' <+> ppr_mono_lty TyOpPrec ty2
ppr_mono_ty _ctxt_prec (HsAppsTy tys)
- = hsep (map (ppr_app_ty TopPrec . unLoc) tys)
+ = hsep (map (ppr_app_ty TyConPrec . unLoc) tys)
ppr_mono_ty _ctxt_prec (HsAppTy fun_ty arg_ty)
= hsep [ppr_mono_lty FunPrec fun_ty, ppr_mono_lty TyConPrec arg_ty]
diff --git a/compiler/iface/IfaceType.hs b/compiler/iface/IfaceType.hs
index 95d6369d45..39e30283db 100644
--- a/compiler/iface/IfaceType.hs
+++ b/compiler/iface/IfaceType.hs
@@ -30,7 +30,7 @@ module IfaceType (
tcArgsIfaceTypes,
-- Printing
- pprIfaceType, pprParendIfaceType,
+ pprIfaceType, pprParendIfaceType, pprPrecIfaceType,
pprIfaceContext, pprIfaceContextArr,
pprIfaceIdBndr, pprIfaceLamBndr, pprIfaceTvBndr, pprIfaceTyConBinders,
pprIfaceBndrs, pprIfaceTcArgs, pprParendIfaceTcArgs,
@@ -227,6 +227,7 @@ Namely we handle these cases,
eqPrimTyCon ~# ~~
eqReprPrimTyCon Coercible Coercible
+See Note [The equality types story] in TysPrim.
-}
data IfaceTyConInfo -- Used to guide pretty-printing
@@ -492,15 +493,15 @@ if_print_coercions yes no
then yes
else no
-pprIfaceInfixApp :: (TyPrec -> a -> SDoc) -> TyPrec -> SDoc -> a -> a -> SDoc
-pprIfaceInfixApp pp p pp_tc ty1 ty2
- = maybeParen p FunPrec $
- sep [pp FunPrec ty1, pprInfixVar True pp_tc <+> pp FunPrec ty2]
+pprIfaceInfixApp :: TyPrec -> SDoc -> SDoc -> SDoc -> SDoc
+pprIfaceInfixApp ctxt_prec pp_tc pp_ty1 pp_ty2
+ = maybeParen ctxt_prec TyOpPrec $
+ sep [pp_ty1, pp_tc <+> pp_ty2]
pprIfacePrefixApp :: TyPrec -> SDoc -> [SDoc] -> SDoc
-pprIfacePrefixApp p pp_fun pp_tys
+pprIfacePrefixApp ctxt_prec pp_fun pp_tys
| null pp_tys = pp_fun
- | otherwise = maybeParen p TyConPrec $
+ | otherwise = maybeParen ctxt_prec TyConPrec $
hang pp_fun 2 (sep pp_tys)
-- ----------------------------- Printing binders ------------------------------------
@@ -565,8 +566,11 @@ instance Outputable IfaceType where
ppr ty = pprIfaceType ty
pprIfaceType, pprParendIfaceType :: IfaceType -> SDoc
-pprIfaceType = eliminateRuntimeRep (ppr_ty TopPrec)
-pprParendIfaceType = eliminateRuntimeRep (ppr_ty TyConPrec)
+pprIfaceType = pprPrecIfaceType TopPrec
+pprParendIfaceType = pprPrecIfaceType TyConPrec
+
+pprPrecIfaceType :: TyPrec -> IfaceType -> SDoc
+pprPrecIfaceType prec ty = eliminateRuntimeRep (ppr_ty prec) ty
ppr_ty :: TyPrec -> IfaceType -> SDoc
ppr_ty _ (IfaceFreeTyVar tyvar) = ppr tyvar -- This is the main reson for IfaceFreeTyVar!
@@ -880,8 +884,8 @@ pprTyTcApp' ctxt_prec tc tys dflags style
-- Suppress detail unles you _really_ want to see
-> text "(TypeError ...)"
- | Just doc <- ppr_equality tc (tcArgsIfaceTypes tys)
- -> maybeParen ctxt_prec TyConPrec doc
+ | Just doc <- ppr_equality ctxt_prec tc (tcArgsIfaceTypes tys)
+ -> doc
| otherwise
-> ppr_iface_tc_app ppr_ty ctxt_prec tc tys_wo_kinds
@@ -891,9 +895,10 @@ pprTyTcApp' ctxt_prec tc tys dflags style
-- | Pretty-print a type-level equality.
--
--- See Note [Equality predicates in IfaceType].
-ppr_equality :: IfaceTyCon -> [IfaceType] -> Maybe SDoc
-ppr_equality tc args
+-- See Note [Equality predicates in IfaceType]
+-- and Note [The equality types story] in TysPrim
+ppr_equality :: TyPrec -> IfaceTyCon -> [IfaceType] -> Maybe SDoc
+ppr_equality ctxt_prec tc args
| hetero_eq_tc
, [k1, k2, t1, t2] <- args
= Just $ print_equality (k1, k2, t1, t2)
@@ -914,11 +919,10 @@ ppr_equality tc args
hetero_eq_tc = tc_name `hasKey` eqPrimTyConKey -- (~#)
|| tc_name `hasKey` eqReprPrimTyConKey -- (~R#)
|| tc_name `hasKey` heqTyConKey -- (~~)
-
print_equality args =
- sdocWithDynFlags
- $ \dflags -> getPprStyle
- $ \style -> print_equality' args style dflags
+ sdocWithDynFlags $ \dflags ->
+ getPprStyle $ \style ->
+ print_equality' args style dflags
print_equality' (ki1, ki2, ty1, ty2) style dflags
| print_eqs
@@ -930,14 +934,15 @@ ppr_equality tc args
| otherwise
= if tc_name `hasKey` eqReprPrimTyConKey
- then text "Coercible"
- <+> sep [ pp TyConPrec ty1, pp TyConPrec ty2 ]
- else sep [pp TyOpPrec ty1, char '~', pp TyOpPrec ty2]
+ then pprIfacePrefixApp ctxt_prec (text "Coercible")
+ [pp TyConPrec ty1, pp TyConPrec ty2]
+ else pprIfaceInfixApp ctxt_prec (char '~')
+ (pp TyOpPrec ty1) (pp TyOpPrec ty2)
where
ppr_infix_eq eq_op
- = sep [ parens (pp TyOpPrec ty1 <+> dcolon <+> pp TyOpPrec ki1)
- , eq_op
- , parens (pp TyOpPrec ty2 <+> dcolon <+> pp TyOpPrec ki2) ]
+ = pprIfaceInfixApp ctxt_prec eq_op
+ (parens (pp TopPrec ty1 <+> dcolon <+> pp TyOpPrec ki1))
+ (parens (pp TopPrec ty2 <+> dcolon <+> pp TyOpPrec ki2))
print_kinds = gopt Opt_PrintExplicitKinds dflags
print_eqs = gopt Opt_PrintEqualityRelations dflags ||
@@ -963,7 +968,8 @@ ppr_iface_tc_app pp ctxt_prec tc tys
| [ty1,ty2] <- tys -- Infix, two arguments;
-- we know nothing of precedence though
- = pprIfaceInfixApp pp ctxt_prec (ppr tc) ty1 ty2
+ = pprIfaceInfixApp ctxt_prec (ppr tc)
+ (pp TyOpPrec ty1) (pp TyOpPrec ty2)
| otherwise
= pprIfacePrefixApp ctxt_prec (parens (ppr tc)) (map (pp TyConPrec) tys)
@@ -1024,7 +1030,8 @@ ppr_co ctxt_prec (IfaceAppCo co1 co2)
= maybeParen ctxt_prec TyConPrec $
ppr_co FunPrec co1 <+> pprParendIfaceCoercion co2
ppr_co ctxt_prec co@(IfaceForAllCo {})
- = maybeParen ctxt_prec FunPrec (pprIfaceForAllCoPart tvs (pprIfaceCoercion inner_co))
+ = maybeParen ctxt_prec FunPrec $
+ pprIfaceForAllCoPart tvs (pprIfaceCoercion inner_co)
where
(tvs, inner_co) = split_co co
@@ -1208,20 +1215,24 @@ instance Binary IfaceTcArgs where
--- | Prints "(C a, D b) =>", including the arrow. This is used when we want to
--- print a context in a type.
+-- | Prints "(C a, D b) =>", including the arrow.
+-- Used when we want to print a context in a type, so we
+-- use FunPrec to decide whether to parenthesise a singleton
+-- predicate; e.g. Num a => a -> a
pprIfaceContextArr :: [IfacePredType] -> SDoc
pprIfaceContextArr [] = empty
-pprIfaceContextArr [pred] = ppr_ty TyOpPrec pred <+> darrow
-pprIfaceContextArr preds =
- parens (fsep (punctuate comma (map ppr preds))) <+> darrow
-
--- | Prints a context or @()@ if empty. This is used when, e.g., we want to
--- display a context in an error message.
-pprIfaceContext :: [IfacePredType] -> SDoc
-pprIfaceContext [] = parens empty
-pprIfaceContext [pred] = ppr_ty TyOpPrec pred
-pprIfaceContext preds = parens (fsep (punctuate comma (map ppr preds)))
+pprIfaceContextArr [pred] = ppr_ty FunPrec pred <+> darrow
+pprIfaceContextArr preds = ppr_parend_preds preds <+> darrow
+
+-- | Prints a context or @()@ if empty
+-- You give it the context precedence
+pprIfaceContext :: TyPrec -> [IfacePredType] -> SDoc
+pprIfaceContext _ [] = text "()"
+pprIfaceContext prec [pred] = ppr_ty prec pred
+pprIfaceContext _ preds = ppr_parend_preds preds
+
+ppr_parend_preds :: [IfacePredType] -> SDoc
+ppr_parend_preds preds = parens (fsep (punctuate comma (map ppr preds)))
instance Binary IfaceType where
put_ _ (IfaceFreeTyVar tv)
diff --git a/compiler/typecheck/TcErrors.hs b/compiler/typecheck/TcErrors.hs
index c9e07fc43d..6d422a4c44 100644
--- a/compiler/typecheck/TcErrors.hs
+++ b/compiler/typecheck/TcErrors.hs
@@ -1236,7 +1236,7 @@ mkIPErr ctxt cts
msg | null givens
= addArising orig $
sep [ text "Unbound implicit parameter" <> plural cts
- , nest 2 (pprTheta preds) ]
+ , nest 2 (pprParendTheta preds) ]
| otherwise
= couldNotDeduce givens (preds, orig)
diff --git a/compiler/typecheck/TcType.hs b/compiler/typecheck/TcType.hs
index e22dfc3822..e12b70b6d1 100644
--- a/compiler/typecheck/TcType.hs
+++ b/compiler/typecheck/TcType.hs
@@ -183,7 +183,7 @@ module TcType (
pprKind, pprParendKind, pprSigmaType,
pprType, pprParendType, pprTypeApp, pprTyThingCategory, tyThingCategory,
- pprTheta, pprThetaArrowTy, pprClassPred,
+ pprTheta, pprParendTheta, pprThetaArrowTy, pprClassPred,
pprTvBndr, pprTvBndrs,
TypeSize, sizeType, sizeTypes, toposortTyVars
diff --git a/compiler/types/TyCoRep.hs b/compiler/types/TyCoRep.hs
index 300ef80a8f..74ebfbeb9a 100644
--- a/compiler/types/TyCoRep.hs
+++ b/compiler/types/TyCoRep.hs
@@ -55,9 +55,10 @@ module TyCoRep (
pickLR,
-- * Pretty-printing
- pprType, pprParendType, pprTypeApp, pprTvBndr, pprTvBndrs,
+ pprType, pprParendType, pprPrecType,
+ pprTypeApp, pprTvBndr, pprTvBndrs,
pprSigmaType,
- pprTheta, pprForAll, pprUserForAll,
+ pprTheta, pprParendTheta, pprForAll, pprUserForAll,
pprTyVar, pprTyVars,
pprThetaArrowTy, pprClassPred,
pprKind, pprParendKind, pprTyLit,
@@ -2424,27 +2425,17 @@ defined to use this. @pprParendType@ is the same, except it puts
parens around the type, except for the atomic cases. @pprParendType@
works just by setting the initial context precedence very high.
-Note [Precedence in types]
-~~~~~~~~~~~~~~~~~~~~~~~~~~
-We don't keep the fixity of type operators in the operator. So the pretty printer
-follows the following precedence order:
- Type constructor application binds more tightly than
- Operator applications which bind more tightly than
- Function arrow
-
-So we might see a :+: T b -> c
-meaning (a :+: (T b)) -> c
-
-Maybe operator applications should bind a bit less tightly?
-
-Anyway, that's the current story; it is used consistently for Type and HsType.
+See Note [Precedence in types] in BasicTypes.
-}
------------------
pprType, pprParendType :: Type -> SDoc
-pprType = pprIfaceType . tidyToIfaceType
-pprParendType = pprParendIfaceType . tidyToIfaceType
+pprType = pprPrecType TopPrec
+pprParendType = pprPrecType TyConPrec
+
+pprPrecType :: TyPrec -> Type -> SDoc
+pprPrecType prec ty = pprPrecIfaceType prec (tidyToIfaceType ty)
pprTyLit :: TyLit -> SDoc
pprTyLit = pprIfaceTyLit . toIfaceTyLit
@@ -2471,7 +2462,10 @@ pprClassPred clas tys = pprTypeApp (classTyCon clas) tys
------------
pprTheta :: ThetaType -> SDoc
-pprTheta = pprIfaceContext . map tidyToIfaceType
+pprTheta = pprIfaceContext TopPrec . map tidyToIfaceType
+
+pprParendTheta :: ThetaType -> SDoc
+pprParendTheta = pprIfaceContext TyConPrec . map tidyToIfaceType
pprThetaArrowTy :: ThetaType -> SDoc
pprThetaArrowTy = pprIfaceContextArr . map tidyToIfaceType
diff --git a/compiler/types/Type.hs b/compiler/types/Type.hs
index 7750a35072..65c02ba719 100644
--- a/compiler/types/Type.hs
+++ b/compiler/types/Type.hs
@@ -182,7 +182,8 @@ module Type (
cloneTyVarBndr, cloneTyVarBndrs, lookupTyVar,
-- * Pretty-printing
- pprType, pprParendType, pprTypeApp, pprTyThingCategory, pprShortTyThing,
+ pprType, pprParendType, pprPrecType,
+ pprTypeApp, pprTyThingCategory, pprShortTyThing,
pprTvBndr, pprTvBndrs, pprForAll, pprUserForAll,
pprSigmaType, ppSuggestExplicitKinds,
pprTheta, pprThetaArrowTy, pprClassPred,