| //! This module provides a pass that removes parts of MIR that are no longer relevant after |
| //! analysis phase and borrowck. In particular, it removes false edges, user type annotations and |
| //! replaces following statements with [`Nop`]s: |
| //! |
| //! - [`AscribeUserType`] |
| //! - [`FakeRead`] |
| //! - [`Assign`] statements with a [`Fake`] borrow |
| //! - [`Coverage`] statements of kind [`BlockMarker`] or [`SpanMarker`] |
| //! |
| //! [`AscribeUserType`]: rustc_middle::mir::StatementKind::AscribeUserType |
| //! [`Assign`]: rustc_middle::mir::StatementKind::Assign |
| //! [`FakeRead`]: rustc_middle::mir::StatementKind::FakeRead |
| //! [`Nop`]: rustc_middle::mir::StatementKind::Nop |
| //! [`Fake`]: rustc_middle::mir::BorrowKind::Fake |
| //! [`Coverage`]: rustc_middle::mir::StatementKind::Coverage |
| //! [`BlockMarker`]: rustc_middle::mir::coverage::CoverageKind::BlockMarker |
| //! [`SpanMarker`]: rustc_middle::mir::coverage::CoverageKind::SpanMarker |
| |
| use rustc_middle::mir::coverage::CoverageKind; |
| use rustc_middle::mir::{Body, BorrowKind, CastKind, Rvalue, StatementKind, TerminatorKind}; |
| use rustc_middle::ty::TyCtxt; |
| use rustc_middle::ty::adjustment::PointerCoercion; |
| |
| pub(super) struct CleanupPostBorrowck; |
| |
| impl<'tcx> crate::MirPass<'tcx> for CleanupPostBorrowck { |
| fn run_pass(&self, _tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { |
| for basic_block in body.basic_blocks.as_mut() { |
| for statement in basic_block.statements.iter_mut() { |
| match statement.kind { |
| StatementKind::AscribeUserType(..) |
| | StatementKind::Assign(box (_, Rvalue::Ref(_, BorrowKind::Fake(_), _))) |
| | StatementKind::Coverage( |
| // These kinds of coverage statements are markers inserted during |
| // MIR building, and are not needed after InstrumentCoverage. |
| CoverageKind::BlockMarker { .. } | CoverageKind::SpanMarker { .. }, |
| ) |
| | StatementKind::FakeRead(..) |
| | StatementKind::BackwardIncompatibleDropHint { .. } => statement.make_nop(), |
| StatementKind::Assign(box ( |
| _, |
| Rvalue::Cast( |
| ref mut cast_kind @ CastKind::PointerCoercion( |
| PointerCoercion::ArrayToPointer |
| | PointerCoercion::MutToConstPointer, |
| _, |
| ), |
| .., |
| ), |
| )) => { |
| // BorrowCk needed to track whether these cases were coercions or casts, |
| // to know whether to check lifetimes in their pointees, |
| // but from now on that distinction doesn't matter, |
| // so just make them ordinary pointer casts instead. |
| *cast_kind = CastKind::PtrToPtr; |
| } |
| _ => (), |
| } |
| } |
| let terminator = basic_block.terminator_mut(); |
| match terminator.kind { |
| TerminatorKind::FalseEdge { real_target, .. } |
| | TerminatorKind::FalseUnwind { real_target, .. } => { |
| terminator.kind = TerminatorKind::Goto { target: real_target }; |
| } |
| _ => {} |
| } |
| } |
| |
| body.user_type_annotations.raw.clear(); |
| |
| for decl in &mut body.local_decls { |
| decl.user_ty = None; |
| } |
| } |
| |
| fn is_required(&self) -> bool { |
| true |
| } |
| } |