How to access information computed by compiler passes?

Hi!

We are building a verification tool for Rust, implementing it as a compiler plugin (driver).

We need to access the information computed by a lot of passes (among which the borrow checker, the drop checker, l-values...). Looking at the code of the compiler it seems that those information are often hidden from outside the crates.

For this reason, we plan to depend on a patched version of the compiler, in which we add some pub where required.

I saw that this is the approach used by the Borrow visualizer prototype (https://github.com/Nashenas88/borrow_visualizer_prototype). However, we would like to avoid the overhead of maintaining our fork of the compiler with a patch on top of it.

What do you think? Do you see an easier solution? Could we perhaps hope to push (some of) our patches to the compiler?

@vakaras @Nashenas88

1 Like

I can't speak about your use case specifically, but creating a custom driver (as the borrow visualizer appears to do, and as many other tools including clippy and miri do) is absolutely the recommended way of hooking into the compiler and doing something custom with the compilation pipeline (i.e., pretty much every more complex than a procedural macro). Note that this does not require maintaining a compiler fork, or even building the compiler from source. You just link to librustc* crates, set up some callbacks, and then call an API from the rustc_driver crate.

1 Like

Thanks for the reply. Indeed, we are writing a custom driver and we have acces to a &mut rustc_driver::driver::CompileState<'a, 'tcx>.

The problem is, how can we use a CompileState to access the result of the borrow checker's dataflow analysis? It seems that the result of the librustc_mir::dataflow::do_dataflow call is not stored in CompileState, so we need to patch the librustc_mir::borrow_check::do_mir_borrowck and (somehow) store the result of the dataflow analysis (somewhere). For example, we can add an argument to do_mir_borrowck that is a callback to our code.

This is just for the borrow checker, but we need the same for other passes as well...

1 Like

I see. As I said, I'm not familiar with this part of the compiler. Generally custom drivers can execute arbitrary queries and therefore have access to quite a lot of compiler data, though it might be that the specific borrowck-related data you need is currently not exposed this way.

My experience with that project was that internals changed very frequently, and it was very difficult to maintain as a side project. I would imagine that a full time person on it wouldn't have as much issue as someone working on it a few hours a week. That being said compiler plugins are not guaranteed to be stable. The internal team does not want to lock down its ability to improve the design of the compiler. There is an idea/plan related to the nll work to expose some information to RLS. Check it out Borrow visualizer for the Rust Language Service - #36 by Nashenas88 - tools and infrastructure - Rust Internals . I'm supposed to be the one working on this, but my full time job has begun taking up all of my free time lately. I'll post an update there soon and hopefully someone will take over in the meantime.

I see... Thanks for the info!