Parameter Ty/Const/Regions When inside of generic items, types can be written that use in scope generic parameters, for example fn foo<'a, T>(_: &'a Vec<T>). In this specific case, the &'a Vec<T> type would be represented internally as: TyK...
TypeFoldable and TypeFolder In a previous chapter, we discussed instantiating binders. This involves looking at everything inside of a Early(Binder) to find any usages of the bound vars in order to replace them. Binders can wrap an arbitrar...
Aliases and Normalization 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 (...
Typing/Parameter Environments 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 ty...
Type inference Type inference is the process of automatic detection of the type of an expression. It is what allows Rust to work with fewer or no type annotations, making things easier for users: fn main() { let mut things = vec![]; things....
Trait resolution (old-style) This chapter describes the general process of trait resolution and points out some non-obvious things. Note: This chapter (and its subchapters) describe how the trait solver currently works. However, we are in t...
Higher-ranked trait bounds One of the more subtle concepts in trait resolution is higher-ranked trait bounds. An example of such a bound is for<'a> MyTrait<&'a isize>. Let's walk through how selection on higher-ranked trait references works...
Caching and subtle considerations therewith In general, we attempt to cache the results of trait selection. This is a somewhat complex process. Part of the reason for this is that we want to be able to cache results even when all the types...
Implied bounds We currently add implied region bounds to avoid explicit annotations. e.g. fn foo<'a, T>(x: &'a T) can freely assume that T: 'a holds without specifying it. There are two kinds of implied bounds: explicit and implicit. Explic...
Specialization TODO: where does Chalk fit in? Should we mention/discuss it here? Defined in the specialize module. The basic strategy is to build up a specialization graph during coherence checking (coherence checking looks for overlapping...
Chalk-based trait solving Chalk is an experimental trait solver for Rust that is (as of May 2022) under development by the Types team. Its goal is to enable a lot of trait system features and bug fixes that are hard to implement (e.g. GATs...
Lowering to logic 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 very similar fas...
Goals and clauses 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 chapter, Rust's trait solver is based on an extension of hereditary...
Canonical queries The "start" of the trait system is the canonical query (these are both queries in the more general sense of the word – something you would like to know the answer to – and in the rustc-specific sense). The idea is that the...
Canonicalization NOTE: FIXME: The content of this chapter has some overlap with Next-gen trait solving Canonicalization chapter. It is suggested to reorganize these contents in the future. Canonicalization is the process of isolating an inf...
Trait solving (new) This chapter describes how trait solving works with the new WIP solver located in rustc_trait_selection/solve. Feel free to also look at the docs for the current solver and the chalk solver. Core concepts The goal of the...
Invariants of the type system FIXME: This file talks about invariants of the type system as a whole, not only the solver There are a lot of invariants - things the type system guarantees to be true at all times - which are desirable or expe...
The solver Also consider reading the documentation for the recursive solver in chalk as it is very similar to this implementation and also talks about limitations of this approach. A rough walkthrough The entry-point of the solver is InferC...
Candidate preference There are multiple ways to prove Trait and NormalizesTo goals. Each such option is called a Candidate. If there are multiple applicable candidates, we prefer some candidates over others. We store the relevant informatio...
Canonicalization Canonicalization is the process of isolating a value from its context and is necessary for global caching of goals which include inference variables. The idea is that given the goals u32: Trait<?x> and u32: Trait<?y>, where...