Skip to content
GitLab
Projects Groups Snippets
  • /
  • Help
    • Help
    • Support
    • Community forum
    • Submit feedback
  • Sign in / Register
  • GHC GHC
  • Project information
    • Project information
    • Activity
    • Labels
    • Members
  • Repository
    • Repository
    • Files
    • Commits
    • Branches
    • Tags
    • Contributors
    • Graph
    • Compare
    • Locked Files
  • Issues 5,348
    • Issues 5,348
    • List
    • Boards
    • Service Desk
    • Milestones
    • Iterations
  • Merge requests 567
    • Merge requests 567
  • CI/CD
    • CI/CD
    • Pipelines
    • Jobs
    • Schedules
    • Test Cases
  • Deployments
    • Deployments
    • Releases
  • Analytics
    • Analytics
    • Value stream
    • CI/CD
    • Code review
    • Insights
    • Issue
    • Repository
  • Wiki
    • Wiki
  • Snippets
    • Snippets
  • Activity
  • Graph
  • Create a new issue
  • Jobs
  • Commits
  • Issue Boards
Collapse sidebar
  • Glasgow Haskell CompilerGlasgow Haskell Compiler
  • GHCGHC
  • Issues
  • #20119
Closed
Open
Issue created Jul 14, 2021 by Alfredo Di Napoli@adinapoliDeveloper10 of 10 checklist items completed10/10 checklist items

Convert diagnostics in Tc Utils, Solver,Module & co to proper `TcRnMessage`

See also #19905 and #18516.

Short Summary: Get rid of the usages of TcRnUnknownMessage in various modules. Do so by creating new type constructors for the TcRnMessage type, specific to the diagnostics you are converting.

Long summary

There are various occurrences of TcRnUnknownMessage in the following modules:

  • GHC.Tc.Deriv (9)
  • GHC.Tc.Errors (4)
  • GHC.Tc.Instance.Family (2)
  • GHC.Tc.Module (14)
  • GHC.Tc.Solver.Interact (1)
  • GHC.Tc.Solver (1)
  • GHC.Tc.Utils.Backpack (5)
  • GHC.Tc.Utils.Env (7)
  • GHC.Tc.Utils.Instantiate (2)
  • GHC.Tc.Utils.TcMType (3)

These occurrences takes a SDoc as input and produces a TcRnMessage, but they carry very little information and structure with them, which means that GHC API users can't meaningfully derive much from the SDoc unless it's parsed or analysed. We would like to replace these with new type constructors to be added to the TcRnMessage type, which would give us a precise (and structured) semantic of the diagnostics in question.

Example

To give you a concrete example of a successfully ported message, we want to go from something like this:

localPatternSynonymErr :: TcRnMessage
localPatternSynonymErr
  = TcRnUnknownMessage $ mkPlainError noHints $
    hang (text "Illegal pattern synonym declaration for" <+> quotes (ppr rdrname))
       2 (text "Pattern synonym declarations are only valid at top level")

to something like this:

localPatternSynonymErr = TcRnIllegalPatSynDecl rdrname

Where TcRnIllegalPatSynDecl is defined as:

  data TcRnMessage =
    ...
    | TcRnIllegalPatSynDecl :: !(LIdP GhcPs) -> TcRnMessage
    ...

Possible plan of action

What follows is a possible plan of action, to guide the developer working on this:

  • Add as many type constructors as needed to GHC.Tc.Errors.Types.TcRnMessage. If possible, try to document these following the schema used for the existing ones. It might be possible there is already a type constructor readily available to use, so check for its presence.

  • This is a good time to grep the codebase for the text of the diagnostics you want to port, which should hopefully yield a number of test cases. You can later run the testsuite on those tests locally (e.g. ./hadrian/build test --only=...), to verify the final output didn't change. Occasionally the final output might change, for example if new hints are added. Don't be afraid to amend the tests in case that happens, and use your best judgement. The goal is to port existing messages to a new infrastructure, not necessarily improve GHC's diagnostic English prose. That can happen at a later stage.

  • Occasionally some instances of TcRnUnknownMessage might be wrapping SDocs which are generated from other SDocs (perhaps even passed as input in a function that produces yet another SDoc). All those little SDoc fragments should be converted into proper Haskell types so that we would be passing to new type constructors not one or more SDocs but richer Haskell types (random examples: Name, OccName, HsBind GhcPs, etc).

  • In rare circumstances it might be not feasible to pass a proper Haskell type, maybe due to some nasty cyclic import. If that happens, it's passable (but not ideal) to do something like this:

      ...
      TcRnNewConstructor :: Outputable a => ComplexTypeThatTakesAn a -> ... -> TcRnMessage
  • GHC will now complain that the instance Diagnostic TcRnMessage inside GHC.Tc.Errors.Ppr is not complete, if new type constructors were added. The diagnosticMessage, diagnosticReason and diagnosticHints will need to handle the new type constructors.

  • Implement diagnosticMessage by copying the original textual representation of the diagnostic message from the ported module. If the textual representation is using external data (i.e. local binds in that module) add the necessary type arguments to the constructor to "carry the data over". Again, follow the existing patterns.

  • Implement diagnosticReason by copying the original DiagnosticReason(s) from the original module, where the message was produced originally.

  • Implement diagnosticHints by copying, once again, what the original diagnostic in ported module is doing. If there are no hints, return noHints. Be aware that hints might be tucked and hidden into the English prose of the diagnostic you are porting, in which case you might have to create a brand new GhcHint type constructor if none of the existing ones captures the hint.

Edited Mar 22, 2023 by Torsten Schmits
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information
Assignee
Assign to
Time tracking