I'm working on a research project where I modify the Rust compiler to (1) look for any object definitions of a certain type, (2) trace their uses, then (3) modify some related statements before/after the use.
Right now I can successfully use a depth-first search to follow a def to all its uses using rustc_mir::util::DefUseAnalysis
in the MIR, including through function calls and closures. However, now I'm stuck on how to modify statements in multiple MIR Body
structs (step 3).
I have defined a struct that implements the MirPass
trait and added it as a new MIR optimization pass. The run_pass
function takes &mut Body<'tcx>
as an argument, so obviously you can modify the MIR of the current function, but can I get a mutable reference to the called functions' MIR? I can't see a way to do this without calling something like tcx.mir_built(fn_call_def_id).
steal()
, which will later cause a compiler error because the value can only be stolen once and it needs to be stolen later.
For example, suppose we have the following code:
fn foo() {
let my_object = MyType::new();
bar(my_object);
}
fn bar(my_object: MyType) {
my_object.baz(1);
}
I can recognize the definition of my_object
in foo
and its use in bar
. Now I want to modify the MIR in bar
, for example, by changing the argument from 1 to 2. However, we're only running an MIR pass on foo
, not bar
, so we don't have a mutable reference to the Body
struct of bar
. Is it even possible to get a mutable reference to bar
inside foo
's run_pass
?
Please let me know if I can better clarify my problem. Since this is a research project, I'm open to "hacky" solutions that work for a proof of concept.