]> git.proxmox.com Git - rustc.git/blame - src/doc/rustc-guide/src/traits/chalk-overview.md
New upstream version 1.42.0+dfsg0+pve1
[rustc.git] / src / doc / rustc-guide / src / traits / chalk-overview.md
CommitLineData
a1dfa0c6
XL
1# An Overview of Chalk
2
3> Chalk is under heavy development, so if any of these links are broken or if
4> any of the information is inconsistent with the code or outdated, please
5> [open an issue][rustc-issues] so we can fix it. If you are able to fix the
6> issue yourself, we would love your contribution!
7
8[Chalk][chalk] recasts Rust's trait system explicitly in terms of logic
9programming by "lowering" Rust code into a kind of logic program we can then
46de9a89
FG
10execute queries against (see [*Lowering to Logic*][lowering-to-logic] and
11[*Lowering Rules*][lowering-rules]). Its goal is to be an executable, highly
a1dfa0c6
XL
12readable specification of the Rust trait system.
13
14There are many expected benefits from this work. It will consolidate our
15existing, somewhat ad-hoc implementation into something far more principled and
16expressive, which should behave better in corner cases, and be much easier to
17extend.
18
19## Chalk Structure
20
21Chalk has two main "products". The first of these is the
22[`chalk_engine`][chalk_engine] crate, which defines the core [SLG
23solver][slg]. This is the part rustc uses.
24
25The rest of chalk can be considered an elaborate testing harness. Chalk is
26capable of parsing Rust-like "programs", lowering them to logic, and
27performing queries on them.
28
29Here's a sample session in the chalk repl, chalki. After feeding it our
30program, we perform some queries on it.
31
32```rust,ignore
33?- program
34Enter a program; press Ctrl-D when finished
35| struct Foo { }
36| struct Bar { }
37| struct Vec<T> { }
38| trait Clone { }
39| impl<T> Clone for Vec<T> where T: Clone { }
40| impl Clone for Foo { }
41
42?- Vec<Foo>: Clone
43Unique; substitution [], lifetime constraints []
44
45?- Vec<Bar>: Clone
46No possible solution.
47
48?- exists<T> { Vec<T>: Clone }
49Ambiguous; no inference guidance
50```
51
52You can see more examples of programs and queries in the [unit
53tests][chalk-test-example].
54
55Next we'll go through each stage required to produce the output above.
56
57### Parsing ([chalk_parse])
58
59Chalk is designed to be incorporated with the Rust compiler, so the syntax and
60concepts it deals with heavily borrow from Rust. It is convenient for the sake
61of testing to be able to run chalk on its own, so chalk includes a parser for a
62Rust-like syntax. This syntax is orthogonal to the Rust AST and grammar. It is
63not intended to look exactly like it or support the exact same syntax.
64
65The parser takes that syntax and produces an [Abstract Syntax Tree (AST)][ast].
66You can find the [complete definition of the AST][chalk-ast] in the source code.
67
68The syntax contains things from Rust that we know and love, for example: traits,
69impls, and struct definitions. Parsing is often the first "phase" of
70transformation that a program goes through in order to become a format that
71chalk can understand.
72
48663c56 73### Rust Intermediate Representation ([chalk_rust_ir])
a1dfa0c6
XL
74
75After getting the AST we convert it to a more convenient intermediate
48663c56
XL
76representation called [`chalk_rust_ir`][chalk_rust_ir]. This is sort of
77analogous to the [HIR] in Rust. The process of converting to IR is called
78*lowering*.
a1dfa0c6 79
48663c56 80The [`chalk::program::Program`][chalk-program] struct contains some "rust things"
a1dfa0c6
XL
81but indexed and accessible in a different way. For example, if you have a
82type like `Foo<Bar>`, we would represent `Foo` as a string in the AST but in
48663c56 83`chalk::program::Program`, we use numeric indices (`ItemId`).
a1dfa0c6
XL
84
85The [IR source code][ir-code] contains the complete definition.
86
87### Chalk Intermediate Representation ([chalk_ir])
88
89Once we have Rust IR it is time to convert it to "program clauses". A
90[`ProgramClause`] is essentially one of the following:
91
92* A [clause] of the form `consequence :- conditions` where `:-` is read as
93 "if" and `conditions = cond1 && cond2 && ...`
94* A universally quantified clause of the form
95 `forall<T> { consequence :- conditions }`
96 * `forall<T> { ... }` is used to represent [universal quantification]. See the
97 section on [Lowering to logic][lowering-forall] for more information.
98 * A key thing to note about `forall` is that we don't allow you to "quantify"
99 over traits, only types and regions (lifetimes). That is, you can't make a
100 rule like `forall<Trait> { u32: Trait }` which would say "`u32` implements
101 all traits". You can however say `forall<T> { T: Trait }` meaning "`Trait`
102 is implemented by all types".
103 * `forall<T> { ... }` is represented in the code using the [`Binders<T>`
104 struct][binders-struct].
105
106*See also: [Goals and Clauses][goals-and-clauses]*
107
108This is where we encode the rules of the trait system into logic. For
109example, if we have the following Rust:
110
111```rust,ignore
112impl<T: Clone> Clone for Vec<T> {}
113```
114
115We generate the following program clause:
116
117```rust,ignore
118forall<T> { (Vec<T>: Clone) :- (T: Clone) }
119```
120
121This rule dictates that `Vec<T>: Clone` is only satisfied if `T: Clone` is also
122satisfied (i.e. "provable").
123
48663c56
XL
124Similar to [`chalk::program::Program`][chalk-program] which has "rust-like
125things", chalk_ir defines [`ProgramEnvironment`] which is "pure logic".
a1dfa0c6
XL
126The main field in that struct is `program_clauses`, which contains the
127[`ProgramClause`]s generated by the rules module.
128
dc9dc135 129### Rules ([chalk_solve])
a1dfa0c6 130
dc9dc135
XL
131The `chalk_solve` crate ([source code][chalk_solve]) defines the logic rules we
132use for each item in the Rust IR. It works by iterating over every trait, impl,
a1dfa0c6
XL
133etc. and emitting the rules that come from each one.
134
135*See also: [Lowering Rules][lowering-rules]*
136
137#### Well-formedness checks
138
139As part of lowering to logic, we also do some "well formedness" checks. See
dc9dc135 140the [`chalk_solve::wf` source code][solve-wf-src] for where those are done.
a1dfa0c6
XL
141
142*See also: [Well-formedness checking][wf-checking]*
143
144#### Coherence
145
48663c56 146The method `CoherenceSolver::specialization_priorities` in the `coherence` module
a1dfa0c6
XL
147([source code][coherence-src]) checks "coherence", which means that it
148ensures that two impls of the same trait for the same type cannot exist.
149
150### Solver ([chalk_solve])
151
152Finally, when we've collected all the program clauses we care about, we want
153to perform queries on it. The component that finds the answer to these
154queries is called the *solver*.
155
156*See also: [The SLG Solver][slg]*
157
158## Crates
159
160Chalk's functionality is broken up into the following crates:
161- [**chalk_engine**][chalk_engine]: Defines the core [SLG solver][slg].
48663c56 162- [**chalk_rust_ir**][chalk_rust_ir], containing the "HIR-like" form of the AST
a1dfa0c6
XL
163- [**chalk_ir**][chalk_ir]: Defines chalk's internal representation of
164 types, lifetimes, and goals.
165- [**chalk_solve**][chalk_solve]: Combines `chalk_ir` and `chalk_engine`,
dc9dc135
XL
166 effectively, which implements logic rules converting `chalk_rust_ir` to
167 `chalk_ir`
168 - Defines the `coherence` module, which implements coherence rules
a1dfa0c6
XL
169 - [`chalk_engine::context`][engine-context] provides the necessary hooks.
170- [**chalk_parse**][chalk_parse]: Defines the raw AST and a parser.
171- [**chalk**][doc-chalk]: Brings everything together. Defines the following
172 modules:
48663c56 173 - `chalk::lowering`, which converts AST to `chalk_rust_ir`
a1dfa0c6
XL
174 - Also includes [chalki][chalki], chalk's REPL.
175
532ac7d7 176[Browse source code on GitHub](https://github.com/rust-lang/chalk)
a1dfa0c6
XL
177
178## Testing
179
180chalk has a test framework for lowering programs to logic, checking the
181lowered logic, and performing queries on it. This is how we test the
182implementation of chalk itself, and the viability of the [lowering
183rules][lowering-rules].
184
185The main kind of tests in chalk are **goal tests**. They contain a program,
186which is expected to lower to logic successfully, and a set of queries
187(goals) along with the expected output. Here's an
188[example][chalk-test-example]. Since chalk's output can be quite long, goal
189tests support specifying only a prefix of the output.
190
191**Lowering tests** check the stages that occur before we can issue queries
48663c56 192to the solver: the [lowering to chalk_rust_ir][chalk-test-lowering], and the
a1dfa0c6
XL
193[well-formedness checks][chalk-test-wf] that occur after that.
194
195### Testing internals
196
197Goal tests use a [`test!` macro][test-macro] that takes chalk's Rust-like
198syntax and runs it through the full pipeline described above. The macro
199ultimately calls the [`solve_goal` function][solve_goal].
200
201Likewise, lowering tests use the [`lowering_success!` and
202`lowering_error!` macros][test-lowering-macros].
203
204## More Resources
205
532ac7d7
XL
206* [Chalk Source Code](https://github.com/rust-lang/chalk)
207* [Chalk Glossary](https://github.com/rust-lang/chalk/blob/master/GLOSSARY.md)
a1dfa0c6
XL
208
209### Blog Posts
210
211* [Lowering Rust traits to logic](http://smallcultfollowing.com/babysteps/blog/2017/01/26/lowering-rust-traits-to-logic/)
212* [Unification in Chalk, part 1](http://smallcultfollowing.com/babysteps/blog/2017/03/25/unification-in-chalk-part-1/)
213* [Unification in Chalk, part 2](http://smallcultfollowing.com/babysteps/blog/2017/04/23/unification-in-chalk-part-2/)
d9bb1a4e 214* [Negative reasoning in Chalk](https://aturon.github.io/blog/2017/04/24/negative-chalk/)
a1dfa0c6
XL
215* [Query structure in chalk](http://smallcultfollowing.com/babysteps/blog/2017/05/25/query-structure-in-chalk/)
216* [Cyclic queries in chalk](http://smallcultfollowing.com/babysteps/blog/2017/09/12/tabling-handling-cyclic-queries-in-chalk/)
217* [An on-demand SLG solver for chalk](http://smallcultfollowing.com/babysteps/blog/2018/01/31/an-on-demand-slg-solver-for-chalk/)
218
219[goals-and-clauses]: ./goals-and-clauses.html
220[HIR]: ../hir.html
221[lowering-forall]: ./lowering-to-logic.html#type-checking-generic-functions-beyond-horn-clauses
222[lowering-rules]: ./lowering-rules.html
223[lowering-to-logic]: ./lowering-to-logic.html
224[slg]: ./slg.html
225[wf-checking]: ./wf.html
226
227[ast]: https://en.wikipedia.org/wiki/Abstract_syntax_tree
532ac7d7
XL
228[chalk]: https://github.com/rust-lang/chalk
229[rustc-issues]: https://github.com/rust-lang/rustc-guide/issues
a1dfa0c6
XL
230[universal quantification]: https://en.wikipedia.org/wiki/Universal_quantification
231
d9bb1a4e
FG
232[`ProgramClause`]: https://rust-lang.github.io/chalk/chalk_ir/enum.ProgramClause.html
233[`ProgramEnvironment`]: https://rust-lang.github.io/chalk/chalk_integration/program_environment/struct.ProgramEnvironment.html
234[chalk_engine]: https://rust-lang.github.io/chalk/chalk_engine
235[chalk_ir]: https://rust-lang.github.io/chalk/chalk_ir/index.html
236[chalk_parse]: https://rust-lang.github.io/chalk/chalk_parse/index.html
237[chalk_solve]: https://rust-lang.github.io/chalk/chalk_solve/index.html
238[chalk_rust_ir]: https://rust-lang.github.io/chalk/chalk_rust_ir/index.html
239[doc-chalk]: https://rust-lang.github.io/chalk/chalk/index.html
240[engine-context]: https://rust-lang.github.io/chalk/chalk_engine/context/index.html
241[chalk-program]: https://rust-lang.github.io/chalk/chalk_integration/program/struct.Program.html
242
243[binders-struct]: https://rust-lang.github.io/chalk/chalk_ir/struct.Binders.html
244[chalk-ast]: https://rust-lang.github.io/chalk/chalk_parse/ast/index.html
532ac7d7
XL
245[chalk-test-example]: https://github.com/rust-lang/chalk/blob/4bce000801de31bf45c02f742a5fce335c9f035f/src/test.rs#L115
246[chalk-test-lowering-example]: https://github.com/rust-lang/chalk/blob/4bce000801de31bf45c02f742a5fce335c9f035f/src/rust_ir/lowering/test.rs#L8-L31
247[chalk-test-lowering]: https://github.com/rust-lang/chalk/blob/4bce000801de31bf45c02f742a5fce335c9f035f/src/rust_ir/lowering/test.rs
248[chalk-test-wf]: https://github.com/rust-lang/chalk/blob/4bce000801de31bf45c02f742a5fce335c9f035f/src/rules/wf/test.rs#L1
d9bb1a4e 249[chalki]: https://github.com/rust-lang/chalk/blob/master/src/main.rs
532ac7d7 250[clause]: https://github.com/rust-lang/chalk/blob/master/GLOSSARY.md#clause
d9bb1a4e
FG
251[coherence-src]: https://rust-lang.github.io/chalk/chalk_solve/coherence/index.html
252[ir-code]: https://rust-lang.github.io/chalk/chalk_rust_ir/
253[solve-wf-src]: https://rust-lang.github.io/chalk/chalk_solve/wf/index.html
532ac7d7
XL
254[solve_goal]: https://github.com/rust-lang/chalk/blob/4bce000801de31bf45c02f742a5fce335c9f035f/src/test.rs#L85
255[test-lowering-macros]: https://github.com/rust-lang/chalk/blob/4bce000801de31bf45c02f742a5fce335c9f035f/src/test_util.rs#L21-L54
256[test-macro]: https://github.com/rust-lang/chalk/blob/4bce000801de31bf45c02f742a5fce335c9f035f/src/test.rs#L33