Opened 3 years ago

Closed 2 years ago

#13420 closed bug (fixed)

Bizarre pretty-printing of closed type families in GHCi

Reported by: RyanGlScott Owned by:
Priority: normal Milestone: 8.4.1
Component: GHCi Version: 8.0.2
Keywords: TypeFamilies Cc: goldfire
Operating System: Unknown/Multiple Architecture: Unknown/Multiple
Type of failure: None/Unknown Test Case:
Blocked By: Blocking:
Related Tickets: Differential Rev(s): Phab:D3497
Wiki Page:

Description

Load this code:

{-# LANGUAGE TypeFamilies #-}
module Bug where

type family F a where
  F [Int] = Bool
  F [a]   = Double
  F (a b) = Char

into GHCi 8.0.1, 8.0.2, or HEAD, and run :i F. You'll see this:

$ /opt/ghc/8.0.2/bin/ghci Bug.hs
GHCi, version 8.0.2: http://www.haskell.org/ghc/  :? for help
Loaded GHCi configuration from /home/rgscott/.ghci
[1 of 1] Compiling Bug              ( Bug.hs, interpreted )
Ok, modules loaded: Bug.
λ> :i F
type family F a :: *
  where
      F [Int] = Bool
    [a] F [a] = Double
    [b, (a :: * -> *)] F (a b) = Char
        -- Defined at Bug.hs:4:1

Compare this with GHCi 7.10.3, where the pretty-printing is far more sane:

$ /opt/ghc/7.10.3/bin/ghci Bug.hs
GHCi, version 7.10.3: http://www.haskell.org/ghc/  :? for help
[1 of 1] Compiling Bug              ( Bug.hs, interpreted )
Ok, modules loaded: Bug.
λ> :i F
type family F a :: * where
    F [Int] = Bool
    F [a] = Double
    F (a b) = Char
        -- Defined at Bug.hs:4:1

Change History (5)

comment:1 Changed 3 years ago by RyanGlScott

Cc: goldfire added

It looks like 6746549772c5cc0ac66c0fce562f297f4d4b80a2 (Kind equalities) is the culprit.

In particular, before that commit, you had to enable -fprint-explicit-foralls in order to see something like this. In GHCi 7.10.3:

GHCi, version 7.10.3: http://www.haskell.org/ghc/  :? for help
[1 of 1] Compiling Bug              ( ../Bug.hs, interpreted )
Ok, modules loaded: Bug.
λ> :set -fprint-explicit-foralls 
λ> :i F
type family F a :: * where
    F [Int] = Bool
  forall a. F [a] = Double
  forall (a :: * -> *) b. F (a b) = Char
        -- Defined at ../Bug.hs:4:1

But in GHC 8.0.1 and later, -fprint-explicit-foralls has no effect on the output. This part of the commit is responsible:

  • compiler/iface/IfaceSyn.hs

    diff --git a/compiler/iface/IfaceSyn.hs b/compiler/iface/IfaceSyn.hs
    index 307a448..247566c 100644 (file)
    a b pprAxBranch :: SDoc -> IfaceAxBranch -> SDoc 
    511511-- be a branch for an imported TyCon, so it would be an ExtName
    512512-- So it's easier to take an SDoc here
    513513pprAxBranch pp_tc (IfaceAxBranch { ifaxbTyVars = tvs
    514                                   , ifaxbLHS = pat_tys
    515                                   , ifaxbRHS = rhs
    516                                   , ifaxbIncomps = incomps })
    517   = hang (pprUserIfaceForAll tvs)
    518       2 (hang pp_lhs 2 (equals <+> ppr rhs))
     514                                 , ifaxbCoVars = cvs
     515                                 , ifaxbLHS = pat_tys
     516                                 , ifaxbRHS = rhs
     517                                 , ifaxbIncomps = incomps })
     518  = hang ppr_binders 2 (hang pp_lhs 2 (equals <+> ppr rhs))
    519519    $+$
    520520    nest 2 maybe_incomps
    521521  where
     522    ppr_binders
     523      | null tvs && null cvs = empty
     524      | null cvs             = brackets (pprWithCommas pprIfaceTvBndr tvs)
     525      | otherwise
     526      = brackets (pprWithCommas pprIfaceTvBndr tvs <> semi <+>
     527                  pprWithCommas pprIfaceIdBndr cvs)
    522528    pp_lhs = hang pp_tc 2 (pprParendIfaceTcArgs pat_tys)
    523529    maybe_incomps = ppUnless (null incomps) $ parens $
    524530                    ptext (sLit "incompatible indices:") <+> ppr incomps

Notice that we're not using pprUserIfaceForAll anymore (which consults -fprint-explicit-foralls), but instead we're using pprWithCommas, which causes the strange list-like output that we see today.

Richard, do you have a strong opinion on how closed type families should be rendered? My inclination would be to revert back to the old behavior, but maybe you had a reason for choosing this strategy.

comment:2 Changed 3 years ago by goldfire

I do remember that this change was intentional (that is, I'm not surprised by your report) but the reasons are cloudy. I'd be happy if the binders were printed only with -fprint-explicit-foralls and agree that doing so is an improvement.

comment:3 Changed 2 years ago by RyanGlScott

Differential Rev(s): Phab:D3497
Milestone: 8.4.1
Status: newpatch

comment:4 Changed 2 years ago by Ben Gamari <ben@…>

In da792e47/ghc:

Only pretty-print binders in closed type families with -fprint-explicit-foralls

Previously, we were unconditionally pretty-printing all type variable
binders when pretty-printing closed type families (e.g., in the output
of `:info` in GHCi). This threw me for a loop, so let's guard this behind
the `-fprint-explicit-foralls` flag.

Test Plan: make test TEST=T13420

Reviewers: goldfire, austin, bgamari

Reviewed By: bgamari

Subscribers: rwbarton, thomie

GHC Trac Issues: #13420

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

comment:5 Changed 2 years ago by bgamari

Resolution: fixed
Status: patchclosed
Note: See TracTickets for help on using tickets.