|
| 1 | +# The lowering module in rustc |
| 2 | + |
| 3 | +The program clauses described in the |
| 4 | +[lowering rules](./traits-lowering-rules.html) section are actually |
| 5 | +created in the [`rustc_traits::lowering`][lowering] module. |
| 6 | + |
| 7 | +[lowering]: https://github.com/rust-lang/rust/tree/master/src/librustc_traits/lowering.rs |
| 8 | + |
| 9 | +## The `program_clauses_for` query |
| 10 | + |
| 11 | +The main entry point is the `program_clauses_for` [query], which -- |
| 12 | +given a def-id -- produces a set of Chalk program clauses. These |
| 13 | +queries are tested using a |
| 14 | +[dedicated unit-testing mechanism, described below](#unit-tests). The |
| 15 | +query is invoked on a `DefId` that identifies something like a trait, |
| 16 | +an impl, or an associated item definition. It then produces and |
| 17 | +returns a vector of program clauses. |
| 18 | + |
| 19 | +[query]: ./query.html |
| 20 | + |
| 21 | +<a name=unit-tests> |
| 22 | + |
| 23 | +## Unit tests |
| 24 | + |
| 25 | +Unit tests are located in [`src/test/ui/chalkify`][chalkify]. A good |
| 26 | +example test is [the `lower_impl` test][lower_impl]. At the time of |
| 27 | +this writing, it looked like this: |
| 28 | + |
| 29 | +```rust |
| 30 | +#![feature(rustc_attrs)] |
| 31 | + |
| 32 | +trait Foo { } |
| 33 | + |
| 34 | +#[rustc_dump_program_clauses] //~ ERROR Implemented(T: Foo) :- |
| 35 | +impl<T: 'static> Foo for T where T: Iterator<Item = i32> { } |
| 36 | + |
| 37 | +fn main() { |
| 38 | + println!("hello"); |
| 39 | +} |
| 40 | +``` |
| 41 | + |
| 42 | +The `#[rustc_dump_program_clauses]` annotation can be attached to |
| 43 | +anything with a def-id. (It requires the `rustc_attrs` feature.) The |
| 44 | +compiler will then invoke the `program_clauses_for` query on that |
| 45 | +item, and emit compiler errors that dump the clauses produced. These |
| 46 | +errors just exist for unit-testing, as we can then leverage the |
| 47 | +standard [ui test] mechanisms to check them. In this case, there is a |
| 48 | +`//~ ERROR Implemented` annotation which is intentionally minimal (it |
| 49 | +need only be a prefix of the error), but [the stderr file] contains |
| 50 | +the full details: |
| 51 | + |
| 52 | +``` |
| 53 | +error: Implemented(T: Foo) :- ProjectionEq(<T as std::iter::Iterator>::Item == i32), TypeOutlives(T \ |
| 54 | +: 'static), Implemented(T: std::iter::Iterator), Implemented(T: std::marker::Sized). |
| 55 | + --> $DIR/lower_impl.rs:15:1 |
| 56 | + | |
| 57 | +LL | #[rustc_dump_program_clauses] //~ ERROR Implemented(T: Foo) :- |
| 58 | + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
| 59 | +
|
| 60 | +error: aborting due to previous error |
| 61 | +``` |
| 62 | + |
| 63 | +[chalkify]: https://github.com/rust-lang/rust/tree/master/src/test/ui/chalkify |
| 64 | +[lower_impl]: https://github.com/rust-lang/rust/tree/master/src/test/ui/chalkify/lower_impl.rs |
| 65 | +[the stderr file]: https://github.com/rust-lang/rust/tree/master/src/test/ui/chalkify/lower_impl.stderr |
| 66 | +[ui test]: https://rust-lang-nursery.github.io/rustc-guide/tests/adding.html#guide-to-the-ui-tests |
0 commit comments