]> git.proxmox.com Git - rustc.git/blob - src/librustc_mir/transform/clean_end_regions.rs
New upstream version 1.23.0+dfsg1
[rustc.git] / src / librustc_mir / transform / clean_end_regions.rs
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;
25 use rustc::mir::{BasicBlock, Location, Mir, Rvalue, Statement, StatementKind};
26 use rustc::mir::visit::{MutVisitor, Visitor, TyContext};
27 use rustc::ty::{Ty, RegionKind, TyCtxt};
28 use transform::{MirPass, MirSource};
29
30 pub struct CleanEndRegions;
31
32 struct GatherBorrowedRegions {
33 seen_regions: FxHashSet<region::Scope>,
34 }
35
36 struct DeleteTrivialEndRegions<'a> {
37 seen_regions: &'a FxHashSet<region::Scope>,
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 if !tcx.sess.emit_end_regions() { return; }
46
47 let mut gather = GatherBorrowedRegions {
48 seen_regions: FxHashSet()
49 };
50 gather.visit_mir(mir);
51
52 let mut delete = DeleteTrivialEndRegions { seen_regions: &mut gather.seen_regions };
53 delete.visit_mir(mir);
54 }
55 }
56
57 impl<'tcx> Visitor<'tcx> for GatherBorrowedRegions {
58 fn visit_rvalue(&mut self,
59 rvalue: &Rvalue<'tcx>,
60 location: Location) {
61 // Gather regions that are used for borrows
62 if let Rvalue::Ref(r, _, _) = *rvalue {
63 if let RegionKind::ReScope(ce) = *r {
64 self.seen_regions.insert(ce);
65 }
66 }
67 self.super_rvalue(rvalue, location);
68 }
69
70 fn visit_ty(&mut self, ty: &Ty<'tcx>, _: TyContext) {
71 // Gather regions that occur in types
72 for re in ty.walk().flat_map(|t| t.regions()) {
73 match *re {
74 RegionKind::ReScope(ce) => { self.seen_regions.insert(ce); }
75 _ => {},
76 }
77 }
78 self.super_ty(ty);
79 }
80 }
81
82 impl<'a, 'tcx> MutVisitor<'tcx> for DeleteTrivialEndRegions<'a> {
83 fn visit_statement(&mut self,
84 block: BasicBlock,
85 statement: &mut Statement<'tcx>,
86 location: Location) {
87 let mut delete_it = false;
88
89 if let StatementKind::EndRegion(ref region_scope) = statement.kind {
90 if !self.seen_regions.contains(region_scope) {
91 delete_it = true;
92 }
93 }
94
95 if delete_it {
96 statement.kind = StatementKind::Nop;
97 }
98 self.super_statement(block, statement, location);
99 }
100 }