The lowering module in rustc
The program clauses described in the
lowering rules section are actually
created in the rustc_traits::lowering
module.
The program_clauses_for
query
The main entry point is the program_clauses_for
query, which –
given a def-id – produces a set of Chalk program clauses. These
queries are tested using a
dedicated unit-testing mechanism, described below. The
query is invoked on a DefId
that identifies something like a trait,
an impl, or an associated item definition. It then produces and
returns a vector of program clauses.
Unit tests
Unit tests are located in src/test/ui/chalkify
. A good
example test is the lower_impl
test. At the time of
this writing, it looked like this:
#![feature(rustc_attrs)]
trait Foo { }
#[rustc_dump_program_clauses] //~ ERROR program clause dump
impl<T: 'static> Foo for T where T: Iterator<Item = i32> { }
fn main() {
println!("hello");
}
The #[rustc_dump_program_clauses]
annotation can be attached to
anything with a def-id. (It requires the rustc_attrs
feature.) The
compiler will then invoke the program_clauses_for
query on that
item, and emit compiler errors that dump the clauses produced. These
errors just exist for unit-testing, as we can then leverage the
standard ui test mechanisms to check them. In this case, there is a
//~ ERROR program clause dump
annotation which is always the same for
#[rustc_dump_program_clauses]
, but the stderr file contains
the full details:
error: program clause dump
--> $DIR/lower_impl.rs:5:1
|
LL | #[rustc_dump_program_clauses]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: forall<T> { Implemented(T: Foo) :- ProjectionEq(<T as std::iter::Iterator>::Item == i32), TypeOutlives(T: 'static), Implemented(T: std::iter::Iterator), Implemented(T: std::marker::Sized). }