|
| 1 | +# Crates |
| 2 | + |
| 3 | +The chalk library is composed of a number of crates. This is partly |
| 4 | +to help clarify its internal structure, but also to allow parts of |
| 5 | +chalk to be embedded in other programs in a piecemeal fashion. |
| 6 | + |
| 7 | +## Intermediate representations |
| 8 | + |
| 9 | +Chalk contains three levels of IR: |
| 10 | + |
| 11 | +- The **AST**, produced by . This is used purely for writing test cases |
| 12 | + with a Rust-like syntax. This is consumed by **lowering** code, which |
| 13 | + takes AST and products **Rust IR** (the next bullet point). |
| 14 | +- The **Rust IR**. This is a "HIR-like" notation that defines the |
| 15 | + interesting properties of things like traits, impls, and structs. |
| 16 | + It is an input to the **rules** code, which produces |
| 17 | +- The **Chalk IR**. This is most "Prolog-like" of the various IRs. It |
| 18 | + contains the definition of **types** as well as prolog-like concepts |
| 19 | + such as goals (things that must be proven true) and clauses (things |
| 20 | + that are assumed to be true). |
| 21 | + |
| 22 | +## Reusable bits of functionality |
| 23 | + |
| 24 | +There are several re-usable bits of functionality. Each of these |
| 25 | +re-usable bits of code comes associated with a set of traits that |
| 26 | +connect it to the broader whole. |
| 27 | + |
| 28 | +### The "integration" crate (`chalk`) |
| 29 | + |
| 30 | +In the chalk project, the main `chalk` crate is the crate that |
| 31 | +connects all the pieces together, but in a compiler like rustc (or |
| 32 | +rust-analyzer) there would be other types that play that role. We call |
| 33 | +this the **integration** crate. |
| 34 | + |
| 35 | +The role of the integration crate is as follows: |
| 36 | + |
| 37 | +- It configures the solver and stores its state in between solving goals. |
| 38 | +- It defines "the program" -- that is, the set of all traits/impls etc. |
| 39 | +- It gives access to information about the program, such as whether a given |
| 40 | + trait is coinductive, or the Rust IR for a |
| 41 | + |
| 42 | + |
| 43 | +### The chalk-solve crate |
| 44 | + |
| 45 | +| The `chalk-solve` crate | | |
| 46 | +|---|--- | |
| 47 | +| Purpose: | to solve a given goal | |
| 48 | +| Depends on IR: | chalk-ir but not rust-ir | |
| 49 | +| Context required: | `ChalkSolveDatabase` | |
| 50 | + |
| 51 | +The `chalk-solve` crate exposes a key typ called `Solver`. This is a |
| 52 | +solver that, given a goal (expressed in chalk-ir) will solve the goal |
| 53 | +and yield up a `Solution`. The solver caches intermediate data between |
| 54 | +invocations, so solving the same goal twice in a row (or solving goals |
| 55 | +with common subgoals) is faster. |
| 56 | + |
| 57 | +The solver is configured by a type that implements the |
| 58 | +`ChalkSolveDatabase` trait. This trait contains some callbacks that |
| 59 | +provide needed context for the solver -- notably, the solver can ask: |
| 60 | + |
| 61 | +- **What are the program clauses that might solve given rule?** This |
| 62 | + is answered by the code in the chalk-rules crate. |
| 63 | +- **Is this trait coinductive?** This is answered by the rust-ir. |
| 64 | + |
| 65 | +#### The chalk-engine crate |
| 66 | + |
| 67 | +| The `chalk-engine` crate | | |
| 68 | +|---|--- | |
| 69 | +| Purpose: | define the base solving strategy | |
| 70 | +| IR: | none | |
| 71 | +| Context required: | `Context` trait | |
| 72 | + |
| 73 | +For the purposes of chalk, the `chalk-engine` crate is effectively |
| 74 | +encapsulated by `chalk-solve`. It defines the base SLG engine. It is |
| 75 | +written in a very generic style that knows next to nothing about Rust |
| 76 | +itself. In particular, it does not depend on any of the Chalk IRs, |
| 77 | +which allows it to be used by rustc (which currently doesn't use |
| 78 | +chalk-ir). The engine can be configured via the traits defined in |
| 79 | +`chalk_engine::context::Context`, which contain (for example) |
| 80 | +associated types that define what a goal or clause is, as well as |
| 81 | +functions that operate on those things. |
| 82 | + |
| 83 | +### The chalk-rules crate |
| 84 | + |
| 85 | +| The `chalk-rules` crate | | |
| 86 | +|---|--- | |
| 87 | +| Purpose: | create chalk-ir goals/clauses given rust-ir | |
| 88 | +| Depends on IR: | chalk-ir and rust-ir | |
| 89 | +| Context required: | `Context` trait | |
| 90 | + |
| 91 | +The `chalk-rules` defines code that "lowers" rust-ir into chalk-ir, |
| 92 | +producing both goals and clauses. |
| 93 | + |
| 94 | +- For example, the `clauses` module defines a trait |
| 95 | + (`ToProgramClauses`) that is implemented for various bits of |
| 96 | + rust-ir. It might (for example) lower an impl into a set of program |
| 97 | + clauses. |
| 98 | +- The coherence rules are defined in the `coherence` module; these |
| 99 | + include code to check if an impl meets the orphan rules, and to |
| 100 | + check for overlap between impls. |
| 101 | + - These can also return information about the specialization tree |
| 102 | + for a given trait. |
| 103 | +- Finally, the well-formedness rules are defined in the `wf` module. |
| 104 | + |
| 105 | +The chalk-rules crate defines a `ChalkRulesDatabase` trait that contains |
| 106 | +a number of callbacks that it needs. These callbacks are grouped into |
| 107 | +two sub-traits: |
| 108 | + |
| 109 | +- The `GoalSolver` trait, which exposes a `solve` method for solving |
| 110 | + goals. This solving is ultimately done by the code in the |
| 111 | + `chalk-solve` crate. |
| 112 | +- The `RustIrSource` trait, which offers a number of accessors to |
| 113 | + fetch rust-ir. For example, the `trait_datum` method returns the |
| 114 | + `TraitDatum` for a given `TraitId`. |
| 115 | + - Note that -- by design -- this trait does not include any |
| 116 | + "open-ended" methods that ask queries like "return all the impls |
| 117 | + in the program" or "return all structs". These sorts of open-ended |
| 118 | + walks are expected to be performed at an outer level (in our case, |
| 119 | + in the chalk crate). |
| 120 | + |
| 121 | +## The flow |
| 122 | + |
| 123 | +This section tries to document how the flow of information proceeds in |
| 124 | +the main chalk testing harness. This can help give an idea how all the |
| 125 | +parts of the system interact. |
| 126 | + |
| 127 | +- To begin with, the integration crate is asked to solve some goal |
| 128 | + (via `ChalkRulesDatabase::solve`, for example). |
| 129 | +- It will get access to its internal `Solver` (instantiating one, if |
| 130 | + one does not already exist) and invoke the `Solver::solve` method. |
| 131 | +- The solver may periodically request the set of applicable program clauses |
| 132 | + for the main goal or some subgoal. |
| 133 | +- The integration crate will examine the goal in question and use the code in the `chalk-rules` |
| 134 | + crate to instantiate program clauses. |
| 135 | + - This may, in the case of specialization, require recursively solving goals. |
| 136 | +- Once the program clauses are known, the solver can continue. It may |
| 137 | + periodically ask the integration crate whether a given bit of IR is |
| 138 | + coinductive. |
0 commit comments