mozilla/rust — pull request #11460 by brson (2014-01-10 23:12:16+00:00)
Title: RFC: Diagnostic registry prototype

This is the beginning of a solution for #2092, which calls for linking rustc errors to FAQs that better explain what the errors mean. It's just barely started, but I'm asking for feedback now because it depends on a set of private syntax extensions that are huge hacks, and they need to be snapshotted for work to continue.

My intention is to get the infrastructure in place, get all errors converted to this system, then encourage people who encounter errors to start adding docs.

The core idea is that every individual diagnostic message has a corresponding globally unique and stable code, which are registered in a central location (primarily so they are easy to track), each raised error must specify a diagnostic code. There is an additional database containing optional extended descriptions of diagnostic codes. This database can be used by the compiler itself to emit extended information or it may be used to generate standalone documentation.

Some simple tricks are used to statically ensure that diagnostic codes are used correctly, and to allow string literals to be reused without duplication.

The design is intended to put minimal burden on compiler writers; the amount of code needed to raise an error is comparable to what we have today, and the primary diagnostic message is still inline at the site where it is raised.

In use the system consists of three phases which occur in *lexical* order.

## Diagnostic registry

The first module of each crate that uses these diagnostics is called `mod diag_index` and simply contains lines like the following:

```
reg_diag!(A0000)
reg_diag!(A0001)
reg_diag!(A0002)
...
```

This simply registers all the diagnostic codes used by the crate. This registry is used to validate that codes are used correctly in later phases, but also simply as a convenient way to keep track of which codes have been used. As codes are retired from use they will remain in this file forever, never to reused again. The naming convention for codes is debatable but I've chosen a letter plus 4 digits. The letter is just a very simple namespace so that multiple crates can keep their own independent lists of diagnostic codes.

## Reporting

This takes the place of our current calls to e.g. `sess.span_fatal`. Instead of calling the diagnostic functions directly now you use a macro like `raise_fatal!(sess, sp, A0001, "Error in module {}", modname)`. These macros do 3 things:

1) Ensure that the diagnostic code is registered (statically).
2) Record the diagnostic message (in compile-time state) so it can be used later in the database.
3) Defer to the session to report the diagnostic

## Extended documentation

Finally, the last module in the crate is called `diag_db` and contains a single function called `load`, which can be used to get a vector of all diagnostics that have extended documentation, along with their primary diagnostic message, and the extended documentation. This module `include!`s a list of `diag_desc!` macros that document the diagnostic codes as markdown.

# Future direction

After the snapshot goes through I'll convert all the diagnostics in all our tools to use this; add the full complement of diagnostic reporting macros; add some language to our error reporting indicating whether there's extended information; add a diagnostic message indicating how to contribute extended diagnostics when there are non; add a flag to retrieve extended info; add a flag to dump all extended diagnostics as mardown; and begin testing the extended documentation.