Merge pull request #2509 from rust-lang/tshepang-auto-toc

make toc generation fully automatic
This commit is contained in:
Tshepang Mbambo 2025-08-03 06:55:44 +02:00 committed by GitHub
commit 3bba46bb52
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
73 changed files with 198 additions and 147 deletions

View file

@ -17,7 +17,6 @@ jobs:
MDBOOK_VERSION: 0.4.48
MDBOOK_LINKCHECK2_VERSION: 0.9.1
MDBOOK_MERMAID_VERSION: 0.12.6
MDBOOK_TOC_VERSION: 0.11.2
MDBOOK_OUTPUT__LINKCHECK__FOLLOW_WEB_LINKS: ${{ github.event_name != 'pull_request' }}
DEPLOY_DIR: book/html
BASE_SHA: ${{ github.event.pull_request.base.sha }}
@ -34,7 +33,7 @@ jobs:
with:
path: |
~/.cargo/bin
key: ${{ runner.os }}-${{ env.MDBOOK_VERSION }}--${{ env.MDBOOK_LINKCHECK2_VERSION }}--${{ env.MDBOOK_TOC_VERSION }}--${{ env.MDBOOK_MERMAID_VERSION }}
key: ${{ runner.os }}-${{ env.MDBOOK_VERSION }}--${{ env.MDBOOK_LINKCHECK2_VERSION }}--${{ env.MDBOOK_MERMAID_VERSION }}
- name: Restore cached Linkcheck
if: github.event_name == 'schedule'
@ -57,7 +56,6 @@ jobs:
run: |
cargo install mdbook --version ${{ env.MDBOOK_VERSION }}
cargo install mdbook-linkcheck2 --version ${{ env.MDBOOK_LINKCHECK2_VERSION }}
cargo install mdbook-toc --version ${{ env.MDBOOK_TOC_VERSION }}
cargo install mdbook-mermaid --version ${{ env.MDBOOK_MERMAID_VERSION }}
- name: Check build

View file

@ -43,7 +43,7 @@ rustdocs][rustdocs].
To build a local static HTML site, install [`mdbook`](https://github.com/rust-lang/mdBook) with:
```
cargo install mdbook mdbook-linkcheck2 mdbook-toc mdbook-mermaid
cargo install mdbook mdbook-linkcheck2 mdbook-mermaid
```
and execute the following command in the root of the repository:
@ -67,8 +67,8 @@ ENABLE_LINKCHECK=1 mdbook serve
### Table of Contents
We use `mdbook-toc` to auto-generate TOCs for long sections. You can invoke the preprocessor by
including the `<!-- toc -->` marker at the place where you want the TOC.
Each page has a TOC that is automatically generated by `pagetoc.js`.
There is an associated `pagetoc.css`, for styling.
## Synchronizing josh subtree with rustc

View file

@ -6,17 +6,18 @@ description = "A guide to developing the Rust compiler (rustc)"
[build]
create-missing = false
[preprocessor.toc]
command = "mdbook-toc"
renderer = ["html"]
[preprocessor.mermaid]
command = "mdbook-mermaid"
[output.html]
git-repository-url = "https://github.com/rust-lang/rustc-dev-guide"
edit-url-template = "https://github.com/rust-lang/rustc-dev-guide/edit/master/{path}"
additional-js = ["mermaid.min.js", "mermaid-init.js"]
additional-js = [
"mermaid.min.js",
"mermaid-init.js",
"pagetoc.js",
]
additional-css = ["pagetoc.css"]
[output.html.search]
use-boolean-and = true

View file

@ -0,0 +1,84 @@
/* Inspired by https://github.com/JorelAli/mdBook-pagetoc/tree/98ee241 (under WTFPL) */
:root {
--toc-width: 270px;
--center-content-toc-shift: calc(-1 * var(--toc-width) / 2);
}
.nav-chapters {
/* adjust width of buttons that bring to the previous or the next page */
min-width: 50px;
}
@media only screen {
@media (max-width: 1179px) {
.sidebar-hidden #sidetoc {
display: none;
}
}
@media (max-width: 1439px) {
.sidebar-visible #sidetoc {
display: none;
}
}
@media (1180px <= width <= 1439px) {
.sidebar-hidden main {
position: relative;
left: var(--center-content-toc-shift);
}
}
@media (1440px <= width <= 1700px) {
.sidebar-visible main {
position: relative;
left: var(--center-content-toc-shift);
}
}
#sidetoc {
margin-left: calc(100% + 20px);
}
#pagetoc {
position: fixed;
/* adjust TOC width */
width: var(--toc-width);
height: calc(100vh - var(--menu-bar-height) - 0.67em * 4);
overflow: auto;
}
#pagetoc a {
border-left: 1px solid var(--sidebar-bg);
color: var(--fg);
display: block;
padding-bottom: 5px;
padding-top: 5px;
padding-left: 10px;
text-align: left;
text-decoration: none;
}
#pagetoc a:hover,
#pagetoc a.active {
background: var(--sidebar-bg);
color: var(--sidebar-active) !important;
}
#pagetoc .active {
background: var(--sidebar-bg);
color: var(--sidebar-active);
}
#pagetoc .pagetoc-H2 {
padding-left: 20px;
}
#pagetoc .pagetoc-H3 {
padding-left: 40px;
}
#pagetoc .pagetoc-H4 {
padding-left: 60px;
}
}
@media print {
#sidetoc {
display: none;
}
}

View file

@ -0,0 +1,104 @@
// Inspired by https://github.com/JorelAli/mdBook-pagetoc/tree/98ee241 (under WTFPL)
let activeHref = location.href;
function updatePageToc(elem = undefined) {
let selectedPageTocElem = elem;
const pagetoc = document.getElementById("pagetoc");
function getRect(element) {
return element.getBoundingClientRect();
}
function overflowTop(container, element) {
return getRect(container).top - getRect(element).top;
}
function overflowBottom(container, element) {
return getRect(container).bottom - getRect(element).bottom;
}
// We've not selected a heading to highlight, and the URL needs updating
// so we need to find a heading based on the URL
if (selectedPageTocElem === undefined && location.href !== activeHref) {
activeHref = location.href;
for (const pageTocElement of pagetoc.children) {
if (pageTocElement.href === activeHref) {
selectedPageTocElem = pageTocElement;
}
}
}
// We still don't have a selected heading, let's try and find the most
// suitable heading based on the scroll position
if (selectedPageTocElem === undefined) {
const margin = window.innerHeight / 3;
const headers = document.getElementsByClassName("header");
for (let i = 0; i < headers.length; i++) {
const header = headers[i];
if (selectedPageTocElem === undefined && getRect(header).top >= 0) {
if (getRect(header).top < margin) {
selectedPageTocElem = header;
} else {
selectedPageTocElem = headers[Math.max(0, i - 1)];
}
}
// a very long last section's heading is over the screen
if (selectedPageTocElem === undefined && i === headers.length - 1) {
selectedPageTocElem = header;
}
}
}
// Remove the active flag from all pagetoc elements
for (const pageTocElement of pagetoc.children) {
pageTocElement.classList.remove("active");
}
// If we have a selected heading, set it to active and scroll to it
if (selectedPageTocElem !== undefined) {
for (const pageTocElement of pagetoc.children) {
if (selectedPageTocElem.href.localeCompare(pageTocElement.href) === 0) {
pageTocElement.classList.add("active");
if (overflowTop(pagetoc, pageTocElement) > 0) {
pagetoc.scrollTop = pageTocElement.offsetTop;
}
if (overflowBottom(pagetoc, pageTocElement) < 0) {
pagetoc.scrollTop -= overflowBottom(pagetoc, pageTocElement);
}
}
}
}
}
if (document.getElementById("sidetoc") === null &&
document.getElementsByClassName("header").length > 0) {
// The sidetoc element doesn't exist yet, let's create it
// Create the empty sidetoc and pagetoc elements
const sidetoc = document.createElement("div");
const pagetoc = document.createElement("div");
sidetoc.id = "sidetoc";
pagetoc.id = "pagetoc";
sidetoc.appendChild(pagetoc);
// And append them to the current DOM
const main = document.querySelector('main');
main.insertBefore(sidetoc, main.firstChild);
// Populate sidebar on load
window.addEventListener("load", () => {
for (const header of document.getElementsByClassName("header")) {
const link = document.createElement("a");
link.innerHTML = header.innerHTML;
link.href = header.hash;
link.classList.add("pagetoc-" + header.parentElement.tagName);
document.getElementById("pagetoc").appendChild(link);
link.onclick = () => updatePageToc(link);
}
updatePageToc();
});
// Update page table of contents selected heading on scroll
window.addEventListener("scroll", () => updatePageToc());
}

View file

@ -1,7 +1,5 @@
# Inline assembly
<!-- toc -->
## Overview
Inline assembly in rustc mostly revolves around taking an `asm!` macro invocation and plumbing it

View file

@ -1,7 +1,5 @@
# Backend Agnostic Codegen
<!-- toc -->
[`rustc_codegen_ssa`]
provides an abstract interface for all backends to implement,
namely LLVM, [Cranelift], and [GCC].

View file

@ -1,7 +1,5 @@
# Implicit caller location
<!-- toc -->
Approved in [RFC 2091], this feature enables the accurate reporting of caller location during panics
initiated from functions like `Option::unwrap`, `Result::expect`, and `Index::index`. This feature
adds the [`#[track_caller]`][attr-reference] attribute for functions, the

View file

@ -1,7 +1,5 @@
# Monomorphization
<!-- toc -->
As you probably know, Rust has a very expressive type system that has extensive
support for generic types. But of course, assembly is not generic, so we need
to figure out the concrete types of all the generics before the code can

View file

@ -1,7 +1,5 @@
# Updating LLVM
<!-- toc -->
<!-- date-check: Aug 2024 -->
Rust supports building against multiple LLVM versions:

View file

@ -1,7 +1,5 @@
# Move paths
<!-- toc -->
In reality, it's not enough to track initialization at the granularity
of local variables. Rust also allows us to do moves and initialization
at the field granularity:

View file

@ -1,7 +1,5 @@
# Region inference (NLL)
<!-- toc -->
The MIR-based region checking code is located in [the `rustc_mir::borrow_check`
module][nll].

View file

@ -1,7 +1,5 @@
# Constraint propagation
<!-- toc -->
The main work of the region inference is **constraint propagation**,
which is done in the [`propagate_constraints`] function. There are
three sorts of constraints that are used in NLL, and we'll explain how

View file

@ -1,7 +1,5 @@
# Universal regions
<!-- toc -->
"Universal regions" is the name that the code uses to refer to "named
lifetimes" -- e.g., lifetime parameters and `'static`. The name
derives from the fact that such lifetimes are "universally quantified"

View file

@ -1,7 +1,5 @@
# Member constraints
<!-- toc -->
A member constraint `'m member of ['c_1..'c_N]` expresses that the
region `'m` must be *equal* to some **choice regions** `'c_i` (for
some `i`). These constraints cannot be expressed by users, but they

View file

@ -1,7 +1,5 @@
# Placeholders and universes
<!-- toc -->
From time to time we have to reason about regions that we can't
concretely know. For example, consider this program:

View file

@ -1,7 +1,5 @@
# Procedures for breaking changes
<!-- toc -->
This page defines the best practices procedure for making bug fixes or soundness
corrections in the compiler that can cause existing code to stop compiling. This
text is based on

View file

@ -1,7 +1,5 @@
# What Bootstrapping does
<!-- toc -->
[*Bootstrapping*][boot] is the process of using a compiler to compile itself.
More accurately, it means using an older compiler to compile a newer version of
the same compiler.

View file

@ -1,7 +1,5 @@
# How to build and run the compiler
<!-- toc -->
<div class="warning">
For `profile = "library"` users, or users who use `download-rustc = true | "if-unchanged"`, please be advised that

View file

@ -6,8 +6,6 @@ relevant to your desired goal.
See also the associated documentation in the [target tier policy].
<!-- toc -->
[target tier policy]: https://doc.rust-lang.org/rustc/target-tier-policy.html#adding-a-new-target
## Specifying a new LLVM

View file

@ -1,7 +1,5 @@
# Optimized build of the compiler
<!-- toc -->
There are multiple additional build configuration options and techniques that can be used to compile a
build of `rustc` that is as optimized as possible (for example when building `rustc` for a Linux
distribution). The status of these configuration options for various Rust targets is tracked [here].

View file

@ -3,8 +3,6 @@
The full bootstrapping process takes quite a while. Here are some suggestions to
make your life easier.
<!-- toc -->
## Installing a pre-push hook
CI will automatically fail your build if it doesn't pass `tidy`, our internal

View file

@ -1,7 +1,5 @@
# Debugging the compiler
<!-- toc -->
This chapter contains a few tips to debug the compiler. These tips aim to be
useful no matter what you are working on. Some of the other chapters have
advice about specific parts of the compiler (e.g. the [Queries Debugging and

View file

@ -1,7 +1,5 @@
# High-level overview of the compiler source
<!-- toc -->
Now that we have [seen what the compiler does][orgch],
let's take a look at the structure of the [`rust-lang/rust`] repository,
where the rustc source code lives.

View file

@ -1,7 +1,5 @@
# Interpreter
<!-- toc -->
The interpreter is a virtual machine for executing MIR without compiling to
machine code. It is usually invoked via `tcx.const_eval_*` functions. The
interpreter is shared between the compiler (for compile-time function

View file

@ -1,7 +1,5 @@
# Contribution procedures
<!-- toc -->
## Bug reports
While bugs are unfortunate, they're a reality in software. We can't fix what we

View file

@ -1,7 +1,5 @@
# Async closures/"coroutine-closures"
<!-- toc -->
Please read [RFC 3668](https://rust-lang.github.io/rfcs/3668-async-closures.html) to understand the general motivation of the feature. This is a very technical and somewhat "vertical" chapter; ideally we'd split this and sprinkle it across all the relevant chapters, but for the purposes of understanding async closures *holistically*, I've put this together all here in one chapter.
## Coroutine-closures -- a technical deep dive

View file

@ -1,7 +1,5 @@
# Debugging support in the Rust compiler
<!-- toc -->
This document explains the state of debugging tools support in the Rust compiler (rustc).
It gives an overview of GDB, LLDB, WinDbg/CDB,
as well as infrastructure around Rust compiler to debug Rust code.

View file

@ -1,7 +1,5 @@
# Errors and lints
<!-- toc -->
A lot of effort has been put into making `rustc` have great error messages.
This chapter is about how to emit compile errors and lints from the compiler.

View file

@ -1,8 +1,6 @@
# Early vs Late bound parameters
<!-- toc -->
> **NOTE**: This chapter largely talks about early/late bound as being solely relevant when discussing function item types/function definitions. This is potentially not completely true, async blocks and closures should likely be discussed somewhat in this chapter.
## What does it mean to be "early" bound or "late" bound

View file

@ -3,8 +3,6 @@
Thank you for your interest in contributing to Rust! There are many ways to
contribute, and we appreciate all of them.
<!-- toc -->
If this is your first time contributing, the [walkthrough] chapter can give you a good example of
how a typical contribution would go.

View file

@ -1,7 +1,5 @@
# Using Git
<!-- toc -->
The Rust project uses [Git] to manage its source code. In order to
contribute, you'll need some familiarity with its features so that your changes
can be incorporated into the compiler.

View file

@ -1,7 +1,5 @@
# Editions
<!-- toc -->
This chapter gives an overview of how Edition support works in rustc.
This assumes that you are familiar with what Editions are (see the [Edition Guide]).

View file

@ -1,7 +1,5 @@
# The HIR
<!-- toc -->
The HIR "High-Level Intermediate Representation" is the primary IR used
in most of rustc. It is a compiler-friendly representation of the abstract
syntax tree (AST) that is generated after parsing, macro expansion, and name

View file

@ -1,7 +1,5 @@
# Implementing new language features
<!-- toc -->
When you want to implement a new significant feature in the compiler, you need to go through this process to make sure everything goes smoothly.
**NOTE: This section is for *language* features, not *library* features, which use [a different process].**

View file

@ -1,7 +1,5 @@
# LLVM source-based code coverage
<!-- toc -->
`rustc` supports detailed source-based code and test coverage analysis
with a command line option (`-C instrument-coverage`) that instruments Rust
libraries and binaries with additional instructions and data, at compile time.

View file

@ -1,7 +1,5 @@
# Macro expansion
<!-- toc -->
Rust has a very powerful macro system. In the previous chapter, we saw how
the parser sets aside macros to be expanded (using temporary [placeholders]).
This chapter is about the process of expanding those macros iteratively until

View file

@ -1,7 +1,5 @@
# MIR construction
<!-- toc -->
The lowering of [HIR] to [MIR] occurs for the following (probably incomplete)
list of items:

View file

@ -1,7 +1,5 @@
# Dataflow Analysis
<!-- toc -->
If you work on the MIR, you will frequently come across various flavors of
[dataflow analysis][wiki]. `rustc` uses dataflow to find uninitialized
variables, determine what variables are live across a generator `yield`

View file

@ -1,7 +1,5 @@
# Drop elaboration
<!-- toc -->
## Dynamic drops
According to the [reference][reference-drop]:

View file

@ -1,7 +1,5 @@
# The MIR (Mid-level IR)
<!-- toc -->
MIR is Rust's _Mid-level Intermediate Representation_. It is
constructed from [HIR](../hir.html). MIR was introduced in
[RFC 1211]. It is a radically simplified form of Rust that is used for

View file

@ -1,7 +1,5 @@
# Name resolution
<!-- toc -->
In the previous chapters, we saw how the [*Abstract Syntax Tree* (`AST`)][ast]
is built with all macros expanded. We saw how doing that requires doing some
name resolution to resolve imports and macro names. In this chapter, we show

View file

@ -1,7 +1,5 @@
# Aliases and Normalization
<!-- toc -->
## Aliases
In Rust there are a number of types that are considered equal to some "underlying" type, for example inherent associated types, trait associated types, free type aliases (`type Foo = u32`), and opaque types (`-> impl RPIT`). We consider such types to be "aliases", alias types are represented by the [`TyKind::Alias`][tykind_alias] variant, with the kind of alias tracked by the [`AliasTyKind`][aliaskind] enum.

View file

@ -1,7 +1,5 @@
# Overview of the compiler
<!-- toc -->
This chapter is about the overall process of compiling a program -- how
everything fits together.

View file

@ -1,7 +1,5 @@
# Panicking in Rust
<!-- toc -->
## Step 1: Invocation of the `panic!` macro.
There are actually two panic macros - one defined in `core`, and one defined in `std`.

View file

@ -1,7 +1,5 @@
# Profile-guided optimization
<!-- toc -->
`rustc` supports doing profile-guided optimization (PGO).
This chapter describes what PGO is and how the support for it is
implemented in `rustc`.

View file

@ -1,7 +1,5 @@
# Incremental compilation in detail
<!-- toc -->
The incremental compilation scheme is, in essence, a surprisingly
simple extension to the overall query system. It relies on the fact that:

View file

@ -1,7 +1,5 @@
# Incremental compilation
<!-- toc -->
The incremental compilation scheme is, in essence, a surprisingly
simple extension to the overall query system. We'll start by describing
a slightly simplified variant of the real thing the "basic algorithm"

View file

@ -1,7 +1,5 @@
# The Query Evaluation Model in detail
<!-- toc -->
This chapter provides a deeper dive into the abstract model queries are built on.
It does not go into implementation details but tries to explain
the underlying logic. The examples here, therefore, have been stripped down and

View file

@ -1,7 +1,5 @@
# How Salsa works
<!-- toc -->
This chapter is based on the explanation given by Niko Matsakis in this
[video](https://www.youtube.com/watch?v=_muY4HjSqVw) about
[Salsa](https://github.com/salsa-rs/salsa). To find out more you may

View file

@ -1,7 +1,5 @@
# Queries: demand-driven compilation
<!-- toc -->
As described in [Overview of the compiler], the Rust compiler
is still (as of <!-- date-check --> July 2021) transitioning from a
traditional "pass-based" setup to a "demand-driven" system. The compiler query

View file

@ -1,7 +1,5 @@
# Rustdoc Internals
<!-- toc -->
This page describes [`rustdoc`]'s passes and modes. For an overview of `rustdoc`,
see the ["Rustdoc overview" chapter](./rustdoc.md).

View file

@ -7,8 +7,6 @@ in the crates in the doc bundle, and the second reads
it, turns it into some in-memory structures, and
scans them linearly to search.
<!-- toc -->
## Search index format
`search.js` calls this Raw, because it turns it into

View file

@ -9,8 +9,6 @@ For more details about how rustdoc works, see the
[Rustdoc internals]: ./rustdoc-internals.md
<!-- toc -->
`rustdoc` uses `rustc` internals (and, of course, the standard library), so you
will have to build the compiler and `std` once before you can build `rustdoc`.

View file

@ -6,8 +6,6 @@ APIs to use unstable APIs internally in the rustc standard library.
**NOTE**: this section is for *library* features, not *language* features. For instructions on
stabilizing a language feature see [Stabilizing Features](./stabilization_guide.md).
<!-- toc -->
## unstable
The `#[unstable(feature = "foo", issue = "1234", reason = "lorem ipsum")]`

View file

@ -6,8 +6,6 @@
Once an unstable feature has been well-tested with no outstanding concerns, anyone may push for its stabilization, though involving the people who have worked on it is prudent. Follow these steps:
<!-- toc -->
## Write an RFC, if needed
If the feature was part of a [lang experiment], the lang team generally will want to first accept an RFC before stabilization.

View file

@ -1,7 +1,5 @@
# The `#[test]` attribute
<!-- toc -->
Many Rust programmers rely on a built-in attribute called `#[test]`. All

View file

@ -1,7 +1,5 @@
# Adding new tests
<!-- toc -->
**In general, we expect every PR that fixes a bug in rustc to come accompanied
by a regression test of some kind.** This test should fail in master but pass
after the PR. These tests are really useful for preventing us from repeating the

View file

@ -1,7 +1,5 @@
# Compiletest
<!-- toc -->
## Introduction
`compiletest` is the main test harness of the Rust test suite. It allows test

View file

@ -1,7 +1,5 @@
# Compiletest directives
<!-- toc -->
<!--
FIXME(jieyouxu) completely revise this chapter.
-->

View file

@ -1,7 +1,5 @@
# Testing the compiler
<!-- toc -->
The Rust project runs a wide variety of different tests, orchestrated by the
build system (`./x test`). This section gives a brief overview of the different
testing tools. Subsequent chapters dive into [running tests](running.md) and

View file

@ -1,7 +1,5 @@
# Running tests
<!-- toc -->
You can run the entire test collection using `x`. But note that running the
*entire* test collection is almost never what you want to do during local
development because it takes a really long time. For local development, see the

View file

@ -1,7 +1,5 @@
# UI tests
<!-- toc -->
UI tests are a particular [test suite](compiletest.md#test-suites) of
compiletest.

View file

@ -1,7 +1,5 @@
# The THIR
<!-- toc -->
The THIR ("Typed High-Level Intermediate Representation"), previously called HAIR for
"High-Level Abstract IR", is another IR used by rustc that is generated after
[type checking]. It is (as of <!-- date-check --> January 2024) used for

View file

@ -1,7 +1,5 @@
# Using tracing to debug the compiler
<!-- toc -->
The compiler has a lot of [`debug!`] (or `trace!`) calls, which print out logging information
at many points. These are very useful to at least narrow down the location of
a bug if not to find it entirely, or just to orient yourself as to why the

View file

@ -1,7 +1,5 @@
# Goals and clauses
<!-- toc -->
In logic programming terms, a **goal** is something that you must
prove and a **clause** is something that you know is true. As
described in the [lowering to logic](./lowering-to-logic.html)

View file

@ -1,7 +1,5 @@
# Lowering to logic
<!-- toc -->
The key observation here is that the Rust trait system is basically a
kind of logic, and it can be mapped onto standard logical inference
rules. We can then look for solutions to those inference rules in a

View file

@ -1,7 +1,5 @@
# Trait resolution (old-style)
<!-- toc -->
This chapter describes the general process of _trait resolution_ and points out
some non-obvious things.

View file

@ -1,7 +1,5 @@
# The `ty` module: representing types
<!-- toc -->
The `ty` module defines how the Rust compiler represents types internally. It also defines the
*typing context* (`tcx` or `TyCtxt`), which is the central data structure in the compiler.

View file

@ -1,7 +1,5 @@
# Type inference
<!-- toc -->
Type inference is the process of automatic detection of the type of an
expression.

View file

@ -1,7 +1,5 @@
# Typing/Parameter Environments
<!-- toc -->
## Typing Environments
When interacting with the type system there are a few variables to consider that can affect the results of trait solving. The set of in-scope where clauses, and what phase of the compiler type system operations are being performed in (the [`ParamEnv`][penv] and [`TypingMode`][tmode] structs respectively).

View file

@ -1,7 +1,5 @@
# Variance of type and lifetime parameters
<!-- toc -->
For a more general background on variance, see the [background] appendix.
[background]: ./appendix/background.html

View file

@ -1,7 +1,5 @@
# Walkthrough: a typical contribution
<!-- toc -->
There are _a lot_ of ways to contribute to the Rust compiler, including fixing
bugs, improving performance, helping design features, providing feedback on
existing features, etc. This chapter does not claim to scratch the surface.