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