Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RFC: Diagnostic registry prototype #11460

Closed
wants to merge 6 commits into from
Closed

Conversation

brson
Copy link
Contributor

@brson brson commented Jan 10, 2014

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 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 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 be 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 4 things:

  1. Ensure that the diagnostic code is registered (statically).
  2. Prevents reuse of the same code for multiple diagnostics.
  3. Record the diagnostic message (in compile-time state) so it can be used later in the database.
  4. 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.

///
/// This must be called (lexically) before a `desc_diag` on the same diagnostic code.
macro_rules! alert_error (
($sess: expr, $name: tt, $msg: tt, $($arg: tt)*) => { {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should combine $msg: tt, $($arg: tt)* to just $($arg:tt)+ in order to allow strings literals without arguments (I think?)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I take that back, maybe just remove the comma after $msg?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I need the message itself for other reasons. If I combine it with $arg can I still pull it out within the macro?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe I can just create a second case that doesn't have $args

@brson
Copy link
Contributor Author

brson commented Jan 10, 2014

@nikomatsakis You may be interested.

safe, concurrent, fast
```

"),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I understand this correctly, this file is going to be hotly contested in terms of rebase conflicts because everyone is going to be adding their error here, right? I think this is in a good format to try to avoid rebase conflicts, but something to keep in mind.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes

@alexcrichton
Copy link
Member

So it appears that we will have a central database of all error codes, but not necessarily a central database of the "extended description" of all error codes. I imagine that this is intended to forward-port error codes instead of describing them all at once?

Also cc #8161, mildly related to this.

@brson
Copy link
Contributor Author

brson commented Jan 10, 2014

@alexcrichton Yes, this won't actually produce a list of all error codes at runtime, just those with extended descriptions.

@brson
Copy link
Contributor Author

brson commented Jan 10, 2014

Yes, we can't describe them all at one time. We'll just set up the system and encourage people to document them as needed.

@alexcrichton
Copy link
Member

r=me with the small comment at the bottom of lib.rs, or without, you'll be changing this anyway

This is awesome, fantastic work!

This provides a way to create stable diagnostic codes, while keeping
the overal burden on compiler writers low, and introducing a way to
incrementally provide extended documentation of diagnostics.
@brson
Copy link
Contributor Author

brson commented Jan 11, 2014

I'm eager to keep moving forward on this so I'm going to get these extensions snapshotted. If it turns out people don't like this direction it's no big loss to revert.

@brson
Copy link
Contributor Author

brson commented Jan 11, 2014

I actually don't need the snapshot after all, so I'm just going to keep working on it.