blob: 6478de34e97e9d6c14370a896ec63d149915bf5e [file] [log] [blame]
<!DOCTYPE HTML>
<html lang="en" class="light sidebar-visible" dir="ltr">
<head>
<!-- Book generated using mdBook -->
<meta charset="UTF-8">
<title>Coding conventions - 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 -->
<link rel="stylesheet" href="pagetoc.css">
<!-- 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.js";
</script>
<!-- Start loading toc.js asap -->
<script src="toc.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="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 = false;
}
if (sidebar === 'visible') {
sidebar_toggle.checked = true;
} else {
html.classList.remove('sidebar-visible');
}
</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 (`/`)" 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/main/src/conventions.md" title="Suggest an edit" aria-label="Suggest an edit" rel="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">
<div class="search-wrapper">
<input type="search" id="searchbar" name="searchbar" placeholder="Search this book ..." aria-controls="searchresults-outer" aria-describedby="searchresults-header">
<div class="spinner-wrapper">
<i class="fa fa-spinner fa-spin"></i>
</div>
</div>
</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="coding-conventions"><a class="header" href="#coding-conventions">Coding conventions</a></h1>
<p>This file offers some tips on the coding conventions for rustc. This
chapter covers <a href="#formatting">formatting</a>, <a href="#cc">coding for correctness</a>,
<a href="#cio">using crates from crates.io</a>, and some tips on
<a href="#er">structuring your PR for easy review</a>.</p>
<p><a id="formatting"></a></p>
<h2 id="formatting-and-the-tidy-script"><a class="header" href="#formatting-and-the-tidy-script">Formatting and the tidy script</a></h2>
<p>rustc is moving towards the <a href="https://github.com/rust-dev-tools/fmt-rfcs">Rust standard coding style</a>.</p>
<p>However, for now we don't use stable <code>rustfmt</code>; we use a pinned version with a
special config, so this may result in different style from normal <a href="https://github.com/rust-lang/rustfmt"><code>rustfmt</code></a>.
Therefore, formatting this repository using <code>cargo fmt</code> is not recommended.</p>
<p>Instead, formatting should be done using <code>./x fmt</code>. It's a good habit to run
<code>./x fmt</code> before every commit, as this reduces conflicts later.</p>
<p>Formatting is checked by the <code>tidy</code> script. It runs automatically when you do
<code>./x test</code> and can be run in isolation with <code>./x fmt --check</code>.</p>
<p>If you want to use format-on-save in your editor, the pinned version of
<code>rustfmt</code> is built under <code>build/&lt;target&gt;/stage0/bin/rustfmt</code>.</p>
<h3 id="formatting-c-code"><a class="header" href="#formatting-c-code">Formatting C++ code</a></h3>
<p>The compiler contains some C++ code for interfacing with parts of LLVM that
don't have a stable C API.
When modifying that code, use this command to format it:</p>
<pre><code class="language-console">./x test tidy --extra-checks cpp:fmt --bless
</code></pre>
<p>This uses a pinned version of <code>clang-format</code>, to avoid relying on the local
environment.</p>
<h3 id="formatting-and-linting-python-code"><a class="header" href="#formatting-and-linting-python-code">Formatting and linting Python code</a></h3>
<p>The Rust repository contains quite a lot of Python code. We try to keep
it both linted and formatted by the <a href="https://github.com/astral-sh/ruff">ruff</a> tool.</p>
<p>When modifying Python code, use this command to format it:</p>
<pre><code class="language-console">./x test tidy --extra-checks py:fmt --bless
</code></pre>
<p>And, the following command to run lints:</p>
<pre><code class="language-console">./x test tidy --extra-checks py:lint
</code></pre>
<p>These use a pinned version of <code>ruff</code>, to avoid relying on the local environment.</p>
<p><a id="copyright"></a></p>
<!-- REUSE-IgnoreStart -->
<!-- Prevent REUSE from interpreting the heading as a copyright notice -->
<h3 id="copyright-notice"><a class="header" href="#copyright-notice">Copyright notice</a></h3>
<!-- REUSE-IgnoreEnd -->
<p>In the past, files began with a copyright and license notice. Please <strong>omit</strong>
this notice for new files licensed under the standard terms (dual
MIT/Apache-2.0).</p>
<p>All of the copyright notices should be gone by now, but if you come across one
in the rust-lang/rust repo, feel free to open a PR to remove it.</p>
<h3 id="line-length"><a class="header" href="#line-length">Line length</a></h3>
<p>Lines should be at most 100 characters. It's even better if you can
keep things to 80.</p>
<p>Sometimes, and particularly for tests, it can be necessary to exempt yourself from this limit.
In that case, you can add a comment towards the top of the file like so:</p>
<pre><pre class="playground"><code class="language-rust"><span class="boring">#![allow(unused)]
</span><span class="boring">fn main() {
</span>// ignore-tidy-linelength
<span class="boring">}</span></code></pre></pre>
<h3 id="tabs-vs-spaces"><a class="header" href="#tabs-vs-spaces">Tabs vs spaces</a></h3>
<p>Prefer 4-space indents.</p>
<p><a id="cc"></a></p>
<h2 id="coding-for-correctness"><a class="header" href="#coding-for-correctness">Coding for correctness</a></h2>
<p>Beyond formatting, there are a few other tips that are worth
following.</p>
<h3 id="prefer-exhaustive-matches"><a class="header" href="#prefer-exhaustive-matches">Prefer exhaustive matches</a></h3>
<p>Using <code>_</code> in a match is convenient, but it means that when new
variants are added to the enum, they may not get handled correctly.
Ask yourself: if a new variant were added to this enum, what's the
chance that it would want to use the <code>_</code> code, versus having some
other treatment? Unless the answer is "low", then prefer an
exhaustive match.</p>
<p>The same advice applies to <code>if let</code> and <code>while let</code>,
which are effectively tests for a single variant.</p>
<h3 id="use-todo-comments-for-things-you-dont-want-to-forget"><a class="header" href="#use-todo-comments-for-things-you-dont-want-to-forget">Use "TODO" comments for things you don't want to forget</a></h3>
<p>As a useful tool to yourself, you can insert a <code>// TODO</code> comment
for something that you want to get back to before you land your PR:</p>
<pre><code class="language-rust ignore">fn do_something() {
if something_else {
unimplemented!(); // TODO write this
}
}</code></pre>
<p>The tidy script will report an error for a <code>// TODO</code> comment, so this
code would not be able to land until the TODO is fixed (or removed).</p>
<p>This can also be useful in a PR as a way to signal from one commit that you are
leaving a bug that a later commit will fix:</p>
<pre><code class="language-rust ignore">if foo {
return true; // TODO wrong, but will be fixed in a later commit
}</code></pre>
<p><a id="cio"></a></p>
<h2 id="using-crates-from-cratesio"><a class="header" href="#using-crates-from-cratesio">Using crates from crates.io</a></h2>
<p>See the <a href="./crates-io.html">crates.io dependencies</a> section.</p>
<p><a id="er"></a></p>
<h2 id="how-to-structure-your-pr"><a class="header" href="#how-to-structure-your-pr">How to structure your PR</a></h2>
<p>How you prepare the commits in your PR can make a big difference for the
reviewer. Here are some tips.</p>
<p><strong>Isolate "pure refactorings" into their own commit.</strong> For example, if
you rename a method, then put that rename into its own commit, along
with the renames of all the uses.</p>
<p><strong>More commits is usually better.</strong> If you are doing a large change,
it's almost always better to break it up into smaller steps that can
be independently understood. The one thing to be aware of is that if
you introduce some code following one strategy, then change it
dramatically (versus adding to it) in a later commit, that
'back-and-forth' can be confusing.</p>
<p><strong>Format liberally.</strong> While only the final commit of a PR must be correctly
formatted, it is both easier to review and less noisy to format each commit
individually using <code>./x fmt</code>.</p>
<p><strong>No merges.</strong> We do not allow merge commits into our history, other
than those by bors. If you get a merge conflict, rebase instead via a
command like <code>git rebase --interactive rust-lang/main</code> (presuming you use the
name <code>rust-lang</code> for your remote).</p>
<p><strong>Individual commits do not have to build (but it's nice).</strong> We do not
require that every intermediate commit successfully builds – we only
expect to be able to bisect at a PR level. However, if you <em>can</em> make
individual commits build, that is always helpful.</p>
<h2 id="naming-conventions"><a class="header" href="#naming-conventions">Naming conventions</a></h2>
<p>Apart from normal Rust style/naming conventions, there are also some specific
to the compiler.</p>
<ul>
<li>
<p><code>cx</code> tends to be short for "context" and is often used as a suffix. For
example, <code>tcx</code> is a common name for the <a href="./ty.html">Typing Context</a>.</p>
</li>
<li>
<p><a href="./ty.html"><code>'tcx</code></a> is used as the lifetime name for the Typing Context.</p>
</li>
<li>
<p>Because <code>crate</code> is a keyword, if you need a variable to represent something
crate-related, often the spelling is changed to <code>krate</code>.</p>
</li>
</ul>
</main>
<nav class="nav-wrapper" aria-label="Page navigation">
<!-- Mobile navigation buttons -->
<a rel="prev" href="feature-gates.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="bug-fix-procedure.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="feature-gates.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="bug-fix-procedure.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>
<script src="pagetoc.js"></script>
</div>
</body>
</html>