|
| 1 | +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT |
| 2 | +// file at the top-level directory of this distribution and at |
| 3 | +// http://rust-lang.org/COPYRIGHT. |
| 4 | +// |
| 5 | +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or |
| 6 | +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license |
| 7 | +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your |
| 8 | +// option. This file may not be copied, modified, or distributed |
| 9 | +// except according to those terms. |
| 10 | + |
| 11 | +//! This module provides one pass, `CleanEndRegions`, that reduces the |
| 12 | +//! set of `EndRegion` statements in the MIR. |
| 13 | +//! |
| 14 | +//! The "pass" is actually implemented as two traversals (aka visits) |
| 15 | +//! of the input MIR. The first traversal, `GatherBorrowedRegions`, |
| 16 | +//! finds all of the regions in the MIR that are involved in a borrow. |
| 17 | +//! |
| 18 | +//! The second traversal, `DeleteTrivialEndRegions`, walks over the |
| 19 | +//! MIR and removes any `EndRegion` that is applied to a region that |
| 20 | +//! was not seen in the previous pass. |
| 21 | +
|
| 22 | +use rustc_data_structures::fx::FxHashSet; |
| 23 | + |
| 24 | +use rustc::middle::region::CodeExtent; |
| 25 | +use rustc::mir::transform::{MirPass, MirSource}; |
| 26 | +use rustc::mir::{BasicBlock, Location, Mir, Rvalue, Statement, StatementKind}; |
| 27 | +use rustc::mir::visit::{MutVisitor, Visitor}; |
| 28 | +use rustc::ty::{RegionKind, TyCtxt}; |
| 29 | + |
| 30 | +pub struct CleanEndRegions; |
| 31 | + |
| 32 | +struct GatherBorrowedRegions { |
| 33 | + seen_regions: FxHashSet<CodeExtent>, |
| 34 | +} |
| 35 | + |
| 36 | +struct DeleteTrivialEndRegions<'a> { |
| 37 | + seen_regions: &'a FxHashSet<CodeExtent>, |
| 38 | +} |
| 39 | + |
| 40 | +impl MirPass for CleanEndRegions { |
| 41 | + fn run_pass<'a, 'tcx>(&self, |
| 42 | + _tcx: TyCtxt<'a, 'tcx, 'tcx>, |
| 43 | + _source: MirSource, |
| 44 | + mir: &mut Mir<'tcx>) { |
| 45 | + let mut gather = GatherBorrowedRegions { seen_regions: FxHashSet() }; |
| 46 | + gather.visit_mir(mir); |
| 47 | + |
| 48 | + let mut delete = DeleteTrivialEndRegions { seen_regions: &mut gather.seen_regions }; |
| 49 | + delete.visit_mir(mir); |
| 50 | + } |
| 51 | +} |
| 52 | + |
| 53 | +impl<'tcx> Visitor<'tcx> for GatherBorrowedRegions { |
| 54 | + fn visit_rvalue(&mut self, |
| 55 | + rvalue: &Rvalue<'tcx>, |
| 56 | + location: Location) { |
| 57 | + if let Rvalue::Ref(r, _, _) = *rvalue { |
| 58 | + if let RegionKind::ReScope(ce) = *r { |
| 59 | + self.seen_regions.insert(ce); |
| 60 | + } |
| 61 | + } |
| 62 | + self.super_rvalue(rvalue, location); |
| 63 | + } |
| 64 | +} |
| 65 | + |
| 66 | +impl<'a, 'tcx> MutVisitor<'tcx> for DeleteTrivialEndRegions<'a> { |
| 67 | + fn visit_statement(&mut self, |
| 68 | + block: BasicBlock, |
| 69 | + statement: &mut Statement<'tcx>, |
| 70 | + location: Location) { |
| 71 | + let mut delete_it = false; |
| 72 | + |
| 73 | + if let StatementKind::EndRegion(ref extent) = statement.kind { |
| 74 | + if !self.seen_regions.contains(extent) { |
| 75 | + delete_it = true; |
| 76 | + } |
| 77 | + } |
| 78 | + |
| 79 | + if delete_it { |
| 80 | + statement.kind = StatementKind::Nop; |
| 81 | + } |
| 82 | + self.super_statement(block, statement, location); |
| 83 | + } |
| 84 | +} |
0 commit comments