Skip to content
This repository was archived by the owner on Aug 3, 2024. It is now read-only.

Commit c3eb3f0

Browse files
sjakobialexbiehl
authored andcommitted
tyThingToLHsDecl: Preserve type synonyms that contain a forall (#880)
* tyThingToLHsDecls: Preserve type synonyms that contain a forall Fixes #879. * Add Note [Invariant: Never expand type synonyms] * Clarify Note [Invariant: Never expand type synonyms]
1 parent 657b1b3 commit c3eb3f0

File tree

1 file changed

+46
-2
lines changed

1 file changed

+46
-2
lines changed

haddock-api/src/Haddock/Convert.hs

Lines changed: 46 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ import NameSet ( emptyNameSet )
3131
import RdrName ( mkVarUnqual )
3232
import PatSyn
3333
import SrcLoc ( Located, noLoc, unLoc, GenLocated(..), srcLocSpan )
34-
import TcType ( tcSplitSigmaTy )
34+
import TcType
3535
import TyCon
3636
import Type
3737
import TyCoRep
@@ -515,7 +515,7 @@ synifyType _ (FunTy t1 t2) = let
515515
s2 = synifyType WithinType t2
516516
in noLoc $ HsFunTy s1 s2
517517
synifyType s forallty@(ForAllTy _tv _ty) =
518-
let (tvs, ctx, tau) = tcSplitSigmaTy forallty
518+
let (tvs, ctx, tau) = tcSplitSigmaTyPreserveSynonyms forallty
519519
sPhi = HsQualTy { hst_ctxt = synifyCtx ctx
520520
, hst_body = synifyType WithinType tau }
521521
in case s of
@@ -610,3 +610,47 @@ synifyFamInst fi opaque = do
610610
ts' = synifyTypes ts
611611
annot_ts = zipWith3 annotHsType is_poly_tvs ts ts'
612612
is_poly_tvs = mkIsPolyTvs (tyConVisibleTyVars fam_tc)
613+
614+
{-
615+
Note [Invariant: Never expand type synonyms]
616+
617+
In haddock, we never want to expand a type synonym that may be presented to the
618+
user, as we want to keep the link to the abstraction captured in the synonym.
619+
620+
All code in Haddock.Convert must make sure that this invariant holds.
621+
622+
See https://github.com/haskell/haddock/issues/879 for a bug where this
623+
invariant didn't hold.
624+
-}
625+
626+
-- | A version of 'TcType.tcSplitSigmaTy' that preserves type synonyms.
627+
--
628+
-- See Note [Invariant: Never expand type synonyms]
629+
tcSplitSigmaTyPreserveSynonyms :: Type -> ([TyVar], ThetaType, Type)
630+
tcSplitSigmaTyPreserveSynonyms ty =
631+
case tcSplitForAllTysPreserveSynonyms ty of
632+
(tvs, rho) -> case tcSplitPhiTyPreserveSynonyms rho of
633+
(theta, tau) -> (tvs, theta, tau)
634+
635+
-- | See Note [Invariant: Never expand type synonyms]
636+
tcSplitForAllTysPreserveSynonyms :: Type -> ([TyVar], Type)
637+
tcSplitForAllTysPreserveSynonyms ty = split ty ty []
638+
where
639+
split _ (ForAllTy (TvBndr tv _) ty') tvs = split ty' ty' (tv:tvs)
640+
split orig_ty _ tvs = (reverse tvs, orig_ty)
641+
642+
-- | See Note [Invariant: Never expand type synonyms]
643+
tcSplitPhiTyPreserveSynonyms :: Type -> (ThetaType, Type)
644+
tcSplitPhiTyPreserveSynonyms ty0 = split ty0 []
645+
where
646+
split ty ts
647+
= case tcSplitPredFunTyPreserveSynonyms_maybe ty of
648+
Just (pred_, ty') -> split ty' (pred_:ts)
649+
Nothing -> (reverse ts, ty)
650+
651+
-- | See Note [Invariant: Never expand type synonyms]
652+
tcSplitPredFunTyPreserveSynonyms_maybe :: Type -> Maybe (PredType, Type)
653+
tcSplitPredFunTyPreserveSynonyms_maybe (FunTy arg res)
654+
| isPredTy arg = Just (arg, res)
655+
tcSplitPredFunTyPreserveSynonyms_maybe _
656+
= Nothing

0 commit comments

Comments
 (0)