Command-line Arguments Command-line flags are documented in the rustc book. All stable flags should be documented there. Unstable flags should be documented in the unstable book. See the forge guide for new options for details on the proced...
rustc_driver and rustc_interface rustc_driver The rustc_driver is essentially rustc's main function. It acts as the glue for running the various phases of the compiler in the correct order, using the interface defined in the rustc_interface...
External rustc_drivers rustc_private Overview The rustc_private feature allows external crates to use compiler internals. Using rustc_private with official toolchains When using the rustc_private feature with official Rust toolchains distri...
Example: Type checking through rustc_driver rustc_driver allows you to interact with Rust code at various stages of compilation. Getting the type of an expression To get the type of an expression, use the after_analysis callback to get a Ty...
Example: Getting diagnostic through rustc_interface The rustc_interface allows you to intercept diagnostics that would otherwise be printed to stderr. Getting diagnostics To get diagnostics from the compiler, configure rustc_interface::Conf...
Errors and lints 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. Diagnostic structure The main parts of a diagnostic error are the follo...
Diagnostic and subdiagnostic structs rustc has two diagnostic traits that can be used to create diagnostics: Diagnostic and Subdiagnostic. For simple diagnostics, derived impls can be used, e.g. #[derive(Diagnostic)]. They are only suitable...
Translation Please see the tracking issue https://github.com/rust-lang/rust/issues/132181 for status updates. The translation infra is waiting for a yet-to-be-proposed redesign and thus rework, we are not mandating usage of current translat...
Lints This page documents some of the machinery around lint registration and how we run lints in the compiler. The LintStore is the central piece of infrastructure, around which everything rotates. The LintStore is held as part of the Sessi...
Error codes We generally try to assign each error message a unique code like E0123. These codes are defined in the compiler in the diagnostics.rs files found in each crate, which basically consist of macros. All error codes have an associat...
Diagnostic Items While writing lints it's common to check for specific types, traits and functions. This raises the question on how to check for these. Types can be checked by their complete type path. However, this requires hard coding pat...
ErrorGuaranteed The previous sections have been about the error message that a user of the compiler sees. But emitting an error can also have a second important side effect within the compiler source code: it generates an ErrorGuaranteed. E...
Analysis This part discusses the many analyses that the compiler uses to check various properties of the code and to inform later stages. Typically, this is what people mean when they talk about "Rust's type system". This includes the repre...
Generic parameter definitions This chapter will discuss how rustc tracks what generic parameters are introduced. For example given some struct Foo<T> how does rustc track that Foo defines some type parameter T (and no other generic paramete...
EarlyBinder and instantiating parameters Given an item that introduces a generic parameter T, whenever we refer to types inside of foo (i.e. the return type or argument types) from outside of foo we must take care to handle the generic para...
Binder and Higher ranked regions Sometimes, we define generic parameters not on an item but as part of a type or a where clause. As an example, the type for<'a> fn(&'a u32) or the where clause for<'a> T: Trait<'a> both introduce a generic l...
Instantiating Binders Much like EarlyBinder, when accessing the inside of a Binder, we must first discharge it by replacing the bound vars with some other value. This is for much the same reason as with EarlyBinder, types referencing parame...
Early vs Late bound parameters 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 sho...
The ty module: representing types 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. ty::Ty When we talk about ho...
ADTs and Generic Arguments The term ADT stands for "Algebraic data type", in rust this refers to a struct, enum, or union. ADTs Representation Let's consider the example of a type like MyStruct<u32>, where MyStruct is defined like so: struc...