Expand description

Contains the logic to lower rustc types into Chalk types

In many cases there is a 1:1 relationship between a rustc type and a Chalk type. For example, a SubstsRef maps almost directly to a Substitution. In some other cases, such as Params, there is no Chalk type, so we have to handle accordingly.

Ty lowering

Much of the Ty lowering is 1:1 with Chalk. (Or will be eventually). A helpful table for what types lower to what can be found in the Chalk book. The most notable difference lies with Params. To convert from rustc to Chalk, we eagerly and deeply convert Params to placeholders (in goals) or bound variables (for clause generation through functions in db).

Region lowering

Regions are handled in rustc and Chalk is quite differently. In rustc, there is a difference between “early bound” and “late bound” regions, where only the late bound regions have a DebruijnIndex. Moreover, in Chalk all regions (Lifetimes) have an associated index. In rustc, only BrAnons have an index, whereas BrNamed don’t. In order to lower regions to Chalk, we convert all regions into BrAnon late-bound regions.

Const lowering

Chalk doesn’t handle consts currently, so consts are currently lowered to an empty tuple.

Bound variable collection

Another difference between rustc and Chalk lies in the handling of binders. Chalk requires that we store the bound parameter kinds, whereas rustc does not. To lower anything wrapped in a Binder, we first deeply find any bound variables from the current Binder.

Structs

This is used to replace BoundRegionKind::BrNamed with BoundRegionKind::BrAnon. Note: we assume that we will always have room for more bound vars. (i.e. we won’t ever hit the u32 limit in BrAnons).
Used to substitute Params with placeholders. We do this since Chalk have a notion of Params.
Used to collect Placeholders.

Traits

LowerInto 🔒
Essentially an Into with a &RustInterner parameter

Functions

To collect bound vars, we have to do two passes. In the first pass, we collect all BoundRegionKinds and ty::Bounds. In the second pass, we then replace BrNamed into BrAnon. The two separate passes are important, since we can only replace BrNamed with BrAnons with indices after all “real” BrAnons.