Skip to content

Error message infrastructure

I have just spent a couple of hours wrestling with the new error message infrastructure for the typechecker. Here are some thoughts and questions.

To be clear, the direction of travel is great -- this is all about detail.

  1. Surely we should have

    instance Outputable e => Outputable (Messages e)
    instance Outputable e => Outputable (MsgEnvelope e)

    I needed it today, and although took me over an hour of faff to figure out how to do it, it's not so hard

    instance Diagnostic e => Outputable (Messages e) where
        ppr msgs = braces (vcat (map ppr_one (bagToList (getMessages msgs))))
           where
             ppr_one :: MsgEnvelope e -> SDoc
             ppr_one envelope = ppr_diag (errMsgDiagnostic envelope)
    
             ppr_diag :: e -> SDoc
             ppr_diag diag = vcat [ ppr (diagnosticReason diag)
                                  , nest 2 (vcat (unDecorated (diagnosticMessage diag))) ]

    This could be improved.

  2. This is newtype poorly named:

    newtype Messages e = Messages { getMessages :: Bag (MsgEnvelope e) }

    Either the newtype should be MsgEnvelopes e or the contents should be Bag (Message e).

  3. We have in GHC.Tc.Errors.Types:

    data TcRnMessage where
       TcRnUnknownMessage :: (Diagnostic a, Typeable a) => a -> TcRnMessage
       TcRnMessageWithInfo :: !UnitState -> !TcRnMessageDetailed -> TcRnMessage
       TcRnSolverReport :: [ReportWithCtxt] -> DiagnosticReason -> [GhcHint] -> TcRnMessage
       ...lots more error-secific-constructors...
    
    data TcRnMessageDetailed
       = TcRnMessageDetailed !ErrInfo !TcRnMessage

    Questions

    • Can't we just inline TcRnMessageDetailed into TcRnMessageWithInfo?
    • How would I choose between TcRnUnknownMessage and TcRnMessageWithInfo and an error-specific constructor?
  4. Also in GHC.Tc.Errors.Types:

    data ReportWithCtxt = ReportWithCtxt ReportErrCtxt TcReportMsg
    
    data TcReportMsg where
       ...lots *more* error-specific constructors....
    • Why do we need TcRnMessage and TcReportMsg? Ah.. maybe those are solver-specific errors? But then calll it TcSolverMessage etc.
    • And put all the solver-specific stuff in TcRnSolverReport; at the moment TcRnInaccessibleCode sticks out like a sore thumb.
    • Why does TcRnSolverReport take a list of solver errors? It really has one error, plus a list of supplementary information, a bit like your various "WithInfo" variants, doesn't it?

Generally, the data types are so large that I found it really helpful to write down the above sketches, just to keep them in my head. We might consider doing that in some way.

To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information