Skip to main content

rustc_mir_transform/
erase_deref_temps.rs

1//! This pass converts all `DerefTemp` locals into normal temporaries
2//! and turns their `CopyForDeref` rvalues into normal copies.
3
4use rustc_middle::mir::visit::MutVisitor;
5use rustc_middle::mir::*;
6use rustc_middle::ty::TyCtxt;
7
8use crate::PassPolicy;
9
10struct EraseDerefTempsVisitor<'tcx> {
11    tcx: TyCtxt<'tcx>,
12}
13
14impl<'tcx> MutVisitor<'tcx> for EraseDerefTempsVisitor<'tcx> {
15    fn tcx(&self) -> TyCtxt<'tcx> {
16        self.tcx
17    }
18
19    fn visit_rvalue(&mut self, rvalue: &mut Rvalue<'tcx>, _: Location) {
20        if let &mut Rvalue::CopyForDeref(place) = rvalue {
21            // We do *NOT* want a retag here! This assignment might copy a mutable reference we
22            // can't actually copy, we just need it temporarily to create another pointer.
23            *rvalue = Rvalue::Use(Operand::Copy(place), WithRetag::No)
24        }
25    }
26
27    fn visit_local_decl(&mut self, _: Local, local_decl: &mut LocalDecl<'tcx>) {
28        if local_decl.is_deref_temp() {
29            let info = local_decl.local_info.as_mut().unwrap_crate_local();
30            **info = LocalInfo::Boring;
31        }
32    }
33}
34
35pub(super) struct EraseDerefTemps;
36
37impl<'tcx> crate::MirPass<'tcx> for EraseDerefTemps {
38    fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
39        EraseDerefTempsVisitor { tcx }.visit_body_preserves_cfg(body);
40    }
41
42    fn policy(&self, _sess: &rustc_session::Session) -> PassPolicy {
43        // Later MIR stages assume that CopyForDeref is gone.
44        PassPolicy::Required
45    }
46}