Skip to content

Commit ba3ce01

Browse files
committed
document the role of the various crates
1 parent f6da755 commit ba3ce01

File tree

1 file changed

+138
-0
lines changed

1 file changed

+138
-0
lines changed

doc/crates.md

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
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

Comments
 (0)