Home Explore Blog CI



rustc

5th chunk of `src/diagnostics.md`
6d8c95950557664543bfb009780dc709f5f35511146302630000000100000fb6
  the code emitting the error is removed from the code where the error is
  constructed behind a relatively deep call-stack. Even then, it is a good way
  to get your bearings.
- Invoking `rustc` with the nightly-only flag `-Z treat-err-as-bug=1`
  will treat the first error being emitted as an Internal Compiler Error, which
  allows you to get a
  stack trace at the point the error has been emitted. Change the `1` to
  something else if you wish to trigger on a later error.

  There are limitations with this approach:
  - Some calls get elided from the stack trace because they get inlined in the compiled `rustc`.
  - The _construction_ of the error is far away from where it is _emitted_,
    a problem similar to the one we faced with the `grep` approach.
    In some cases, we buffer multiple errors in order to emit them in order.
- Invoking `rustc` with `-Z track-diagnostics` will print error creation
  locations alongside the error.

The regular development practices apply: judicious use of `debug!()` statements
and use of a debugger to trigger break points in order to figure out in what
order things are happening.

## `Span`

[`Span`][span] is the primary data structure in `rustc` used to represent a
location in the code being compiled. `Span`s are attached to most constructs in
HIR and MIR, allowing for more informative error reporting.


A `Span` can be looked up in a [`SourceMap`][sourcemap] to get a "snippet"
useful for displaying errors with [`span_to_snippet`][sptosnip] and other
similar methods on the `SourceMap`.


## Error messages

The [`rustc_errors`][errors] crate defines most of the utilities used for
reporting errors.


Diagnostics can be implemented as types which implement the `Diagnostic`
trait. This is preferred for new diagnostics as it enforces a separation
between diagnostic emitting logic and the main code paths. For less-complex
diagnostics, the `Diagnostic` trait can be derived -- see [Diagnostic
structs][diagnostic-structs]. Within the trait implementation, the APIs
described below can be used as normal.


[`DiagCtxt`][DiagCtxt] has methods that create and emit errors. These methods
usually have names like `span_err` or `struct_span_err` or `span_warn`, etc...
There are lots of them; they emit different types of "errors", such as
warnings, errors, fatal errors, suggestions, etc.


In general, there are two classes of such methods: ones that emit an error
directly and ones that allow finer control over what to emit. For example,
[`span_err`][spanerr] emits the given error message at the given `Span`, but
[`struct_span_err`][strspanerr] instead returns a
[`Diag`][diag].

Most of these methods will accept strings, but it is recommended that typed
identifiers for translatable diagnostics be used for new diagnostics (see
[Translation][translation]).


`Diag` allows you to add related notes and suggestions to an error
before emitting it by calling the [`emit`][emit] method. (Failing to either
emit or [cancel][cancel] a `Diag` will result in an ICE.) See the
[docs][diag] for more info on what you can do.


```rust,ignore
// Get a `Diag`. This does _not_ emit an error yet.
let mut err = sess.dcx.struct_span_err(sp, fluent::example::example_error);

// In some cases, you might need to check if `sp` is generated by a macro to
// avoid printing weird errors about macro-generated code.

if let Ok(snippet) = sess.source_map().span_to_snippet(sp) {
    // Use the snippet to generate a suggested fix
    err.span_suggestion(suggestion_sp, fluent::example::try_qux_suggestion, format!("qux {}", snippet));
} else {
    // If we weren't able to generate a snippet, then emit a "help" message
    // instead of a concrete "suggestion". In practice this is unlikely to be
    // reached.
    err.span_help(suggestion_sp, fluent::example::qux_suggestion);
}

// emit the error
err.emit();
```

```fluent
example-example-error = oh no! this is an error!
  .try-qux-suggestion = try using a qux here
  .qux-suggestion = you could use a qux here instead

Title: Finding Errors, Spans, and Error Messages
Summary
This passage details methods for finding error sources in Rust compiler code, including using `debug!()` statements and debuggers. It introduces `Span` as a primary data structure for representing code locations, and the `rustc_errors` crate for reporting errors. It describes how to implement diagnostics with the `Diagnostic` trait, how to use `DiagCtxt` to create errors, and how to add notes and suggestions to an error using `Diag`. Finally, it provides a code example and fluent example to show error message generation.