blob: 23bb667b5a07ce211745d14d3614637e9ff6b628 [file] [log] [blame] [edit]
<!DOCTYPE HTML>
<html lang="en" class="light sidebar-visible" dir="ltr">
<head>
<!-- Book generated using mdBook -->
<meta charset="UTF-8">
<title>Diagnostic and subdiagnostic structs - 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-de23e50b.svg">
<link rel="shortcut icon" href="../favicon-8114d1fc.png">
<link rel="stylesheet" href="../css/variables-8adf115d.css">
<link rel="stylesheet" href="../css/general-2459343d.css">
<link rel="stylesheet" href="../css/chrome-ae938929.css">
<link rel="stylesheet" href="../css/print-9e4910d8.css" media="print">
<!-- Fonts -->
<link rel="stylesheet" href="../fonts/fonts-9644e21d.css">
<!-- Highlight.js Stylesheets -->
<link rel="stylesheet" id="mdbook-highlight-css" href="../highlight-493f70e1.css">
<link rel="stylesheet" id="mdbook-tomorrow-night-css" href="../tomorrow-night-4c0ae647.css">
<link rel="stylesheet" id="mdbook-ayu-highlight-css" href="../ayu-highlight-3fdfc3ac.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";
window.path_to_searchindex_js = "../searchindex-a3921cfd.js";
</script>
<!-- Start loading toc.js asap -->
<script src="../toc-190e7008.js"></script>
</head>
<body>
<div id="mdbook-help-container">
<div id="mdbook-help-popup">
<h2 class="mdbook-help-title">Keyboard shortcuts</h2>
<div>
<p>Press <kbd></kbd> or <kbd></kbd> to navigate between chapters</p>
<p>Press <kbd>S</kbd> or <kbd>/</kbd> to search in the book</p>
<p>Press <kbd>?</kbd> to show this help</p>
<p>Press <kbd>Esc</kbd> to hide this help</p>
</div>
</div>
</div>
<div id="mdbook-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="mdbook-sidebar-toggle-anchor" class="hidden">
<!-- Hide / unhide sidebar before it is displayed -->
<script>
let sidebar = null;
const sidebar_toggle = document.getElementById("mdbook-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 = false;
}
if (sidebar === 'visible') {
sidebar_toggle.checked = true;
} else {
html.classList.remove('sidebar-visible');
}
</script>
<nav id="mdbook-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="mdbook-sidebar-resize-handle" class="sidebar-resize-handle">
<div class="sidebar-resize-indicator"></div>
</div>
</nav>
<div id="mdbook-page-wrapper" class="page-wrapper">
<div class="page">
<div id="mdbook-menu-bar-hover-placeholder"></div>
<div id="mdbook-menu-bar" class="menu-bar sticky">
<div class="left-buttons">
<label id="mdbook-sidebar-toggle" class="icon-button" for="mdbook-sidebar-toggle-anchor" title="Toggle Table of Contents" aria-label="Toggle Table of Contents" aria-controls="mdbook-sidebar">
<span class=fa-svg><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Free 6.2.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2022 Fonticons, Inc. --><path d="M0 96C0 78.3 14.3 64 32 64H416c17.7 0 32 14.3 32 32s-14.3 32-32 32H32C14.3 128 0 113.7 0 96zM0 256c0-17.7 14.3-32 32-32H416c17.7 0 32 14.3 32 32s-14.3 32-32 32H32c-17.7 0-32-14.3-32-32zM448 416c0 17.7-14.3 32-32 32H32c-17.7 0-32-14.3-32-32s14.3-32 32-32H416c17.7 0 32 14.3 32 32z"/></svg></span>
</label>
<button id="mdbook-theme-toggle" class="icon-button" type="button" title="Change theme" aria-label="Change theme" aria-haspopup="true" aria-expanded="false" aria-controls="mdbook-theme-list">
<span class=fa-svg><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512"><!--! Font Awesome Free 6.2.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2022 Fonticons, Inc. --><path d="M371.3 367.1c27.3-3.9 51.9-19.4 67.2-42.9L600.2 74.1c12.6-19.5 9.4-45.3-7.6-61.2S549.7-4.4 531.1 9.6L294.4 187.2c-24 18-38.2 46.1-38.4 76.1L371.3 367.1zm-19.6 25.4l-116-104.4C175.9 290.3 128 339.6 128 400c0 3.9 .2 7.8 .6 11.6c1.8 17.5-10.2 36.4-27.8 36.4H96c-17.7 0-32 14.3-32 32s14.3 32 32 32H240c61.9 0 112-50.1 112-112c0-2.5-.1-5-.2-7.5z"/></svg></span>
</button>
<ul id="mdbook-theme-list" class="theme-popup" aria-label="Themes" role="menu">
<li role="none"><button role="menuitem" class="theme" id="mdbook-theme-default_theme">Auto</button></li>
<li role="none"><button role="menuitem" class="theme" id="mdbook-theme-light">Light</button></li>
<li role="none"><button role="menuitem" class="theme" id="mdbook-theme-rust">Rust</button></li>
<li role="none"><button role="menuitem" class="theme" id="mdbook-theme-coal">Coal</button></li>
<li role="none"><button role="menuitem" class="theme" id="mdbook-theme-navy">Navy</button></li>
<li role="none"><button role="menuitem" class="theme" id="mdbook-theme-ayu">Ayu</button></li>
</ul>
<button id="mdbook-search-toggle" class="icon-button" type="button" title="Search (`/`)" aria-label="Toggle Searchbar" aria-expanded="false" aria-keyshortcuts="/ s" aria-controls="mdbook-searchbar">
<span class=fa-svg><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Free 6.2.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2022 Fonticons, Inc. --><path d="M416 208c0 45.9-14.9 88.3-40 122.7L502.6 457.4c12.5 12.5 12.5 32.8 0 45.3s-32.8 12.5-45.3 0L330.7 376c-34.4 25.2-76.8 40-122.7 40C93.1 416 0 322.9 0 208S93.1 0 208 0S416 93.1 416 208zM208 352c79.5 0 144-64.5 144-144s-64.5-144-144-144S64 128.5 64 208s64.5 144 144 144z"/></svg></span>
</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">
<span class=fa-svg id="print-button"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Free 6.2.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2022 Fonticons, Inc. --><path d="M128 0C92.7 0 64 28.7 64 64v96h64V64H354.7L384 93.3V160h64V93.3c0-17-6.7-33.3-18.7-45.3L400 18.7C388 6.7 371.7 0 354.7 0H128zM384 352v32 64H128V384 368 352H384zm64 32h32c17.7 0 32-14.3 32-32V256c0-35.3-28.7-64-64-64H64c-35.3 0-64 28.7-64 64v96c0 17.7 14.3 32 32 32H64v64c0 35.3 28.7 64 64 64H384c35.3 0 64-28.7 64-64V384zm-16-88c-13.3 0-24-10.7-24-24s10.7-24 24-24s24 10.7 24 24s-10.7 24-24 24z"/></svg></span>
</a>
<a href="https://github.com/rust-lang/rustc-dev-guide" title="Git repository" aria-label="Git repository">
<span class=fa-svg><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 496 512"><!--! Font Awesome Free 6.2.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2022 Fonticons, Inc. --><path d="M165.9 397.4c0 2-2.3 3.6-5.2 3.6-3.3.3-5.6-1.3-5.6-3.6 0-2 2.3-3.6 5.2-3.6 3-.3 5.6 1.3 5.6 3.6zm-31.1-4.5c-.7 2 1.3 4.3 4.3 4.9 2.6 1 5.6 0 6.2-2s-1.3-4.3-4.3-5.2c-2.6-.7-5.5.3-6.2 2.3zm44.2-1.7c-2.9.7-4.9 2.6-4.6 4.9.3 2 2.9 3.3 5.9 2.6 2.9-.7 4.9-2.6 4.6-4.6-.3-1.9-3-3.2-5.9-2.9zM244.8 8C106.1 8 0 113.3 0 252c0 110.9 69.8 205.8 169.5 239.2 12.8 2.3 17.3-5.6 17.3-12.1 0-6.2-.3-40.4-.3-61.4 0 0-70 15-84.7-29.8 0 0-11.4-29.1-27.8-36.6 0 0-22.9-15.7 1.6-15.4 0 0 24.9 2 38.6 25.8 21.9 38.6 58.6 27.5 72.9 20.9 2.3-16 8.8-27.1 16-33.7-55.9-6.2-112.3-14.3-112.3-110.5 0-27.5 7.6-41.3 23.6-58.9-2.6-6.5-11.1-33.3 2.6-67.9 20.9-6.5 69 27 69 27 20-5.6 41.5-8.5 62.8-8.5s42.8 2.9 62.8 8.5c0 0 48.1-33.6 69-27 13.7 34.7 5.2 61.4 2.6 67.9 16 17.7 25.8 31.5 25.8 58.9 0 96.5-58.9 104.2-114.8 110.5 9.2 7.9 17 22.9 17 46.4 0 33.7-.3 75.4-.3 83.6 0 6.5 4.6 14.4 17.3 12.1C428.2 457.8 496 362.9 496 252 496 113.3 383.5 8 244.8 8zM97.2 352.9c-1.3 1-1 3.3.7 5.2 1.6 1.6 3.9 2.3 5.2 1 1.3-1 1-3.3-.7-5.2-1.6-1.6-3.9-2.3-5.2-1zm-10.8-8.1c-.7 1.3.3 2.9 2.3 3.9 1.6 1 3.6.7 4.3-.7.7-1.3-.3-2.9-2.3-3.9-2-.6-3.6-.3-4.3.7zm32.4 35.6c-1.6 1.3-1 4.3 1.3 6.2 2.3 2.3 5.2 2.6 6.5 1 1.3-1.3.7-4.3-1.3-6.2-2.2-2.3-5.2-2.6-6.5-1zm-11.4-14.7c-1.6 1-1.6 3.6 0 5.9 1.6 2.3 4.3 3.3 5.6 2.3 1.6-1.3 1.6-3.9 0-6.2-1.4-2.3-4-3.3-5.6-2z"/></svg></span>
</a>
<a href="https://github.com/rust-lang/rustc-dev-guide/edit/main/src/diagnostics/diagnostic-structs.md" title="Suggest an edit" aria-label="Suggest an edit" rel="edit">
<span class=fa-svg id="git-edit-button"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Free 6.2.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2022 Fonticons, Inc. --><path d="M421.7 220.3l-11.3 11.3-22.6 22.6-205 205c-6.6 6.6-14.8 11.5-23.8 14.1L30.8 511c-8.4 2.5-17.5 .2-23.7-6.1S-1.5 489.7 1 481.2L38.7 353.1c2.6-9 7.5-17.2 14.1-23.8l205-205 22.6-22.6 11.3-11.3 33.9 33.9 62.1 62.1 33.9 33.9zM96 353.9l-9.3 9.3c-.9 .9-1.6 2.1-2 3.4l-25.3 86 86-25.3c1.3-.4 2.5-1.1 3.4-2l9.3-9.3H112c-8.8 0-16-7.2-16-16V353.9zM453.3 19.3l39.4 39.4c25 25 25 65.5 0 90.5l-14.5 14.5-22.6 22.6-11.3 11.3-33.9-33.9-62.1-62.1L314.3 67.7l11.3-11.3 22.6-22.6 14.5-14.5c25-25 65.5-25 90.5 0z"/></svg></span>
</a>
</div>
</div>
<div id="mdbook-search-wrapper" class="hidden">
<form id="mdbook-searchbar-outer" class="searchbar-outer">
<div class="search-wrapper">
<input type="search" id="mdbook-searchbar" name="searchbar" placeholder="Search this book ..." aria-controls="mdbook-searchresults-outer" aria-describedby="searchresults-header">
<div class="spinner-wrapper">
<span class=fa-svg id="fa-spin"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Free 6.2.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2022 Fonticons, Inc. --><path d="M304 48c0-26.5-21.5-48-48-48s-48 21.5-48 48s21.5 48 48 48s48-21.5 48-48zm0 416c0-26.5-21.5-48-48-48s-48 21.5-48 48s21.5 48 48 48s48-21.5 48-48zM48 304c26.5 0 48-21.5 48-48s-21.5-48-48-48s-48 21.5-48 48s21.5 48 48 48zm464-48c0-26.5-21.5-48-48-48s-48 21.5-48 48s21.5 48 48 48s48-21.5 48-48zM142.9 437c18.7-18.7 18.7-49.1 0-67.9s-49.1-18.7-67.9 0s-18.7 49.1 0 67.9s49.1 18.7 67.9 0zm0-294.2c18.7-18.7 18.7-49.1 0-67.9S93.7 56.2 75 75s-18.7 49.1 0 67.9s49.1 18.7 67.9 0zM369.1 437c18.7 18.7 49.1 18.7 67.9 0s18.7-49.1 0-67.9s-49.1-18.7-67.9 0s-18.7 49.1 0 67.9z"/></svg></span>
</div>
</div>
</form>
<div id="mdbook-searchresults-outer" class="searchresults-outer hidden">
<div id="mdbook-searchresults-header" class="searchresults-header"></div>
<ul id="mdbook-searchresults">
</ul>
</div>
</div>
<!-- Apply ARIA attributes after the sidebar and the sidebar toggle button are added to the DOM -->
<script>
document.getElementById('mdbook-sidebar-toggle').setAttribute('aria-expanded', sidebar === 'visible');
document.getElementById('mdbook-sidebar').setAttribute('aria-hidden', sidebar !== 'visible');
Array.from(document.querySelectorAll('#mdbook-sidebar a')).forEach(function(link) {
link.setAttribute('tabIndex', sidebar === 'visible' ? 0 : -1);
});
</script>
<div id="mdbook-content" class="content">
<main>
<h1 id="diagnostic-and-subdiagnostic-structs"><a class="header" href="#diagnostic-and-subdiagnostic-structs">Diagnostic and subdiagnostic structs</a></h1>
<p>rustc has three diagnostic traits that can be used to create diagnostics:
<code>Diagnostic</code>, <code>LintDiagnostic</code>, and <code>Subdiagnostic</code>.</p>
<p>For simple diagnostics,
derived impls can be used, e.g. <code>#[derive(Diagnostic)]</code>. They are only suitable for simple diagnostics that
don’t require much logic in deciding whether or not to add additional
subdiagnostics.</p>
<p>In cases where diagnostics require more complex or dynamic behavior, such as conditionally adding subdiagnostics,
customizing the rendering logic, or selecting messages at runtime, you will need to manually implement
the corresponding trait (<code>Diagnostic</code>, <code>LintDiagnostic</code>, or <code>Subdiagnostic</code>).
This approach provides greater flexibility and is recommended for diagnostics that go beyond simple, static structures.</p>
<p>Diagnostic can be translated into different languages and each has a slug that uniquely identifies the diagnostic.</p>
<h2 id="derivediagnostic-and-derivelintdiagnostic"><a class="header" href="#derivediagnostic-and-derivelintdiagnostic"><code>#[derive(Diagnostic)]</code> and <code>#[derive(LintDiagnostic)]</code></a></h2>
<p>Consider the <a href="https://github.com/rust-lang/rust/blob/6201eabde85db854c1ebb57624be5ec699246b50/compiler/rustc_hir_analysis/src/errors.rs#L68-L77">definition</a> of the “field already declared” diagnostic
shown below:</p>
<pre><code class="language-rust ignore">#[derive(Diagnostic)]
#[diag(hir_analysis_field_already_declared, code = E0124)]
pub struct FieldAlreadyDeclared {
pub field_name: Ident,
#[primary_span]
#[label]
pub span: Span,
#[label(previous_decl_label)]
pub prev_span: Span,
}</code></pre>
<p><code>Diagnostic</code> can only be derived on structs and enums.
Attributes that are placed on the type for structs are placed on each
variants for enums (or vice versa). Each <code>Diagnostic</code> has to have one
attribute, <code>#[diag(...)]</code>, applied to the struct or each enum variant.</p>
<p>If an error has an error code (e.g. “E0624”), then that can be specified using
the <code>code</code> sub-attribute. Specifying a <code>code</code> isn’t mandatory, but if you are
porting a diagnostic that uses <code>Diag</code> to use <code>Diagnostic</code>
then you should keep the code if there was one.</p>
<p><code>#[diag(..)]</code> must provide a slug as the first positional argument (a path to an
item in <code>rustc_errors::fluent::*</code>). A slug uniquely identifies the diagnostic
and is also how the compiler knows what error message to emit (in the default
locale of the compiler, or in the locale requested by the user). See
<a href="./translation.html">translation documentation</a> to learn more about how
translatable error messages are written and how slug items are generated.</p>
<p>In our example, the Fluent message for the “field already declared” diagnostic
looks like this:</p>
<pre><code class="language-fluent">hir_analysis_field_already_declared =
field `{$field_name}` is already declared
.label = field already declared
.previous_decl_label = `{$field_name}` first declared here
</code></pre>
<p><code>hir_analysis_field_already_declared</code> is the slug from our example and is followed
by the diagnostic message.</p>
<p>Every field of the <code>Diagnostic</code> which does not have an annotation is
available in Fluent messages as a variable, like <code>field_name</code> in the example
above. Fields can be annotated <code>#[skip_arg]</code> if this is undesired.</p>
<p>Using the <code>#[primary_span]</code> attribute on a field (that has type <code>Span</code>)
indicates the primary span of the diagnostic which will have the main message
of the diagnostic.</p>
<p>Diagnostics are more than just their primary message, they often include
labels, notes, help messages and suggestions, all of which can also be
specified on a <code>Diagnostic</code>.</p>
<p><code>#[label]</code>, <code>#[help]</code>, <code>#[warning]</code> and <code>#[note]</code> can all be applied to fields which have the
type <code>Span</code>. Applying any of these attributes will create the corresponding
subdiagnostic with that <code>Span</code>. These attributes will look for their
diagnostic message in a Fluent attribute attached to the primary Fluent
message. In our example, <code>#[label]</code> will look for
<code>hir_analysis_field_already_declared.label</code> (which has the message “field already
declared”). If there is more than one subdiagnostic of the same type, then
these attributes can also take a value that is the attribute name to look for
(e.g. <code>previous_decl_label</code> in our example).</p>
<p>Other types have special behavior when used in a <code>Diagnostic</code> derive:</p>
<ul>
<li>Any attribute applied to an <code>Option&lt;T&gt;</code> will only emit a
subdiagnostic if the option is <code>Some(..)</code>.</li>
<li>Any attribute applied to a <code>Vec&lt;T&gt;</code> will be repeated for each element of the
vector.</li>
</ul>
<p><code>#[help]</code>, <code>#[warning]</code> and <code>#[note]</code> can also be applied to the struct itself, in which case
they work exactly like when applied to fields except the subdiagnostic won’t
have a <code>Span</code>. These attributes can also be applied to fields of type <code>()</code> for
the same effect, which when combined with the <code>Option</code> type can be used to
represent optional <code>#[note]</code>/<code>#[help]</code>/<code>#[warning]</code> subdiagnostics.</p>
<p>Suggestions can be emitted using one of four field attributes:</p>
<ul>
<li><code>#[suggestion(slug, code = "...", applicability = "...")]</code></li>
<li><code>#[suggestion_hidden(slug, code = "...", applicability = "...")]</code></li>
<li><code>#[suggestion_short(slug, code = "...", applicability = "...")]</code></li>
<li><code>#[suggestion_verbose(slug, code = "...", applicability = "...")]</code></li>
</ul>
<p>Suggestions must be applied on either a <code>Span</code> field or a <code>(Span, MachineApplicability)</code> field. Similarly to other field attributes, the slug
specifies the Fluent attribute with the message and defaults to the equivalent
of <code>.suggestion</code>. <code>code</code> specifies the code that should be suggested as a
replacement and is a format string (e.g. <code>{field_name}</code> would be replaced by
the value of the <code>field_name</code> field of the struct), not a Fluent identifier.
<code>applicability</code> can be used to specify the applicability in the attribute, it
cannot be used when the field’s type contains an <code>Applicability</code>.</p>
<p>In the end, the <code>Diagnostic</code> derive will generate an implementation of
<code>Diagnostic</code> that looks like the following:</p>
<pre><code class="language-rust ignore">impl&lt;'a, G: EmissionGuarantee&gt; Diagnostic&lt;'a&gt; for FieldAlreadyDeclared {
fn into_diag(self, dcx: &amp;'a DiagCtxt, level: Level) -&gt; Diag&lt;'a, G&gt; {
let mut diag = Diag::new(dcx, level, fluent::hir_analysis_field_already_declared);
diag.set_span(self.span);
diag.span_label(
self.span,
fluent::hir_analysis_label
);
diag.span_label(
self.prev_span,
fluent::hir_analysis_previous_decl_label
);
diag
}
}</code></pre>
<p>Now that we’ve defined our diagnostic, how do we <a href="https://github.com/rust-lang/rust/blob/f1112099eba41abadb6f921df7edba70affe92c5/compiler/rustc_hir_analysis/src/collect.rs#L823-L827">use it</a>? It’s quite
straightforward, just create an instance of the struct and pass it to
<code>emit_err</code> (or <code>emit_warning</code>):</p>
<pre><code class="language-rust ignore">tcx.dcx().emit_err(FieldAlreadyDeclared {
field_name: f.ident,
span: f.span,
prev_span,
});</code></pre>
<h3 id="reference-for-derivediagnostic-and-derivelintdiagnostic"><a class="header" href="#reference-for-derivediagnostic-and-derivelintdiagnostic">Reference for <code>#[derive(Diagnostic)]</code> and <code>#[derive(LintDiagnostic)]</code></a></h3>
<p><code>#[derive(Diagnostic)]</code> and <code>#[derive(LintDiagnostic)]</code> support the
following attributes:</p>
<ul>
<li><code>#[diag(slug, code = "...")]</code>
<ul>
<li><em>Applied to struct or enum variant.</em></li>
<li><em>Mandatory</em></li>
<li>Defines the text and error code to be associated with the diagnostic.</li>
<li>Slug (<em>Mandatory</em>)
<ul>
<li>Uniquely identifies the diagnostic and corresponds to its Fluent message,
mandatory.</li>
<li>A path to an item in <code>rustc_errors::fluent</code>, e.g.
<code>rustc_errors::fluent::hir_analysis_field_already_declared</code>
(<code>rustc_errors::fluent</code> is implicit in the attribute, so just
<code>hir_analysis_field_already_declared</code>).</li>
<li>See <a href="./translation.html">translation documentation</a>.</li>
</ul>
</li>
<li><code>code = "..."</code> (<em>Optional</em>)
<ul>
<li>Specifies the error code.</li>
</ul>
</li>
</ul>
</li>
<li><code>#[note]</code> or <code>#[note(slug)]</code> (<em>Optional</em>)
<ul>
<li><em>Applied to struct or struct fields of type <code>Span</code>, <code>Option&lt;()&gt;</code> or <code>()</code>.</em></li>
<li>Adds a note subdiagnostic.</li>
<li>Value is a path to an item in <code>rustc_errors::fluent</code> for the note’s
message.
<ul>
<li>Defaults to equivalent of <code>.note</code>.</li>
</ul>
</li>
<li>If applied to a <code>Span</code> field, creates a spanned note.</li>
</ul>
</li>
<li><code>#[help]</code> or <code>#[help(slug)]</code> (<em>Optional</em>)
<ul>
<li><em>Applied to struct or struct fields of type <code>Span</code>, <code>Option&lt;()&gt;</code> or <code>()</code>.</em></li>
<li>Adds a help subdiagnostic.</li>
<li>Value is a path to an item in <code>rustc_errors::fluent</code> for the note’s
message.
<ul>
<li>Defaults to equivalent of <code>.help</code>.</li>
</ul>
</li>
<li>If applied to a <code>Span</code> field, creates a spanned help.</li>
</ul>
</li>
<li><code>#[label]</code> or <code>#[label(slug)]</code> (<em>Optional</em>)
<ul>
<li><em>Applied to <code>Span</code> fields.</em></li>
<li>Adds a label subdiagnostic.</li>
<li>Value is a path to an item in <code>rustc_errors::fluent</code> for the note’s
message.
<ul>
<li>Defaults to equivalent of <code>.label</code>.</li>
</ul>
</li>
</ul>
</li>
<li><code>#[warning]</code> or <code>#[warning(slug)]</code> (<em>Optional</em>)
<ul>
<li><em>Applied to struct or struct fields of type <code>Span</code>, <code>Option&lt;()&gt;</code> or <code>()</code>.</em></li>
<li>Adds a warning subdiagnostic.</li>
<li>Value is a path to an item in <code>rustc_errors::fluent</code> for the note’s
message.
<ul>
<li>Defaults to equivalent of <code>.warn</code>.</li>
</ul>
</li>
</ul>
</li>
<li><code>#[suggestion{,_hidden,_short,_verbose}(slug, code = "...", applicability = "...")]</code>
(<em>Optional</em>)
<ul>
<li><em>Applied to <code>(Span, MachineApplicability)</code> or <code>Span</code> fields.</em></li>
<li>Adds a suggestion subdiagnostic.</li>
<li>Slug (<em>Mandatory</em>)
<ul>
<li>A path to an item in <code>rustc_errors::fluent</code>, e.g.
<code>rustc_errors::fluent::hir_analysis_field_already_declared</code>
(<code>rustc_errors::fluent</code> is implicit in the attribute, so just
<code>hir_analysis_field_already_declared</code>). Fluent attributes for all messages
exist as top-level items in that module (so <code>hir_analysis_message.attr</code> is just
<code>attr</code>).</li>
<li>See <a href="./translation.html">translation documentation</a>.</li>
<li>Defaults to <code>rustc_errors::fluent::_subdiag::suggestion</code> (or</li>
<li><code>.suggestion</code> in Fluent).</li>
</ul>
</li>
<li><code>code = "..."</code>/<code>code("...", ...)</code> (<em>Mandatory</em>)
<ul>
<li>One or multiple format strings indicating the code to be suggested as a
replacement. Multiple values signify multiple possible replacements.</li>
</ul>
</li>
<li><code>applicability = "..."</code> (<em>Optional</em>)
<ul>
<li>String which must be one of <code>machine-applicable</code>, <code>maybe-incorrect</code>,
<code>has-placeholders</code> or <code>unspecified</code>.</li>
</ul>
</li>
</ul>
</li>
<li><code>#[subdiagnostic]</code>
<ul>
<li><em>Applied to a type that implements <code>Subdiagnostic</code> (from
<code>#[derive(Subdiagnostic)]</code>).</em></li>
<li>Adds the subdiagnostic represented by the subdiagnostic struct.</li>
</ul>
</li>
<li><code>#[primary_span]</code> (<em>Optional</em>)
<ul>
<li><em>Applied to <code>Span</code> fields on <code>Subdiagnostic</code>s. Not used for <code>LintDiagnostic</code>s.</em></li>
<li>Indicates the primary span of the diagnostic.</li>
</ul>
</li>
<li><code>#[skip_arg]</code> (<em>Optional</em>)
<ul>
<li><em>Applied to any field.</em></li>
<li>Prevents the field from being provided as a diagnostic argument.</li>
</ul>
</li>
</ul>
<h2 id="derivesubdiagnostic"><a class="header" href="#derivesubdiagnostic"><code>#[derive(Subdiagnostic)]</code></a></h2>
<p>It is common in the compiler to write a function that conditionally adds a
specific subdiagnostic to an error if it is applicable. Oftentimes these
subdiagnostics could be represented using a diagnostic struct even if the
overall diagnostic could not. In this circumstance, the <code>Subdiagnostic</code>
derive can be used to represent a partial diagnostic (e.g a note, label, help or
suggestion) as a struct.</p>
<p>Consider the <a href="https://github.com/rust-lang/rust/blob/f1112099eba41abadb6f921df7edba70affe92c5/compiler/rustc_hir_analysis/src/errors.rs#L221-L234">definition</a> of the “expected return type” label
shown below:</p>
<pre class="playground"><code class="language-rust"><span class="boring">#![allow(unused)]
</span><span class="boring">fn main() {
</span>#[derive(Subdiagnostic)]
pub enum ExpectedReturnTypeLabel&lt;'tcx&gt; {
#[label(hir_analysis_expected_default_return_type)]
Unit {
#[primary_span]
span: Span,
},
#[label(hir_analysis_expected_return_type)]
Other {
#[primary_span]
span: Span,
expected: Ty&lt;'tcx&gt;,
},
}
<span class="boring">}</span></code></pre>
<p>Like <code>Diagnostic</code>, <code>Subdiagnostic</code> can be derived for structs or
enums. Attributes that are placed on the type for structs are placed on each
variants for enums (or vice versa). Each <code>Subdiagnostic</code> should have one
attribute applied to the struct or each variant, one of:</p>
<ul>
<li><code>#[label(..)]</code> for defining a label</li>
<li><code>#[note(..)]</code> for defining a note</li>
<li><code>#[help(..)]</code> for defining a help</li>
<li><code>#[warning(..)]</code> for defining a warning</li>
<li><code>#[suggestion{,_hidden,_short,_verbose}(..)]</code> for defining a suggestion</li>
</ul>
<p>All of the above must provide a slug as the first positional argument (a path
to an item in <code>rustc_errors::fluent::*</code>). A slug uniquely identifies the
diagnostic and is also how the compiler knows what error message to emit (in
the default locale of the compiler, or in the locale requested by the user).
See <a href="./translation.html">translation documentation</a> to learn more about how
translatable error messages are written and how slug items are generated.</p>
<p>In our example, the Fluent message for the “expected return type” label
looks like this:</p>
<pre><code class="language-fluent">hir_analysis_expected_default_return_type = expected `()` because of default return type
hir_analysis_expected_return_type = expected `{$expected}` because of return type
</code></pre>
<p>Using the <code>#[primary_span]</code> attribute on a field (with type <code>Span</code>) will denote
the primary span of the subdiagnostic. A primary span is only necessary for a
label or suggestion, which can not be spanless.</p>
<p>Every field of the type/variant which does not have an annotation is available
in Fluent messages as a variable. Fields can be annotated <code>#[skip_arg]</code> if this
is undesired.</p>
<p>Like <code>Diagnostic</code>, <code>Subdiagnostic</code> supports <code>Option&lt;T&gt;</code> and
<code>Vec&lt;T&gt;</code> fields.</p>
<p>Suggestions can be emitted using one of four attributes on the type/variant:</p>
<ul>
<li><code>#[suggestion(..., code = "...", applicability = "...")]</code></li>
<li><code>#[suggestion_hidden(..., code = "...", applicability = "...")]</code></li>
<li><code>#[suggestion_short(..., code = "...", applicability = "...")]</code></li>
<li><code>#[suggestion_verbose(..., code = "...", applicability = "...")]</code></li>
</ul>
<p>Suggestions require <code>#[primary_span]</code> be set on a field and can have the
following sub-attributes:</p>
<ul>
<li>The first positional argument specifies the path to a item in
<code>rustc_errors::fluent</code> corresponding to the Fluent attribute with the message
and defaults to the equivalent of <code>.suggestion</code>.</li>
<li><code>code</code> specifies the code that should be suggested as a replacement and is a
format string (e.g. <code>{field_name}</code> would be replaced by the value of the
<code>field_name</code> field of the struct), not a Fluent identifier.</li>
<li><code>applicability</code> can be used to specify the applicability in the attribute, it
cannot be used when the field’s type contains an <code>Applicability</code>.</li>
</ul>
<p>Applicabilities can also be specified as a field (of type <code>Applicability</code>)
using the <code>#[applicability]</code> attribute.</p>
<p>In the end, the <code>Subdiagnostic</code> derive will generate an implementation
of <code>Subdiagnostic</code> that looks like the following:</p>
<pre class="playground"><code class="language-rust"><span class="boring">#![allow(unused)]
</span><span class="boring">fn main() {
</span>impl&lt;'tcx&gt; Subdiagnostic for ExpectedReturnTypeLabel&lt;'tcx&gt; {
fn add_to_diag(self, diag: &amp;mut rustc_errors::Diagnostic) {
use rustc_errors::{Applicability, IntoDiagArg};
match self {
ExpectedReturnTypeLabel::Unit { span } =&gt; {
diag.span_label(span, rustc_errors::fluent::hir_analysis_expected_default_return_type)
}
ExpectedReturnTypeLabel::Other { span, expected } =&gt; {
diag.set_arg("expected", expected);
diag.span_label(span, rustc_errors::fluent::hir_analysis_expected_return_type)
}
}
}
}
<span class="boring">}</span></code></pre>
<p>Once defined, a subdiagnostic can be used by passing it to the <code>subdiagnostic</code>
function (<a href="https://github.com/rust-lang/rust/blob/f1112099eba41abadb6f921df7edba70affe92c5/compiler/rustc_hir_analysis/src/check/fn_ctxt/suggestions.rs#L670-L674">example</a> and <a href="https://github.com/rust-lang/rust/blob/f1112099eba41abadb6f921df7edba70affe92c5/compiler/rustc_hir_analysis/src/check/fn_ctxt/suggestions.rs#L704-L707">example</a>) on a
diagnostic or by assigning it to a <code>#[subdiagnostic]</code>-annotated field of a
diagnostic struct.</p>
<h3 id="argument-sharing-and-isolation"><a class="header" href="#argument-sharing-and-isolation">Argument sharing and isolation</a></h3>
<p>Subdiagnostics add their own arguments (i.e., certain fields in their structure) to the <code>Diag</code> structure before rendering the information.
<code>Diag</code> structure also stores the arguments from the main diagnostic, so the subdiagnostic can also use the arguments from the main diagnostic.</p>
<p>However, when a subdiagnostic is added to a main diagnostic by implementing <code>#[derive(Subdiagnostic)]</code>,
the following rules, introduced in <a href="https://github.com/rust-lang/rust/pull/142724">rust-lang/rust#142724</a>
apply to the handling of arguments (i.e., variables used in Fluent messages):</p>
<p><strong>Argument isolation between sub diagnostics</strong>:
Arguments set by a subdiagnostic are only available during the rendering of that subdiagnostic.
After the subdiagnostic is rendered, all arguments it introduced are restored from the main diagnostic.
This ensures that multiple subdiagnostics do not pollute each other’s argument scope.
For example, when using a <code>Vec&lt;Subdiag&gt;</code>, it iteratively adds the same argument over and over again.</p>
<p><strong>Same argument override between sub and main diagnostics</strong>:
If a subdiagnostic sets a argument with the same name as a arguments already in the main diagnostic,
it will report an error at runtime unless both have exactly the same value.
It has two benefits:</p>
<ul>
<li>preserves the flexibility that arguments in the main diagnostic are allowed to appear in the attributes of the subdiagnostic.
For example, There is an attribute <code>#[suggestion(code = "{new_vis}")]</code> in the subdiagnostic, but <code>new_vis</code> is the field in the main diagnostic struct.</li>
<li>prevents accidental overwriting or deletion of arguments required by the main diagnostic or other subdiagnostics.</li>
</ul>
<p>These rules guarantee that arguments injected by subdiagnostics are strictly scoped to their own rendering.
The main diagnostic’s arguments remain unaffected by subdiagnostic logic, even in the presence of name collisions.
Additionally, subdiagnostics can access arguments from the main diagnostic with the same name when needed.</p>
<h3 id="reference-for-derivesubdiagnostic"><a class="header" href="#reference-for-derivesubdiagnostic">Reference for <code>#[derive(Subdiagnostic)]</code></a></h3>
<p><code>#[derive(Subdiagnostic)]</code> supports the following attributes:</p>
<ul>
<li><code>#[label(slug)]</code>, <code>#[help(slug)]</code>, <code>#[warning(slug)]</code> or <code>#[note(slug)]</code>
<ul>
<li><em>Applied to struct or enum variant. Mutually exclusive with struct/enum variant attributes.</em></li>
<li><em>Mandatory</em></li>
<li>Defines the type to be representing a label, help or note.</li>
<li>Slug (<em>Mandatory</em>)
<ul>
<li>Uniquely identifies the diagnostic and corresponds to its Fluent message,
mandatory.</li>
<li>A path to an item in <code>rustc_errors::fluent</code>, e.g.
<code>rustc_errors::fluent::hir_analysis_field_already_declared</code>
(<code>rustc_errors::fluent</code> is implicit in the attribute, so just
<code>hir_analysis_field_already_declared</code>).</li>
<li>See <a href="./translation.html">translation documentation</a>.</li>
</ul>
</li>
</ul>
</li>
<li><code>#[suggestion{,_hidden,_short,_verbose}(slug, code = "...", applicability = "...")]</code>
<ul>
<li><em>Applied to struct or enum variant. Mutually exclusive with struct/enum variant attributes.</em></li>
<li><em>Mandatory</em></li>
<li>Defines the type to be representing a suggestion.</li>
<li>Slug (<em>Mandatory</em>)
<ul>
<li>A path to an item in <code>rustc_errors::fluent</code>, e.g.
<code>rustc_errors::fluent::hir_analysis_field_already_declared</code>
(<code>rustc_errors::fluent</code> is implicit in the attribute, so just
<code>hir_analysis::field_already_declared</code>). Fluent attributes for all messages
exist as top-level items in that module (so <code>hir_analysis_message.attr</code> is just
<code>hir_analysis::attr</code>).</li>
<li>See <a href="./translation.html">translation documentation</a>.</li>
<li>Defaults to <code>rustc_errors::fluent::_subdiag::suggestion</code> (or</li>
<li><code>.suggestion</code> in Fluent).</li>
</ul>
</li>
<li><code>code = "..."</code>/<code>code("...", ...)</code> (<em>Mandatory</em>)
<ul>
<li>One or multiple format strings indicating the code to be suggested as a
replacement. Multiple values signify multiple possible replacements.</li>
</ul>
</li>
<li><code>applicability = "..."</code> (<em>Optional</em>)
<ul>
<li><em>Mutually exclusive with <code>#[applicability]</code> on a field.</em></li>
<li>Value is the applicability of the suggestion.</li>
<li>String which must be one of:
<ul>
<li><code>machine-applicable</code></li>
<li><code>maybe-incorrect</code></li>
<li><code>has-placeholders</code></li>
<li><code>unspecified</code></li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
<li><code>#[multipart_suggestion{,_hidden,_short,_verbose}(slug, applicability = "...")]</code>
<ul>
<li><em>Applied to struct or enum variant. Mutually exclusive with struct/enum variant attributes.</em></li>
<li><em>Mandatory</em></li>
<li>Defines the type to be representing a multipart suggestion.</li>
<li>Slug (<em>Mandatory</em>): see <code>#[suggestion]</code></li>
<li><code>applicability = "..."</code> (<em>Optional</em>): see <code>#[suggestion]</code></li>
</ul>
</li>
<li><code>#[primary_span]</code> (<em>Mandatory</em> for labels and suggestions; <em>optional</em> otherwise; not applicable
to multipart suggestions)
<ul>
<li><em>Applied to <code>Span</code> fields.</em></li>
<li>Indicates the primary span of the subdiagnostic.</li>
</ul>
</li>
<li><code>#[suggestion_part(code = "...")]</code> (<em>Mandatory</em>; only applicable to multipart suggestions)
<ul>
<li><em>Applied to <code>Span</code> fields.</em></li>
<li>Indicates the span to be one part of the multipart suggestion.</li>
<li><code>code = "..."</code> (<em>Mandatory</em>)
<ul>
<li>Value is a format string indicating the code to be suggested as a
replacement.</li>
</ul>
</li>
</ul>
</li>
<li><code>#[applicability]</code> (<em>Optional</em>; only applicable to (simple and multipart) suggestions)
<ul>
<li><em>Applied to <code>Applicability</code> fields.</em></li>
<li>Indicates the applicability of the suggestion.</li>
</ul>
</li>
<li><code>#[skip_arg]</code> (<em>Optional</em>)
<ul>
<li><em>Applied to any field.</em></li>
<li>Prevents the field from being provided as a diagnostic argument.</li>
</ul>
</li>
</ul>
</main>
<nav class="nav-wrapper" aria-label="Page navigation">
<!-- Mobile navigation buttons -->
<a rel="prev" href="../diagnostics.html" class="mobile-nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
<span class=fa-svg><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512"><!--! Font Awesome Free 6.2.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2022 Fonticons, Inc. --><path d="M41.4 233.4c-12.5 12.5-12.5 32.8 0 45.3l160 160c12.5 12.5 32.8 12.5 45.3 0s12.5-32.8 0-45.3L109.3 256 246.6 118.6c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0l-160 160z"/></svg></span>
</a>
<a rel="next prefetch" href="../diagnostics/translation.html" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
<span class=fa-svg><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512"><!--! Font Awesome Free 6.2.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2022 Fonticons, Inc. --><path d="M278.6 233.4c12.5 12.5 12.5 32.8 0 45.3l-160 160c-12.5 12.5-32.8 12.5-45.3 0s-12.5-32.8 0-45.3L210.7 256 73.4 118.6c-12.5-12.5-12.5-32.8 0-45.3s32.8-12.5 45.3 0l160 160z"/></svg></span>
</a>
<div style="clear: both"></div>
</nav>
</div>
</div>
<nav class="nav-wide-wrapper" aria-label="Page navigation">
<a rel="prev" href="../diagnostics.html" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
<span class=fa-svg><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512"><!--! Font Awesome Free 6.2.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2022 Fonticons, Inc. --><path d="M41.4 233.4c-12.5 12.5-12.5 32.8 0 45.3l160 160c12.5 12.5 32.8 12.5 45.3 0s12.5-32.8 0-45.3L109.3 256 246.6 118.6c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0l-160 160z"/></svg></span>
</a>
<a rel="next prefetch" href="../diagnostics/translation.html" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
<span class=fa-svg><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512"><!--! Font Awesome Free 6.2.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2022 Fonticons, Inc. --><path d="M278.6 233.4c12.5 12.5 12.5 32.8 0 45.3l-160 160c-12.5 12.5-32.8 12.5-45.3 0s-12.5-32.8 0-45.3L210.7 256 73.4 118.6c-12.5-12.5-12.5-32.8 0-45.3s32.8-12.5 45.3 0l160 160z"/></svg></span>
</a>
</nav>
</div>
<template id=fa-eye><span class=fa-svg><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512"><!--! Font Awesome Free 6.2.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2022 Fonticons, Inc. --><path d="M288 32c-80.8 0-145.5 36.8-192.6 80.6C48.6 156 17.3 208 2.5 243.7c-3.3 7.9-3.3 16.7 0 24.6C17.3 304 48.6 356 95.4 399.4C142.5 443.2 207.2 480 288 480s145.5-36.8 192.6-80.6c46.8-43.5 78.1-95.4 93-131.1c3.3-7.9 3.3-16.7 0-24.6c-14.9-35.7-46.2-87.7-93-131.1C433.5 68.8 368.8 32 288 32zM432 256c0 79.5-64.5 144-144 144s-144-64.5-144-144s64.5-144 144-144s144 64.5 144 144zM288 192c0 35.3-28.7 64-64 64c-11.5 0-22.3-3-31.6-8.4c-.2 2.8-.4 5.5-.4 8.4c0 53 43 96 96 96s96-43 96-96s-43-96-96-96c-2.8 0-5.6 .1-8.4 .4c5.3 9.3 8.4 20.1 8.4 31.6z"/></svg></span></template>
<template id=fa-eye-slash><span class=fa-svg><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 512"><!--! Font Awesome Free 6.2.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2022 Fonticons, Inc. --><path d="M38.8 5.1C28.4-3.1 13.3-1.2 5.1 9.2S-1.2 34.7 9.2 42.9l592 464c10.4 8.2 25.5 6.3 33.7-4.1s6.3-25.5-4.1-33.7L525.6 386.7c39.6-40.6 66.4-86.1 79.9-118.4c3.3-7.9 3.3-16.7 0-24.6c-14.9-35.7-46.2-87.7-93-131.1C465.5 68.8 400.8 32 320 32c-68.2 0-125 26.3-169.3 60.8L38.8 5.1zM223.1 149.5C248.6 126.2 282.7 112 320 112c79.5 0 144 64.5 144 144c0 24.9-6.3 48.3-17.4 68.7L408 294.5c5.2-11.8 8-24.8 8-38.5c0-53-43-96-96-96c-2.8 0-5.6 .1-8.4 .4c5.3 9.3 8.4 20.1 8.4 31.6c0 10.2-2.4 19.8-6.6 28.3l-90.3-70.8zm223.1 298L373 389.9c-16.4 6.5-34.3 10.1-53 10.1c-79.5 0-144-64.5-144-144c0-6.9 .5-13.6 1.4-20.2L83.1 161.5C60.3 191.2 44 220.8 34.5 243.7c-3.3 7.9-3.3 16.7 0 24.6c14.9 35.7 46.2 87.7 93 131.1C174.5 443.2 239.2 480 320 480c47.8 0 89.9-12.9 126.2-32.5z"/></svg></span></template>
<template id=fa-copy><span class=fa-svg><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Free 6.2.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2022 Fonticons, Inc. --><path d="M502.6 70.63l-61.25-61.25C435.4 3.371 427.2 0 418.7 0H255.1c-35.35 0-64 28.66-64 64l.0195 256C192 355.4 220.7 384 256 384h192c35.2 0 64-28.8 64-64V93.25C512 84.77 508.6 76.63 502.6 70.63zM464 320c0 8.836-7.164 16-16 16H255.1c-8.838 0-16-7.164-16-16L239.1 64.13c0-8.836 7.164-16 16-16h128L384 96c0 17.67 14.33 32 32 32h47.1V320zM272 448c0 8.836-7.164 16-16 16H63.1c-8.838 0-16-7.164-16-16L47.98 192.1c0-8.836 7.164-16 16-16H160V128H63.99c-35.35 0-64 28.65-64 64l.0098 256C.002 483.3 28.66 512 64 512h192c35.2 0 64-28.8 64-64v-32h-47.1L272 448z"/></svg></span></template>
<template id=fa-play><span class=fa-svg><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 384 512"><!--! Font Awesome Free 6.2.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2022 Fonticons, Inc. --><path d="M73 39c-14.8-9.1-33.4-9.4-48.5-.9S0 62.6 0 80V432c0 17.4 9.4 33.4 24.5 41.9s33.7 8.1 48.5-.9L361 297c14.3-8.7 23-24.2 23-41s-8.7-32.2-23-41L73 39z"/></svg></span></template>
<template id=fa-clock-rotate-left><span class=fa-svg><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Free 6.2.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2022 Fonticons, Inc. --><path d="M75 75L41 41C25.9 25.9 0 36.6 0 57.9V168c0 13.3 10.7 24 24 24H134.1c21.4 0 32.1-25.9 17-41l-30.8-30.8C155 85.5 203 64 256 64c106 0 192 86 192 192s-86 192-192 192c-40.8 0-78.6-12.7-109.7-34.4c-14.5-10.1-34.4-6.6-44.6 7.9s-6.6 34.4 7.9 44.6C151.2 495 201.7 512 256 512c141.4 0 256-114.6 256-256S397.4 0 256 0C185.3 0 121.3 28.7 75 75zm181 53c-13.3 0-24 10.7-24 24V256c0 6.4 2.5 12.5 7 17l72 72c9.4 9.4 24.6 9.4 33.9 0s9.4-24.6 0-33.9l-65-65V152c0-13.3-10.7-24-24-24z"/></svg></span></template>
<script>
window.playground_copyable = true;
</script>
<script src="../elasticlunr-ef4e11c1.min.js"></script>
<script src="../mark-09e88c2c.min.js"></script>
<script src="../searcher-c2a407aa.js"></script>
<script src="../clipboard-1626706a.min.js"></script>
<script src="../highlight-abc7f01d.js"></script>
<script src="../book-a0b12cfe.js"></script>
<!-- Custom JS scripts -->
<script src="../mermaid-cc85ecea.min.js"></script>
<script src="../mermaid-init-4533fb11.js"></script>
</div>
</body>
</html>