| <!DOCTYPE HTML> |
| <html lang="en" class="light sidebar-visible" dir="ltr"> |
| <head> |
| <!-- Book generated using mdBook --> |
| <meta charset="UTF-8"> |
| <title>Errors and lints - Rust Compiler Development Guide</title> |
| |
| |
| <!-- Custom HTML head --> |
| |
| <meta name="description" content="A guide to developing the Rust compiler (rustc)"> |
| <meta name="viewport" content="width=device-width, initial-scale=1"> |
| <meta name="theme-color" content="#ffffff"> |
| |
| <link rel="icon" href="favicon.svg"> |
| <link rel="shortcut icon" href="favicon.png"> |
| <link rel="stylesheet" href="css/variables.css"> |
| <link rel="stylesheet" href="css/general.css"> |
| <link rel="stylesheet" href="css/chrome.css"> |
| <link rel="stylesheet" href="css/print.css" media="print"> |
| |
| <!-- Fonts --> |
| <link rel="stylesheet" href="FontAwesome/css/font-awesome.css"> |
| <link rel="stylesheet" href="fonts/fonts.css"> |
| |
| <!-- Highlight.js Stylesheets --> |
| <link rel="stylesheet" id="highlight-css" href="highlight.css"> |
| <link rel="stylesheet" id="tomorrow-night-css" href="tomorrow-night.css"> |
| <link rel="stylesheet" id="ayu-highlight-css" href="ayu-highlight.css"> |
| |
| <!-- Custom theme stylesheets --> |
| |
| |
| <!-- Provide site root and default themes to javascript --> |
| <script> |
| const path_to_root = ""; |
| const default_light_theme = "light"; |
| const default_dark_theme = "navy"; |
| </script> |
| <!-- Start loading toc.js asap --> |
| <script src="toc.js"></script> |
| </head> |
| <body> |
| <div id="body-container"> |
| <!-- Work around some values being stored in localStorage wrapped in quotes --> |
| <script> |
| try { |
| let theme = localStorage.getItem('mdbook-theme'); |
| let sidebar = localStorage.getItem('mdbook-sidebar'); |
| |
| if (theme.startsWith('"') && theme.endsWith('"')) { |
| localStorage.setItem('mdbook-theme', theme.slice(1, theme.length - 1)); |
| } |
| |
| if (sidebar.startsWith('"') && sidebar.endsWith('"')) { |
| localStorage.setItem('mdbook-sidebar', sidebar.slice(1, sidebar.length - 1)); |
| } |
| } catch (e) { } |
| </script> |
| |
| <!-- Set the theme before any content is loaded, prevents flash --> |
| <script> |
| const default_theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? default_dark_theme : default_light_theme; |
| let theme; |
| try { theme = localStorage.getItem('mdbook-theme'); } catch(e) { } |
| if (theme === null || theme === undefined) { theme = default_theme; } |
| const html = document.documentElement; |
| html.classList.remove('light') |
| html.classList.add(theme); |
| html.classList.add("js"); |
| </script> |
| |
| <input type="checkbox" id="sidebar-toggle-anchor" class="hidden"> |
| |
| <!-- Hide / unhide sidebar before it is displayed --> |
| <script> |
| let sidebar = null; |
| const sidebar_toggle = document.getElementById("sidebar-toggle-anchor"); |
| if (document.body.clientWidth >= 1080) { |
| try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch(e) { } |
| sidebar = sidebar || 'visible'; |
| } else { |
| sidebar = 'hidden'; |
| } |
| sidebar_toggle.checked = sidebar === 'visible'; |
| html.classList.remove('sidebar-visible'); |
| html.classList.add("sidebar-" + sidebar); |
| </script> |
| |
| <nav id="sidebar" class="sidebar" aria-label="Table of contents"> |
| <!-- populated by js --> |
| <mdbook-sidebar-scrollbox class="sidebar-scrollbox"></mdbook-sidebar-scrollbox> |
| <noscript> |
| <iframe class="sidebar-iframe-outer" src="toc.html"></iframe> |
| </noscript> |
| <div id="sidebar-resize-handle" class="sidebar-resize-handle"> |
| <div class="sidebar-resize-indicator"></div> |
| </div> |
| </nav> |
| |
| <div id="page-wrapper" class="page-wrapper"> |
| |
| <div class="page"> |
| <div id="menu-bar-hover-placeholder"></div> |
| <div id="menu-bar" class="menu-bar sticky"> |
| <div class="left-buttons"> |
| <label id="sidebar-toggle" class="icon-button" for="sidebar-toggle-anchor" title="Toggle Table of Contents" aria-label="Toggle Table of Contents" aria-controls="sidebar"> |
| <i class="fa fa-bars"></i> |
| </label> |
| <button id="theme-toggle" class="icon-button" type="button" title="Change theme" aria-label="Change theme" aria-haspopup="true" aria-expanded="false" aria-controls="theme-list"> |
| <i class="fa fa-paint-brush"></i> |
| </button> |
| <ul id="theme-list" class="theme-popup" aria-label="Themes" role="menu"> |
| <li role="none"><button role="menuitem" class="theme" id="default_theme">Auto</button></li> |
| <li role="none"><button role="menuitem" class="theme" id="light">Light</button></li> |
| <li role="none"><button role="menuitem" class="theme" id="rust">Rust</button></li> |
| <li role="none"><button role="menuitem" class="theme" id="coal">Coal</button></li> |
| <li role="none"><button role="menuitem" class="theme" id="navy">Navy</button></li> |
| <li role="none"><button role="menuitem" class="theme" id="ayu">Ayu</button></li> |
| </ul> |
| <button id="search-toggle" class="icon-button" type="button" title="Search. (Shortkey: s)" aria-label="Toggle Searchbar" aria-expanded="false" aria-keyshortcuts="S" aria-controls="searchbar"> |
| <i class="fa fa-search"></i> |
| </button> |
| </div> |
| |
| <h1 class="menu-title">Rust Compiler Development Guide</h1> |
| |
| <div class="right-buttons"> |
| <a href="print.html" title="Print this book" aria-label="Print this book"> |
| <i id="print-button" class="fa fa-print"></i> |
| </a> |
| <a href="https://github.com/rust-lang/rustc-dev-guide" title="Git repository" aria-label="Git repository"> |
| <i id="git-repository-button" class="fa fa-github"></i> |
| </a> |
| <a href="https://github.com/rust-lang/rustc-dev-guide/edit/master/src/diagnostics.md" title="Suggest an edit" aria-label="Suggest an edit"> |
| <i id="git-edit-button" class="fa fa-edit"></i> |
| </a> |
| |
| </div> |
| </div> |
| |
| <div id="search-wrapper" class="hidden"> |
| <form id="searchbar-outer" class="searchbar-outer"> |
| <input type="search" id="searchbar" name="searchbar" placeholder="Search this book ..." aria-controls="searchresults-outer" aria-describedby="searchresults-header"> |
| </form> |
| <div id="searchresults-outer" class="searchresults-outer hidden"> |
| <div id="searchresults-header" class="searchresults-header"></div> |
| <ul id="searchresults"> |
| </ul> |
| </div> |
| </div> |
| |
| <!-- Apply ARIA attributes after the sidebar and the sidebar toggle button are added to the DOM --> |
| <script> |
| document.getElementById('sidebar-toggle').setAttribute('aria-expanded', sidebar === 'visible'); |
| document.getElementById('sidebar').setAttribute('aria-hidden', sidebar !== 'visible'); |
| Array.from(document.querySelectorAll('#sidebar a')).forEach(function(link) { |
| link.setAttribute('tabIndex', sidebar === 'visible' ? 0 : -1); |
| }); |
| </script> |
| |
| <div id="content" class="content"> |
| <main> |
| <h1 id="errors-and-lints"><a class="header" href="#errors-and-lints">Errors and lints</a></h1> |
| <ul> |
| <li><a href="#diagnostic-structure">Diagnostic structure</a> |
| <ul> |
| <li><a href="#error-codes-and-explanations">Error codes and explanations</a></li> |
| <li><a href="#lints-versus-fixed-diagnostics">Lints versus fixed diagnostics</a></li> |
| </ul> |
| </li> |
| <li><a href="#diagnostic-output-style-guide">Diagnostic output style guide</a> |
| <ul> |
| <li><a href="#lint-naming">Lint naming</a></li> |
| <li><a href="#diagnostic-levels">Diagnostic levels</a></li> |
| </ul> |
| </li> |
| <li><a href="#helpful-tips-and-options">Helpful tips and options</a> |
| <ul> |
| <li><a href="#finding-the-source-of-errors">Finding the source of errors</a></li> |
| </ul> |
| </li> |
| <li><a href="#span"><code>Span</code></a></li> |
| <li><a href="#error-messages">Error messages</a></li> |
| <li><a href="#suggestions">Suggestions</a> |
| <ul> |
| <li><a href="#suggestion-style-guide">Suggestion Style Guide</a></li> |
| </ul> |
| </li> |
| <li><a href="#lints">Lints</a> |
| <ul> |
| <li><a href="#when-do-lints-run">When do lints run?</a></li> |
| <li><a href="#lint-definition-terms">Lint definition terms</a></li> |
| <li><a href="#declaring-a-lint">Declaring a lint</a></li> |
| <li><a href="#edition-gated-lints">Edition-gated lints</a></li> |
| <li><a href="#feature-gated-lints">Feature-gated lints</a></li> |
| <li><a href="#future-incompatible-lints">Future-incompatible lints</a></li> |
| <li><a href="#renaming-or-removing-a-lint">Renaming or removing a lint</a></li> |
| <li><a href="#lint-groups">Lint groups</a></li> |
| <li><a href="#linting-early-in-the-compiler">Linting early in the compiler</a> |
| <ul> |
| <li><a href="#linting-even-earlier-in-the-compiler">Linting even earlier in the compiler</a></li> |
| </ul> |
| </li> |
| </ul> |
| </li> |
| <li><a href="#json-diagnostic-output">JSON diagnostic output</a></li> |
| <li><a href="#rustc_on_unimplemented"><code>#[rustc_on_unimplemented]</code></a> |
| <ul> |
| <li><a href="#filtering">Filtering</a></li> |
| <li><a href="#formatting">Formatting</a></li> |
| </ul> |
| </li> |
| </ul> |
| <p>A lot of effort has been put into making <code>rustc</code> have great error messages. |
| This chapter is about how to emit compile errors and lints from the compiler.</p> |
| <h2 id="diagnostic-structure"><a class="header" href="#diagnostic-structure">Diagnostic structure</a></h2> |
| <p>The main parts of a diagnostic error are the following:</p> |
| <pre><code>error[E0000]: main error message |
| --> file.rs:LL:CC |
| | |
| LL | <code> |
| | -^^^^- secondary label |
| | | |
| | primary label |
| | |
| = note: note without a `Span`, created with `.note` |
| note: sub-diagnostic message for `.span_note` |
| --> file.rs:LL:CC |
| | |
| LL | more code |
| | ^^^^ |
| </code></pre> |
| <ul> |
| <li>Level (<code>error</code>, <code>warning</code>, etc.). It indicates the severity of the message. |
| (See <a href="#diagnostic-levels">diagnostic levels</a>)</li> |
| <li>Code (for example, for "mismatched types", it is <code>E0308</code>). It helps |
| users get more information about the current error through an extended |
| description of the problem in the error code index. Not all diagnostic have a |
| code. For example, diagnostics created by lints don't have one.</li> |
| <li>Message. It is the main description of the problem. It should be general and |
| able to stand on its own, so that it can make sense even in isolation.</li> |
| <li>Diagnostic window. This contains several things: |
| <ul> |
| <li>The path, line number and column of the beginning of the primary span.</li> |
| <li>The users' affected code and its surroundings.</li> |
| <li>Primary and secondary spans underlying the users' code. These spans can |
| optionally contain one or more labels. |
| <ul> |
| <li>Primary spans should have enough text to describe the problem in such a |
| way that if it were the only thing being displayed (for example, in an |
| IDE) it would still make sense. Because it is "spatially aware" (it |
| points at the code), it can generally be more succinct than the error |
| message.</li> |
| <li>If cluttered output can be foreseen in cases when multiple span labels |
| overlap, it is a good idea to tweak the output appropriately. For |
| example, the <code>if/else arms have incompatible types</code> error uses different |
| spans depending on whether the arms are all in the same line, if one of |
| the arms is empty and if none of those cases applies.</li> |
| </ul> |
| </li> |
| </ul> |
| </li> |
| <li>Sub-diagnostics. Any error can have multiple sub-diagnostics that look |
| similar to the main part of the error. These are used for cases where the |
| order of the explanation might not correspond with the order of the code. If |
| the order of the explanation can be "order free", leveraging secondary labels |
| in the main diagnostic is preferred, as it is typically less verbose.</li> |
| </ul> |
| <p>The text should be matter of fact and avoid capitalization and periods, unless |
| multiple sentences are <em>needed</em>:</p> |
| <pre><code class="language-txt">error: the fobrulator needs to be krontrificated |
| </code></pre> |
| <p>When code or an identifier must appear in a message or label, it should be |
| surrounded with backticks:</p> |
| <pre><code class="language-txt">error: the identifier `foo.bar` is invalid |
| </code></pre> |
| <h3 id="error-codes-and-explanations"><a class="header" href="#error-codes-and-explanations">Error codes and explanations</a></h3> |
| <p>Most errors have an associated error code. Error codes are linked to long-form |
| explanations which contains an example of how to trigger the error and in-depth |
| details about the error. They may be viewed with the <code>--explain</code> flag, or via |
| the <a href="https://doc.rust-lang.org/error-index.html">error index</a>.</p> |
| <p>As a general rule, give an error a code (with an associated explanation) if the |
| explanation would give more information than the error itself. A lot of the time |
| it's better to put all the information in the emitted error itself. However, |
| sometimes that would make the error verbose or there are too many possible |
| triggers to include useful information for all cases in the error, in which case |
| it's a good idea to add an explanation.<sup class="footnote-reference" id="fr-estebank-1"><a href="#footnote-estebank">1</a></sup> |
| As always, if you are not sure, just ask your reviewer!</p> |
| <p>If you decide to add a new error with an associated error code, please read |
| <a href="./diagnostics/error-codes.html">this section</a> for a guide and important details about the |
| process.</p> |
| <h3 id="lints-versus-fixed-diagnostics"><a class="header" href="#lints-versus-fixed-diagnostics">Lints versus fixed diagnostics</a></h3> |
| <p>Some messages are emitted via <a href="#lints">lints</a>, where the user can control the |
| level. Most diagnostics are hard-coded such that the user cannot control the |
| level.</p> |
| <p>Usually it is obvious whether a diagnostic should be "fixed" or a lint, but |
| there are some grey areas.</p> |
| <p>Here are a few examples:</p> |
| <ul> |
| <li>Borrow checker errors: these are fixed errors. The user cannot adjust the |
| level of these diagnostics to silence the borrow checker.</li> |
| <li>Dead code: this is a lint. While the user probably doesn't want dead code in |
| their crate, making this a hard error would make refactoring and development |
| very painful.</li> |
| <li><a href="#future-incompatible-lints">future-incompatible lints</a>: |
| these are silenceable lints. |
| It was decided that making them fixed errors would cause too much breakage, |
| so warnings are instead emitted, |
| and will eventually be turned into fixed (hard) errors.</li> |
| </ul> |
| <p>Hard-coded warnings (those using methods like <code>span_warn</code>) should be avoided |
| for normal code, preferring to use lints instead. Some cases, such as warnings |
| with CLI flags, will require the use of hard-coded warnings.</p> |
| <p>See the <code>deny</code> <a href="#diagnostic-levels">lint level</a> below for guidelines when to |
| use an error-level lint instead of a fixed error.</p> |
| <h2 id="diagnostic-output-style-guide"><a class="header" href="#diagnostic-output-style-guide">Diagnostic output style guide</a></h2> |
| <ul> |
| <li>Write in plain simple English. If your message, when shown on a – possibly |
| small – screen (which hasn't been cleaned for a while), cannot be understood |
| by a normal programmer, who just came out of bed after a night partying, |
| it's too complex.</li> |
| <li><code>Error</code>, <code>Warning</code>, <code>Note</code>, and <code>Help</code> messages start with a lowercase |
| letter and do not end with punctuation.</li> |
| <li>Error messages should be succinct. Users will see these error messages many |
| times, and more verbose descriptions can be viewed with the <code>--explain</code> |
| flag. That said, don't make it so terse that it's hard to understand.</li> |
| <li>The word "illegal" is illegal. Prefer "invalid" or a more specific word |
| instead.</li> |
| <li>Errors should document the span of code where they occur (use |
| <a href="https://doc.rust-lang.org/nightly/nightly-rustc/rustc_errors/struct.DiagCtxt.html"><code>rustc_errors::DiagCtxt</code></a>'s |
| <code>span_*</code> methods or a diagnostic struct's <code>#[primary_span]</code> to easily do |
| this). Also <code>note</code> other spans that have contributed to the error if the span |
| isn't too large.</li> |
| <li>When emitting a message with span, try to reduce the span to the smallest |
| amount possible that still signifies the issue</li> |
| <li>Try not to emit multiple error messages for the same error. This may require |
| detecting duplicates.</li> |
| <li>When the compiler has too little information for a specific error message, |
| consult with the compiler team to add new attributes for library code that |
| allow adding more information. For example see |
| <a href="#rustc_on_unimplemented"><code>#[rustc_on_unimplemented]</code></a>. Use these |
| annotations when available!</li> |
| <li>Keep in mind that Rust's learning curve is rather steep, and that the |
| compiler messages are an important learning tool.</li> |
| <li>When talking about the compiler, call it <code>the compiler</code>, not <code>Rust</code> or |
| <code>rustc</code>.</li> |
| <li>Use the <a href="https://en.wikipedia.org/wiki/Serial_comma">Oxford comma</a> when |
| writing lists of items.</li> |
| </ul> |
| <h3 id="lint-naming"><a class="header" href="#lint-naming">Lint naming</a></h3> |
| <p>From <a href="https://github.com/rust-lang/rfcs/blob/master/text/0344-conventions-galore.md#lints">RFC 0344</a>, lint names should be consistent, with the following |
| guidelines:</p> |
| <p>The basic rule is: the lint name should make sense when read as "allow |
| <em>lint-name</em>" or "allow <em>lint-name</em> items". For example, "allow |
| <code>deprecated</code> items" and "allow <code>dead_code</code>" makes sense, while "allow |
| <code>unsafe_block</code>" is ungrammatical (should be plural).</p> |
| <ul> |
| <li> |
| <p>Lint names should state the bad thing being checked for, e.g. <code>deprecated</code>, |
| so that <code>#[allow(deprecated)]</code> (items) reads correctly. Thus <code>ctypes</code> is not |
| an appropriate name; <code>improper_ctypes</code> is.</p> |
| </li> |
| <li> |
| <p>Lints that apply to arbitrary items (like the stability lints) should just |
| mention what they check for: use <code>deprecated</code> rather than |
| <code>deprecated_items</code>. This keeps lint names short. (Again, think "allow |
| <em>lint-name</em> items".)</p> |
| </li> |
| <li> |
| <p>If a lint applies to a specific grammatical class, mention that class and |
| use the plural form: use <code>unused_variables</code> rather than <code>unused_variable</code>. |
| This makes <code>#[allow(unused_variables)]</code> read correctly.</p> |
| </li> |
| <li> |
| <p>Lints that catch unnecessary, unused, or useless aspects of code should use |
| the term <code>unused</code>, e.g. <code>unused_imports</code>, <code>unused_typecasts</code>.</p> |
| </li> |
| <li> |
| <p>Use snake case in the same way you would for function names.</p> |
| </li> |
| </ul> |
| <h3 id="diagnostic-levels"><a class="header" href="#diagnostic-levels">Diagnostic levels</a></h3> |
| <p>Guidelines for different diagnostic levels:</p> |
| <ul> |
| <li> |
| <p><code>error</code>: emitted when the compiler detects a problem that makes it unable to |
| compile the program, either because the program is invalid or the programmer |
| has decided to make a specific <code>warning</code> into an error.</p> |
| </li> |
| <li> |
| <p><code>warning</code>: emitted when the compiler detects something odd about a program. |
| Care should be taken when adding warnings to avoid warning fatigue, and |
| avoid false-positives where there really isn't a problem with the code. Some |
| examples of when it is appropriate to issue a warning:</p> |
| <ul> |
| <li>A situation where the user <em>should</em> take action, such as swap out a |
| deprecated item, or use a <code>Result</code>, but otherwise doesn't prevent |
| compilation.</li> |
| <li>Unnecessary syntax that can be removed without affecting the semantics of |
| the code. For example, unused code, or unnecessary <code>unsafe</code>.</li> |
| <li>Code that is very likely to be incorrect, dangerous, or confusing, but the |
| language technically allows, and is not ready or confident enough to make |
| an error. For example <code>unused_comparisons</code> (out of bounds comparisons) or |
| <code>bindings_with_variant_name</code> (the user likely did not intend to create a |
| binding in a pattern).</li> |
| <li><a href="#future-incompatible">Future-incompatible lints</a>, where something was |
| accidentally or erroneously accepted in the past, but rejecting would |
| cause excessive breakage in the ecosystem.</li> |
| <li>Stylistic choices. For example, camel or snake case, or the <code>dyn</code> trait |
| warning in the 2018 edition. These have a high bar to be added, and should |
| only be used in exceptional circumstances. Other stylistic choices should |
| either be allow-by-default lints, or part of other tools like Clippy or |
| rustfmt.</li> |
| </ul> |
| </li> |
| <li> |
| <p><code>help</code>: emitted following an <code>error</code> or <code>warning</code> to give additional |
| information to the user about how to solve their problem. These messages |
| often include a suggestion string and <a href="https://doc.rust-lang.org/nightly/nightly-rustc/rustc_errors/enum.Applicability.html"><code>rustc_errors::Applicability</code></a> |
| confidence level to guide automated source fixes by tools. See the |
| <a href="#suggestions">Suggestions</a> section for more details.</p> |
| <p>The error or warning portion should <em>not</em> suggest how to fix the problem, |
| only the "help" sub-diagnostic should.</p> |
| </li> |
| <li> |
| <p><code>note</code>: emitted to given more context and identify additional circumstances |
| and parts of the code that caused the warning or error. For example, the |
| borrow checker will note any previous conflicting borrows.</p> |
| <p><code>help</code> vs <code>note</code>: <code>help</code> should be used to show changes the user can |
| possibly make to fix the problem. <code>note</code> should be used for everything else, |
| such as other context, information and facts, online resources to read, etc.</p> |
| </li> |
| </ul> |
| <p>Not to be confused with <em>lint levels</em>, whose guidelines are:</p> |
| <ul> |
| <li> |
| <p><code>forbid</code>: Lints should never default to <code>forbid</code>.</p> |
| </li> |
| <li> |
| <p><code>deny</code>: Equivalent to <code>error</code> diagnostic level. Some examples:</p> |
| <ul> |
| <li>A future-incompatible or edition-based lint that has graduated from the |
| warning level.</li> |
| <li>Something that has an extremely high confidence that is incorrect, but |
| still want an escape hatch to allow it to pass.</li> |
| </ul> |
| </li> |
| <li> |
| <p><code>warn</code>: Equivalent to the <code>warning</code> diagnostic level. See <code>warning</code> above |
| for guidelines.</p> |
| </li> |
| <li> |
| <p><code>allow</code>: Examples of the kinds of lints that should default to <code>allow</code>:</p> |
| <ul> |
| <li>The lint has a too high false positive rate.</li> |
| <li>The lint is too opinionated.</li> |
| <li>The lint is experimental.</li> |
| <li>The lint is used for enforcing something that is not normally enforced. |
| For example, the <code>unsafe_code</code> lint can be used to prevent usage of unsafe |
| code.</li> |
| </ul> |
| </li> |
| </ul> |
| <p>More information about lint levels can be found in the <a href="https://doc.rust-lang.org/nightly/rustc/lints/levels.html">rustc |
| book</a> and the <a href="https://doc.rust-lang.org/nightly/reference/attributes/diagnostics.html#lint-check-attributes">reference</a>.</p> |
| <h2 id="helpful-tips-and-options"><a class="header" href="#helpful-tips-and-options">Helpful tips and options</a></h2> |
| <h3 id="finding-the-source-of-errors"><a class="header" href="#finding-the-source-of-errors">Finding the source of errors</a></h3> |
| <p>There are three main ways to find where a given error is emitted:</p> |
| <ul> |
| <li> |
| <p><code>grep</code> for either a sub-part of the error message/label or error code. This |
| usually works well and is straightforward, but there are some cases where |
| 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.</p> |
| </li> |
| <li> |
| <p>Invoking <code>rustc</code> with the nightly-only flag <code>-Z treat-err-as-bug=1</code> |
| 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 <code>1</code> to |
| something else if you wish to trigger on a later error.</p> |
| <p>There are limitations with this approach:</p> |
| <ul> |
| <li>Some calls get elided from the stack trace because they get inlined in the compiled <code>rustc</code>.</li> |
| <li>The <em>construction</em> of the error is far away from where it is <em>emitted</em>, |
| a problem similar to the one we faced with the <code>grep</code> approach. |
| In some cases, we buffer multiple errors in order to emit them in order.</li> |
| </ul> |
| </li> |
| <li> |
| <p>Invoking <code>rustc</code> with <code>-Z track-diagnostics</code> will print error creation |
| locations alongside the error.</p> |
| </li> |
| </ul> |
| <p>The regular development practices apply: judicious use of <code>debug!()</code> statements |
| and use of a debugger to trigger break points in order to figure out in what |
| order things are happening.</p> |
| <h2 id="span"><a class="header" href="#span"><code>Span</code></a></h2> |
| <p><a href="https://doc.rust-lang.org/nightly/nightly-rustc/rustc_span/struct.Span.html"><code>Span</code></a> is the primary data structure in <code>rustc</code> used to represent a |
| location in the code being compiled. <code>Span</code>s are attached to most constructs in |
| HIR and MIR, allowing for more informative error reporting.</p> |
| <p>A <code>Span</code> can be looked up in a <a href="https://doc.rust-lang.org/nightly/nightly-rustc/rustc_span/source_map/struct.SourceMap.html"><code>SourceMap</code></a> to get a "snippet" |
| useful for displaying errors with <a href="https://doc.rust-lang.org/nightly/nightly-rustc/rustc_span/source_map/struct.SourceMap.html#method.span_to_snippet"><code>span_to_snippet</code></a> and other |
| similar methods on the <code>SourceMap</code>.</p> |
| <h2 id="error-messages"><a class="header" href="#error-messages">Error messages</a></h2> |
| <p>The <a href="https://doc.rust-lang.org/nightly/nightly-rustc/rustc_errors/index.html"><code>rustc_errors</code></a> crate defines most of the utilities used for |
| reporting errors.</p> |
| <p>Diagnostics can be implemented as types which implement the <code>Diagnostic</code> |
| 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 <code>Diagnostic</code> trait can be derived -- see <a href="./diagnostics/diagnostic-structs.html">Diagnostic |
| structs</a>. Within the trait implementation, the APIs |
| described below can be used as normal.</p> |
| <p><a href="https://doc.rust-lang.org/nightly/nightly-rustc/rustc_errors/struct.DiagCtxt.html"><code>DiagCtxt</code></a> has methods that create and emit errors. These methods |
| usually have names like <code>span_err</code> or <code>struct_span_err</code> or <code>span_warn</code>, etc... |
| There are lots of them; they emit different types of "errors", such as |
| warnings, errors, fatal errors, suggestions, etc.</p> |
| <p>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, |
| <a href="https://doc.rust-lang.org/nightly/nightly-rustc/rustc_errors/struct.DiagCtxt.html#method.span_err"><code>span_err</code></a> emits the given error message at the given <code>Span</code>, but |
| <a href="https://doc.rust-lang.org/nightly/nightly-rustc/rustc_errors/struct.DiagCtxt.html#method.struct_span_err"><code>struct_span_err</code></a> instead returns a |
| <a href="https://doc.rust-lang.org/nightly/nightly-rustc/rustc_errors/struct.Diag.html"><code>Diag</code></a>.</p> |
| <p>Most of these methods will accept strings, but it is recommended that typed |
| identifiers for translatable diagnostics be used for new diagnostics (see |
| <a href="./diagnostics/translation.html">Translation</a>).</p> |
| <p><code>Diag</code> allows you to add related notes and suggestions to an error |
| before emitting it by calling the <a href="https://doc.rust-lang.org/nightly/nightly-rustc/rustc_errors/struct.Diag.html#method.emit"><code>emit</code></a> method. (Failing to either |
| emit or <a href="https://doc.rust-lang.org/nightly/nightly-rustc/rustc_errors/struct.Diag.html#method.cancel">cancel</a> a <code>Diag</code> will result in an ICE.) See the |
| <a href="https://doc.rust-lang.org/nightly/nightly-rustc/rustc_errors/struct.Diag.html">docs</a> for more info on what you can do.</p> |
| <pre><code class="language-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();</code></pre> |
| <pre><code class="language-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 |
| </code></pre> |
| <h2 id="suggestions"><a class="header" href="#suggestions">Suggestions</a></h2> |
| <p>In addition to telling the user exactly <em>why</em> their code is wrong, it's |
| oftentimes furthermore possible to tell them how to fix it. To this end, |
| <a href="https://doc.rust-lang.org/nightly/nightly-rustc/rustc_errors/struct.Diag.html"><code>Diag</code></a> offers a structured suggestions API, which formats code |
| suggestions pleasingly in the terminal, or (when the <code>--error-format json</code> flag |
| is passed) as JSON for consumption by tools like <a href="https://github.com/rust-lang/rustfix"><code>rustfix</code></a>.</p> |
| <p>Not all suggestions should be applied mechanically, they have a degree of |
| confidence in the suggested code, from high |
| (<code>Applicability::MachineApplicable</code>) to low (<code>Applicability::MaybeIncorrect</code>). |
| Be conservative when choosing the level. Use the |
| <a href="https://doc.rust-lang.org/nightly/nightly-rustc/rustc_errors/struct.Diag.html#method.span_suggestion"><code>span_suggestion</code></a> method of <code>Diag</code> to |
| make a suggestion. The last argument provides a hint to tools whether |
| the suggestion is mechanically applicable or not.</p> |
| <p>Suggestions point to one or more spans with corresponding code that will |
| replace their current content.</p> |
| <p>The message that accompanies them should be understandable in the following |
| contexts:</p> |
| <ul> |
| <li>shown as an independent sub-diagnostic (this is the default output)</li> |
| <li>shown as a label pointing at the affected span (this is done automatically if |
| some heuristics for verbosity are met)</li> |
| <li>shown as a <code>help</code> sub-diagnostic with no content (used for cases where the |
| suggestion is obvious from the text, but we still want to let tools to apply |
| them)</li> |
| <li>not shown (used for <em>very</em> obvious cases, but we still want to allow tools to |
| apply them)</li> |
| </ul> |
| <p>For example, to make our <code>qux</code> suggestion machine-applicable, we would do:</p> |
| <pre><code class="language-rust ignore">let mut err = sess.dcx.struct_span_err(sp, fluent::example::message); |
| |
| if let Ok(snippet) = sess.source_map().span_to_snippet(sp) { |
| err.span_suggestion( |
| suggestion_sp, |
| fluent::example::try_qux_suggestion, |
| format!("qux {}", snippet), |
| Applicability::MachineApplicable, |
| ); |
| } else { |
| err.span_help(suggestion_sp, fluent::example::qux_suggestion); |
| } |
| |
| err.emit();</code></pre> |
| <p>This might emit an error like</p> |
| <pre><code class="language-console">$ rustc mycode.rs |
| error[E0999]: oh no! this is an error! |
| --> mycode.rs:3:5 |
| | |
| 3 | sad() |
| | ^ help: try using a qux here: `qux sad()` |
| |
| error: aborting due to previous error |
| |
| For more information about this error, try `rustc --explain E0999`. |
| </code></pre> |
| <p>In some cases, like when the suggestion spans multiple lines or when there are |
| multiple suggestions, the suggestions are displayed on their own:</p> |
| <pre><code class="language-console">error[E0999]: oh no! this is an error! |
| --> mycode.rs:3:5 |
| | |
| 3 | sad() |
| | ^ |
| help: try using a qux here: |
| | |
| 3 | qux sad() |
| | ^^^ |
| |
| error: aborting due to previous error |
| |
| For more information about this error, try `rustc --explain E0999`. |
| </code></pre> |
| <p>The possible values of <a href="https://doc.rust-lang.org/nightly/nightly-rustc/rustc_errors/enum.Applicability.html"><code>Applicability</code></a> are:</p> |
| <ul> |
| <li><code>MachineApplicable</code>: Can be applied mechanically.</li> |
| <li><code>HasPlaceholders</code>: Cannot be applied mechanically because it has placeholder |
| text in the suggestions. For example: <code>try adding a type: `let x: <type>` </code>.</li> |
| <li><code>MaybeIncorrect</code>: Cannot be applied mechanically because the suggestion may |
| or may not be a good one.</li> |
| <li><code>Unspecified</code>: Cannot be applied mechanically because we don't know which |
| of the above cases it falls into.</li> |
| </ul> |
| <h3 id="suggestion-style-guide"><a class="header" href="#suggestion-style-guide">Suggestion Style Guide</a></h3> |
| <ul> |
| <li> |
| <p>Suggestions should not be a question. In particular, language like "did you |
| mean" should be avoided. Sometimes, it's unclear why a particular suggestion |
| is being made. In these cases, it's better to be upfront about what the |
| suggestion is.</p> |
| <p>Compare "did you mean: <code>Foo</code>" vs. "there is a struct with a similar name: <code>Foo</code>".</p> |
| </li> |
| <li> |
| <p>The message should not contain any phrases like "the following", "as shown", |
| etc. Use the span to convey what is being talked about.</p> |
| </li> |
| <li> |
| <p>The message may contain further instruction such as "to do xyz, use" or "to do |
| xyz, use abc".</p> |
| </li> |
| <li> |
| <p>The message may contain a name of a function, variable, or type, but avoid |
| whole expressions.</p> |
| </li> |
| </ul> |
| <h2 id="lints"><a class="header" href="#lints">Lints</a></h2> |
| <p>The compiler linting infrastructure is defined in the <a href="https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/lint/index.html"><code>rustc_middle::lint</code></a> |
| module.</p> |
| <h3 id="when-do-lints-run"><a class="header" href="#when-do-lints-run">When do lints run?</a></h3> |
| <p>Different lints will run at different times based on what information the lint |
| needs to do its job. Some lints get grouped into <em>passes</em> where the lints |
| within a pass are processed together via a single visitor. Some of the passes |
| are:</p> |
| <ul> |
| <li> |
| <p>Pre-expansion pass: Works on <a href="the-parser.html">AST nodes</a> before <a href="macro-expansion.html">macro expansion</a>. This |
| should generally be avoided.</p> |
| <ul> |
| <li>Example: <a href="https://doc.rust-lang.org/rustc/lints/listing/allowed-by-default.html#keyword-idents"><code>keyword_idents</code></a> checks for identifiers that will become |
| keywords in future editions, but is sensitive to identifiers used in |
| macros.</li> |
| </ul> |
| </li> |
| <li> |
| <p>Early lint pass: Works on <a href="the-parser.html">AST nodes</a> after <a href="macro-expansion.html">macro expansion</a> and name |
| resolution, just before <a href="./hir/lowering.html">AST lowering</a>. These lints are for purely |
| syntactical lints.</p> |
| <ul> |
| <li>Example: The <a href="https://doc.rust-lang.org/rustc/lints/listing/warn-by-default.html#unused-parens"><code>unused_parens</code></a> lint checks for parenthesized-expressions |
| in situations where they are not needed, like an <code>if</code> condition.</li> |
| </ul> |
| </li> |
| <li> |
| <p>Late lint pass: Works on <a href="hir.html">HIR nodes</a>, towards the end of <a href="part-4-intro.html">analysis</a> (after |
| borrow checking, etc.). These lints have full type information available. |
| Most lints are late.</p> |
| <ul> |
| <li>Example: The <a href="https://doc.rust-lang.org/rustc/lints/listing/warn-by-default.html#invalid-value"><code>invalid_value</code></a> lint (which checks for obviously invalid |
| uninitialized values) is a late lint because it needs type information to |
| figure out whether a type allows being left uninitialized.</li> |
| </ul> |
| </li> |
| <li> |
| <p>MIR pass: Works on <a href="mir/index.html">MIR nodes</a>. This isn't quite the same as other passes; |
| lints that work on MIR nodes have their own methods for running.</p> |
| <ul> |
| <li>Example: The <a href="https://doc.rust-lang.org/rustc/lints/listing/deny-by-default.html#arithmetic-overflow"><code>arithmetic_overflow</code></a> lint is emitted when it detects a |
| constant value that may overflow.</li> |
| </ul> |
| </li> |
| </ul> |
| <p>Most lints work well via the pass systems, and they have a fairly |
| straightforward interface and easy way to integrate (mostly just implementing |
| a specific <code>check</code> function). However, some lints are easier to write when |
| they live on a specific code path anywhere in the compiler. For example, the |
| <a href="https://doc.rust-lang.org/rustc/lints/listing/warn-by-default.html#unused-mut"><code>unused_mut</code></a> lint is implemented in the borrow checker as it requires some |
| information and state in the borrow checker.</p> |
| <p>Some of these inline lints fire before the linting system is ready. Those |
| lints will be <em>buffered</em> where they are held until later phases of the |
| compiler when the linting system is ready. See <a href="#linting-early-in-the-compiler">Linting early in the |
| compiler</a>.</p> |
| <h3 id="lint-definition-terms"><a class="header" href="#lint-definition-terms">Lint definition terms</a></h3> |
| <p>Lints are managed via the <a href="diagnostics/lintstore.html"><code>LintStore</code></a> and get registered in |
| various ways. The following terms refer to the different classes of lints |
| generally based on how they are registered.</p> |
| <ul> |
| <li><em>Built-in</em> lints are defined inside the compiler source.</li> |
| <li><em>Driver-registered</em> lints are registered when the compiler driver is created |
| by an external driver. This is the mechanism used by Clippy, for example.</li> |
| <li><em>Tool</em> lints are lints with a path prefix like <code>clippy::</code> or <code>rustdoc::</code>.</li> |
| <li><em>Internal</em> lints are the <code>rustc::</code> scoped tool lints that only run on the |
| rustc source tree itself and are defined in the compiler source like a |
| regular built-in lint.</li> |
| </ul> |
| <p>More information about lint registration can be found in the <a href="diagnostics/lintstore.html">LintStore</a> |
| chapter.</p> |
| <h3 id="declaring-a-lint"><a class="header" href="#declaring-a-lint">Declaring a lint</a></h3> |
| <p>The built-in compiler lints are defined in the <a href="https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/index.html"><code>rustc_lint</code></a> |
| crate. Lints that need to be implemented in other crates are defined in |
| <a href="https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint_defs/index.html"><code>rustc_lint_defs</code></a>. You should prefer to place lints in <code>rustc_lint</code> if |
| possible. One benefit is that it is close to the dependency root, so it can be |
| much faster to work on.</p> |
| <p>Every lint is implemented via a <code>struct</code> that implements the <code>LintPass</code> <code>trait</code> |
| (you can also implement one of the more specific lint pass traits, either |
| <code>EarlyLintPass</code> or <code>LateLintPass</code> depending on when is best for your lint to run). |
| The trait implementation allows you to check certain syntactic constructs |
| as the linter walks the AST. You can then choose to emit lints in a |
| very similar way to compile errors.</p> |
| <p>You also declare the metadata of a particular lint via the <a href="https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint_defs/macro.declare_lint.html"><code>declare_lint!</code></a> |
| macro. This macro includes the name, the default level, a short description, and some |
| more details.</p> |
| <p>Note that the lint and the lint pass must be registered with the compiler.</p> |
| <p>For example, the following lint checks for uses |
| of <code>while true { ... }</code> and suggests using <code>loop { ... }</code> instead.</p> |
| <pre><code class="language-rust ignore">// Declare a lint called `WHILE_TRUE` |
| declare_lint! { |
| WHILE_TRUE, |
| |
| // warn-by-default |
| Warn, |
| |
| // This string is the lint description |
| "suggest using `loop { }` instead of `while true { }`" |
| } |
| |
| // This declares a struct and a lint pass, providing a list of associated lints. The |
| // compiler currently doesn't use the associated lints directly (e.g., to not |
| // run the pass or otherwise check that the pass emits the appropriate set of |
| // lints). However, it's good to be accurate here as it's possible that we're |
| // going to register the lints via the get_lints method on our lint pass (that |
| // this macro generates). |
| declare_lint_pass!(WhileTrue => [WHILE_TRUE]); |
| |
| // Helper function for `WhileTrue` lint. |
| // Traverse through any amount of parenthesis and return the first non-parens expression. |
| fn pierce_parens(mut expr: &ast::Expr) -> &ast::Expr { |
| while let ast::ExprKind::Paren(sub) = &expr.kind { |
| expr = sub; |
| } |
| expr |
| } |
| |
| // `EarlyLintPass` has lots of methods. We only override the definition of |
| // `check_expr` for this lint because that's all we need, but you could |
| // override other methods for your own lint. See the rustc docs for a full |
| // list of methods. |
| impl EarlyLintPass for WhileTrue { |
| fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &ast::Expr) { |
| if let ast::ExprKind::While(cond, ..) = &e.kind |
| && let ast::ExprKind::Lit(ref lit) = pierce_parens(cond).kind |
| && let ast::LitKind::Bool(true) = lit.kind |
| && !lit.span.from_expansion() |
| { |
| let condition_span = cx.sess.source_map().guess_head_span(e.span); |
| cx.struct_span_lint(WHILE_TRUE, condition_span, |lint| { |
| lint.build(fluent::example::use_loop) |
| .span_suggestion_short( |
| condition_span, |
| fluent::example::suggestion, |
| "loop".to_owned(), |
| Applicability::MachineApplicable, |
| ) |
| .emit(); |
| }) |
| } |
| } |
| }</code></pre> |
| <pre><code class="language-fluent">example-use-loop = denote infinite loops with `loop {"{"} ... {"}"}` |
| .suggestion = use `loop` |
| </code></pre> |
| <h3 id="edition-gated-lints"><a class="header" href="#edition-gated-lints">Edition-gated lints</a></h3> |
| <p>Sometimes we want to change the behavior of a lint in a new edition. To do this, |
| we just add the transition to our invocation of <code>declare_lint!</code>:</p> |
| <pre><code class="language-rust ignore">declare_lint! { |
| pub ANONYMOUS_PARAMETERS, |
| Allow, |
| "detects anonymous parameters", |
| Edition::Edition2018 => Warn, |
| }</code></pre> |
| <p>This makes the <code>ANONYMOUS_PARAMETERS</code> lint allow-by-default in the 2015 edition |
| but warn-by-default in the 2018 edition.</p> |
| <p>See <a href="./guides/editions.html#edition-specific-lints">Edition-specific lints</a> for more information.</p> |
| <h3 id="feature-gated-lints"><a class="header" href="#feature-gated-lints">Feature-gated lints</a></h3> |
| <p>Lints belonging to a feature should only be usable if the feature is enabled in the |
| crate. To support this, lint declarations can contain a feature gate like so:</p> |
| <pre><code class="language-rust ignore">declare_lint! { |
| pub SOME_LINT_NAME, |
| Warn, |
| "a new and useful, but feature gated lint", |
| @feature_gate = sym::feature_name; |
| }</code></pre> |
| <h3 id="future-incompatible-lints"><a class="header" href="#future-incompatible-lints">Future-incompatible lints</a></h3> |
| <p>The use of the term <code>future-incompatible</code> within the compiler has a slightly |
| broader meaning than what rustc exposes to users of the compiler.</p> |
| <p>Inside rustc, future-incompatible lints are for signalling to the user that code they have |
| written may not compile in the future. In general, future-incompatible code |
| exists for two reasons:</p> |
| <ul> |
| <li>The user has written unsound code that the compiler mistakenly accepted. While |
| it is within Rust's backwards compatibility guarantees to fix the soundness hole |
| (breaking the user's code), the lint is there to warn the user that this will happen |
| in some upcoming version of rustc <em>regardless of which edition the code uses</em>. This is the |
| meaning that rustc exclusively exposes to users as "future incompatible".</li> |
| <li>The user has written code that will either no longer compiler <em>or</em> will change |
| meaning in an upcoming <em>edition</em>. These are often called "edition lints" and can be |
| typically seen in the various "edition compatibility" lint groups (e.g., <code>rust_2021_compatibility</code>) |
| that are used to lint against code that will break if the user updates the crate's edition. |
| See <a href="guides/editions.html#migration-lints">migration lints</a> for more details.</li> |
| </ul> |
| <p>A future-incompatible lint should be declared with the <code>@future_incompatible</code> |
| additional "field":</p> |
| <pre><code class="language-rust ignore">declare_lint! { |
| pub ANONYMOUS_PARAMETERS, |
| Allow, |
| "detects anonymous parameters", |
| @future_incompatible = FutureIncompatibleInfo { |
| reference: "issue #41686 <https://github.com/rust-lang/rust/issues/41686>", |
| reason: FutureIncompatibilityReason::EditionError(Edition::Edition2018), |
| }; |
| }</code></pre> |
| <p>Notice the <code>reason</code> field which describes why the future incompatible change is happening. |
| This will change the diagnostic message the user receives as well as determine which |
| lint groups the lint is added to. In the example above, the lint is an "edition lint" |
| (since its "reason" is <code>EditionError</code>), signifying to the user that the use of anonymous |
| parameters will no longer compile in Rust 2018 and beyond.</p> |
| <p>Inside <a href="https://github.com/rust-lang/rust/blob/51fd129ac12d5bfeca7d216c47b0e337bf13e0c2/compiler/rustc_lint/src/context.rs#L212-L237">LintStore::register_lints</a>, lints with <code>future_incompatible</code> |
| fields get placed into either edition-based lint groups (if their <code>reason</code> is tied to |
| an edition) or into the <code>future_incompatibility</code> lint group.</p> |
| <p>If you need a combination of options that's not supported by the |
| <code>declare_lint!</code> macro, you can always change the <code>declare_lint!</code> macro |
| to support this.</p> |
| <h3 id="renaming-or-removing-a-lint"><a class="header" href="#renaming-or-removing-a-lint">Renaming or removing a lint</a></h3> |
| <p>If it is determined that a lint is either improperly named or no longer needed, |
| the lint must be registered for renaming or removal, which will trigger a warning if a user tries |
| to use the old lint name. To declare a rename/remove, add a line with |
| <a href="https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/struct.LintStore.html#method.register_renamed"><code>store.register_renamed</code></a> or <a href="https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/struct.LintStore.html#method.register_removed"><code>store.register_removed</code></a> to the code of the |
| <a href="https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/fn.register_builtins.html"><code>rustc_lint::register_builtins</code></a> function.</p> |
| <pre><code class="language-rust ignore">store.register_renamed("single_use_lifetime", "single_use_lifetimes");</code></pre> |
| <h3 id="lint-groups"><a class="header" href="#lint-groups">Lint groups</a></h3> |
| <p>Lints can be turned on in groups. These groups are declared in the |
| <a href="https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/fn.register_builtins.html"><code>register_builtins</code></a> function in <a href="https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/index.html"><code>rustc_lint::lib</code></a>. The |
| <code>add_lint_group!</code> macro is used to declare a new group.</p> |
| <p>For example,</p> |
| <pre><code class="language-rust ignore">add_lint_group!(sess, |
| "nonstandard_style", |
| NON_CAMEL_CASE_TYPES, |
| NON_SNAKE_CASE, |
| NON_UPPER_CASE_GLOBALS);</code></pre> |
| <p>This defines the <code>nonstandard_style</code> group which turns on the listed lints. A |
| user can turn on these lints with a <code>!#[warn(nonstandard_style)]</code> attribute in |
| the source code, or by passing <code>-W nonstandard-style</code> on the command line.</p> |
| <p>Some lint groups are created automatically in <code>LintStore::register_lints</code>. For instance, |
| any lint declared with <code>FutureIncompatibleInfo</code> where the reason is |
| <code>FutureIncompatibilityReason::FutureReleaseError</code> (the default when |
| <code>@future_incompatible</code> is used in <code>declare_lint!</code>), will be added to |
| the <code>future_incompatible</code> lint group. Editions also have their own lint groups |
| (e.g., <code>rust_2021_compatibility</code>) automatically generated for any lints signaling |
| future-incompatible code that will break in the specified edition.</p> |
| <h3 id="linting-early-in-the-compiler"><a class="header" href="#linting-early-in-the-compiler">Linting early in the compiler</a></h3> |
| <p>On occasion, you may need to define a lint that runs before the linting system |
| has been initialized (e.g. during parsing or macro expansion). This is |
| problematic because we need to have computed lint levels to know whether we |
| should emit a warning or an error or nothing at all.</p> |
| <p>To solve this problem, we buffer the lints until the linting system is |
| processed. <a href="https://doc.rust-lang.org/nightly/nightly-rustc/rustc_session/struct.Session.html#method.buffer_lint"><code>Session</code></a> and <a href="https://doc.rust-lang.org/nightly/nightly-rustc/rustc_session/parse/struct.ParseSess.html#method.buffer_lint"><code>ParseSess</code></a> both have |
| <code>buffer_lint</code> methods that allow you to buffer a lint for later. The linting |
| system automatically takes care of handling buffered lints later.</p> |
| <p>Thus, to define a lint that runs early in the compilation, one defines a lint |
| like normal but invokes the lint with <code>buffer_lint</code>.</p> |
| <h4 id="linting-even-earlier-in-the-compiler"><a class="header" href="#linting-even-earlier-in-the-compiler">Linting even earlier in the compiler</a></h4> |
| <p>The parser (<code>rustc_ast</code>) is interesting in that it cannot have dependencies on |
| any of the other <code>rustc*</code> crates. In particular, it cannot depend on |
| <code>rustc_middle::lint</code> or <code>rustc_lint</code>, where all of the compiler linting |
| infrastructure is defined. That's troublesome!</p> |
| <p>To solve this, <code>rustc_ast</code> defines its own buffered lint type, which |
| <code>ParseSess::buffer_lint</code> uses. After macro expansion, these buffered lints are |
| then dumped into the <code>Session::buffered_lints</code> used by the rest of the compiler.</p> |
| <h2 id="json-diagnostic-output"><a class="header" href="#json-diagnostic-output">JSON diagnostic output</a></h2> |
| <p>The compiler accepts an <code>--error-format json</code> flag to output |
| diagnostics as JSON objects (for the benefit of tools such as <code>cargo fix</code>). It looks like this:</p> |
| <pre><code class="language-console">$ rustc json_error_demo.rs --error-format json |
| {"message":"cannot add `&str` to `{integer}`","code":{"code":"E0277","explanation":"\nYou tried to use a type which doesn't implement some trait in a place which\nexpected that trait. Erroneous code example:\n\n```compile_fail,E0277\n// here we declare the Foo trait with a bar method\ntrait Foo {\n fn bar(&self);\n}\n\n// we now declare a function which takes an object implementing the Foo trait\nfn some_func<T: Foo>(foo: T) {\n foo.bar();\n}\n\nfn main() {\n // we now call the method with the i32 type, which doesn't implement\n // the Foo trait\n some_func(5i32); // error: the trait bound `i32 : Foo` is not satisfied\n}\n```\n\nIn order to fix this error, verify that the type you're using does implement\nthe trait. Example:\n\n```\ntrait Foo {\n fn bar(&self);\n}\n\nfn some_func<T: Foo>(foo: T) {\n foo.bar(); // we can now use this method since i32 implements the\n // Foo trait\n}\n\n// we implement the trait on the i32 type\nimpl Foo for i32 {\n fn bar(&self) {}\n}\n\nfn main() {\n some_func(5i32); // ok!\n}\n```\n\nOr in a generic context, an erroneous code example would look like:\n\n```compile_fail,E0277\nfn some_func<T>(foo: T) {\n println!(\"{:?}\", foo); // error: the trait `core::fmt::Debug` is not\n // implemented for the type `T`\n}\n\nfn main() {\n // We now call the method with the i32 type,\n // which *does* implement the Debug trait.\n some_func(5i32);\n}\n```\n\nNote that the error here is in the definition of the generic function: Although\nwe only call it with a parameter that does implement `Debug`, the compiler\nstill rejects the function: It must work with all possible input types. In\norder to make this example compile, we need to restrict the generic type we're\naccepting:\n\n```\nuse std::fmt;\n\n// Restrict the input type to types that implement Debug.\nfn some_func<T: fmt::Debug>(foo: T) {\n println!(\"{:?}\", foo);\n}\n\nfn main() {\n // Calling the method is still fine, as i32 implements Debug.\n some_func(5i32);\n\n // This would fail to compile now:\n // struct WithoutDebug;\n // some_func(WithoutDebug);\n}\n```\n\nRust only looks at the signature of the called function, as such it must\nalready specify all requirements that will be used for every type parameter.\n"},"level":"error","spans":[{"file_name":"json_error_demo.rs","byte_start":50,"byte_end":51,"line_start":4,"line_end":4,"column_start":7,"column_end":8,"is_primary":true,"text":[{"text":" a + b","highlight_start":7,"highlight_end":8}],"label":"no implementation for `{integer} + &str`","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"the trait `std::ops::Add<&str>` is not implemented for `{integer}`","code":null,"level":"help","spans":[],"children":[],"rendered":null}],"rendered":"error[E0277]: cannot add `&str` to `{integer}`\n --> json_error_demo.rs:4:7\n |\n4 | a + b\n | ^ no implementation for `{integer} + &str`\n |\n = help: the trait `std::ops::Add<&str>` is not implemented for `{integer}`\n\n"} |
| {"message":"aborting due to previous error","code":null,"level":"error","spans":[],"children":[],"rendered":"error: aborting due to previous error\n\n"} |
| {"message":"For more information about this error, try `rustc --explain E0277`.","code":null,"level":"","spans":[],"children":[],"rendered":"For more information about this error, try `rustc --explain E0277`.\n"} |
| </code></pre> |
| <p>Note that the output is a series of lines, each of which is a JSON |
| object, but the series of lines taken together is, unfortunately, not |
| valid JSON, thwarting tools and tricks (such as <a href="https://docs.python.org/3/library/json.html#module-json.tool">piping to <code>python3 -m json.tool</code></a>) |
| that require such. (One speculates that this was intentional for LSP |
| performance purposes, so that each line/object can be sent as |
| it is flushed?)</p> |
| <p>Also note the "rendered" field, which contains the "human" output as a |
| string; this was introduced so that UI tests could both make use of |
| the structured JSON and see the "human" output (well, <em>sans</em> colors) |
| without having to compile everything twice.</p> |
| <p>The "human" readable and the json format emitter can be found under |
| <code>rustc_errors</code>, both were moved from the <code>rustc_ast</code> crate to the |
| <a href="https://doc.rust-lang.org/nightly/nightly-rustc/rustc_errors/index.html">rustc_errors crate</a>.</p> |
| <p>The JSON emitter defines <a href="https://doc.rust-lang.org/nightly/nightly-rustc/rustc_errors/json/struct.Diagnostic.html">its own <code>Diagnostic</code> |
| struct</a> |
| (and sub-structs) for the JSON serialization. Don't confuse this with |
| <a href="https://doc.rust-lang.org/nightly/nightly-rustc/rustc_errors/struct.Diag.html"><code>errors::Diag</code></a>!</p> |
| <h2 id="rustc_on_unimplemented"><a class="header" href="#rustc_on_unimplemented"><code>#[rustc_on_unimplemented]</code></a></h2> |
| <p>This attribute allows trait definitions to modify error messages when an implementation was |
| expected but not found. The string literals in the attribute are format strings and can be |
| formatted with named parameters. See the Formatting |
| section below for what parameters are permitted.</p> |
| <pre><code class="language-rust ignore">#[rustc_on_unimplemented(message = "an iterator over \ |
| elements of type `{A}` cannot be built from a \ |
| collection of type `{Self}`")] |
| trait MyIterator<A> { |
| fn next(&mut self) -> A; |
| } |
| |
| fn iterate_chars<I: MyIterator<char>>(i: I) { |
| // ... |
| } |
| |
| fn main() { |
| iterate_chars(&[1, 2, 3][..]); |
| }</code></pre> |
| <p>When the user compiles this, they will see the following;</p> |
| <pre><code class="language-txt">error[E0277]: an iterator over elements of type `char` cannot be built from a collection of type `&[{integer}]` |
| --> src/main.rs:13:19 |
| | |
| 13 | iterate_chars(&[1, 2, 3][..]); |
| | ------------- ^^^^^^^^^^^^^^ the trait `MyIterator<char>` is not implemented for `&[{integer}]` |
| | | |
| | required by a bound introduced by this call |
| | |
| note: required by a bound in `iterate_chars` |
| </code></pre> |
| <p>You can modify the contents of:</p> |
| <ul> |
| <li>the main error message (<code>message</code>)</li> |
| <li>the label (<code>label</code>)</li> |
| <li>the note(s) (<code>note</code>)</li> |
| </ul> |
| <p>For example, the following attribute</p> |
| <pre><code class="language-rust ignore">#[rustc_on_unimplemented(message = "message", label = "label", note = "note")] |
| trait MyIterator<A> { |
| fn next(&mut self) -> A; |
| }</code></pre> |
| <p>Would generate the following output:</p> |
| <pre><code class="language-text">error[E0277]: message |
| --> <file>:10:19 |
| | |
| 10 | iterate_chars(&[1, 2, 3][..]); |
| | ------------- ^^^^^^^^^^^^^^ label |
| | | |
| | required by a bound introduced by this call |
| | |
| = help: the trait `MyIterator<char>` is not implemented for `&[{integer}]` |
| = note: note |
| note: required by a bound in `iterate_chars` |
| </code></pre> |
| <p>The functionality discussed so far is also available with |
| <a href="https://doc.rust-lang.org/nightly/reference/attributes/diagnostics.html#the-diagnosticon_unimplemented-attribute"><code>#[diagnostic::on_unimplemented]</code></a>. |
| If you can, you should use that instead.</p> |
| <h3 id="filtering"><a class="header" href="#filtering">Filtering</a></h3> |
| <p>To allow more targeted error messages, it is possible to filter the |
| application of these fields with <code>on</code>.</p> |
| <p>You can filter on the following boolean flags:</p> |
| <ul> |
| <li><code>crate_local</code>: whether the code causing the trait bound to not be |
| fulfilled is part of the user's crate. This is used to avoid suggesting |
| code changes that would require modifying a dependency.</li> |
| <li><code>direct</code>: whether this is an user-specified rather than derived obligation.</li> |
| <li><code>from_desugaring</code>: whether we are in some kind of desugaring, like <code>?</code> |
| or a <code>try</code> block for example. This flag can also be matched on, see below.</li> |
| </ul> |
| <p>You can match on the following names and values, using <code>name = "value"</code>:</p> |
| <ul> |
| <li><code>cause</code>: Match against one variant of the <code>ObligationCauseCode</code> |
| enum. Only <code>"MainFunctionType"</code> is supported.</li> |
| <li><code>from_desugaring</code>: Match against a particular variant of the <code>DesugaringKind</code> |
| enum. The desugaring is identified by its variant name, for example |
| <code>"QuestionMark"</code> for <code>?</code> desugaring or <code>"TryBlock"</code> for <code>try</code> blocks.</li> |
| <li><code>Self</code> and any generic arguments of the trait, like <code>Self = "alloc::string::String"</code> |
| or <code>Rhs="i32"</code>.</li> |
| </ul> |
| <p>The compiler can provide several values to match on, for example:</p> |
| <ul> |
| <li>the self_ty, pretty printed with and without type arguments resolved.</li> |
| <li><code>"{integral}"</code>, if self_ty is an integral of which the type is known.</li> |
| <li><code>"[]"</code>, <code>"[{ty}]"</code>, <code>"[{ty}; _]"</code>, <code>"[{ty}; $N]"</code> when applicable.</li> |
| <li>references to said slices and arrays.</li> |
| <li><code>"fn"</code>, <code>"unsafe fn"</code> or <code>"#[target_feature] fn"</code> when self is a function.</li> |
| <li><code>"{integer}"</code> and <code>"{float}"</code> if the type is a number but we haven't inferred it yet.</li> |
| <li>combinations of the above, like <code>"[{integral}; _]"</code>.</li> |
| </ul> |
| <p>For example, the <code>Iterator</code> trait can be filtered in the following way:</p> |
| <pre><code class="language-rust ignore">#[rustc_on_unimplemented( |
| on(Self = "&str", note = "call `.chars()` or `.as_bytes()` on `{Self}`"), |
| message = "`{Self}` is not an iterator", |
| label = "`{Self}` is not an iterator", |
| note = "maybe try calling `.iter()` or a similar method" |
| )] |
| pub trait Iterator {}</code></pre> |
| <p>Which would produce the following outputs:</p> |
| <pre><code class="language-text">error[E0277]: `Foo` is not an iterator |
| --> src/main.rs:4:16 |
| | |
| 4 | for foo in Foo {} |
| | ^^^ `Foo` is not an iterator |
| | |
| = note: maybe try calling `.iter()` or a similar method |
| = help: the trait `std::iter::Iterator` is not implemented for `Foo` |
| = note: required by `std::iter::IntoIterator::into_iter` |
| |
| error[E0277]: `&str` is not an iterator |
| --> src/main.rs:5:16 |
| | |
| 5 | for foo in "" {} |
| | ^^ `&str` is not an iterator |
| | |
| = note: call `.chars()` or `.bytes() on `&str` |
| = help: the trait `std::iter::Iterator` is not implemented for `&str` |
| = note: required by `std::iter::IntoIterator::into_iter` |
| </code></pre> |
| <p>The <code>on</code> filter accepts <code>all</code>, <code>any</code> and <code>not</code> predicates similar to the <code>cfg</code> attribute:</p> |
| <pre><code class="language-rust ignore">#[rustc_on_unimplemented(on( |
| all(Self = "&str", T = "alloc::string::String"), |
| note = "you can coerce a `{T}` into a `{Self}` by writing `&*variable`" |
| ))] |
| pub trait From<T>: Sized { |
| /* ... */ |
| }</code></pre> |
| <h3 id="formatting"><a class="header" href="#formatting">Formatting</a></h3> |
| <p>The string literals are format strings that accept parameters wrapped in braces |
| but positional and listed parameters and format specifiers are not accepted. |
| The following parameter names are valid:</p> |
| <ul> |
| <li><code>Self</code> and all generic parameters of the trait.</li> |
| <li><code>This</code>: the name of the trait the attribute is on, without generics.</li> |
| <li><code>Trait</code>: the name of the "sugared" trait. See <code>TraitRefPrintSugared</code>.</li> |
| <li><code>ItemContext</code>: the kind of <code>hir::Node</code> we're in, things like <code>"an async block"</code>, |
| <code>"a function"</code>, <code>"an async function"</code>, etc.</li> |
| </ul> |
| <p>Something like:</p> |
| <pre><code class="language-rust ignore">#![feature(rustc_attrs)] |
| |
| #[rustc_on_unimplemented(message = "Self = `{Self}`, \ |
| T = `{T}`, this = `{This}`, trait = `{Trait}`, \ |
| context = `{ItemContext}`")] |
| pub trait From<T>: Sized { |
| fn from(x: T) -> Self; |
| } |
| |
| fn main() { |
| let x: i8 = From::from(42_i32); |
| }</code></pre> |
| <p>Will format the message into</p> |
| <pre><code class="language-text">"Self = `i8`, T = `i32`, this = `From`, trait = `From<i32>`, context = `a function`" |
| </code></pre> |
| <hr> |
| <ol class="footnote-definition"><li id="footnote-estebank"> |
| <p>This rule of thumb was suggested by <strong>@estebank</strong> <a href="https://github.com/rust-lang/rustc-dev-guide/pull/967#issuecomment-733218283">here</a>. <a href="#fr-estebank-1">↩</a></p> |
| </li> |
| </ol> |
| </main> |
| |
| <nav class="nav-wrapper" aria-label="Page navigation"> |
| <!-- Mobile navigation buttons --> |
| <a rel="prev" href="rustc-driver/getting-diagnostics.html" class="mobile-nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left"> |
| <i class="fa fa-angle-left"></i> |
| </a> |
| |
| <a rel="next prefetch" href="diagnostics/diagnostic-structs.html" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right"> |
| <i class="fa fa-angle-right"></i> |
| </a> |
| |
| <div style="clear: both"></div> |
| </nav> |
| </div> |
| </div> |
| |
| <nav class="nav-wide-wrapper" aria-label="Page navigation"> |
| <a rel="prev" href="rustc-driver/getting-diagnostics.html" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left"> |
| <i class="fa fa-angle-left"></i> |
| </a> |
| |
| <a rel="next prefetch" href="diagnostics/diagnostic-structs.html" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right"> |
| <i class="fa fa-angle-right"></i> |
| </a> |
| </nav> |
| |
| </div> |
| |
| |
| |
| |
| <script> |
| window.playground_copyable = true; |
| </script> |
| |
| |
| <script src="elasticlunr.min.js"></script> |
| <script src="mark.min.js"></script> |
| <script src="searcher.js"></script> |
| |
| <script src="clipboard.min.js"></script> |
| <script src="highlight.js"></script> |
| <script src="book.js"></script> |
| |
| <!-- Custom JS scripts --> |
| <script src="mermaid.min.js"></script> |
| <script src="mermaid-init.js"></script> |
| |
| |
| </div> |
| </body> |
| </html> |