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.
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.
11 //! This module provides one pass, `CleanEndRegions`, that reduces the
12 //! set of `EndRegion` statements in the MIR.
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.
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.
22 use rustc_data_structures
::fx
::FxHashSet
;
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}
;
30 pub struct CleanEndRegions
;
32 struct GatherBorrowedRegions
{
33 seen_regions
: FxHashSet
<region
::Scope
>,
36 struct DeleteTrivialEndRegions
<'a
> {
37 seen_regions
: &'a FxHashSet
<region
::Scope
>,
40 impl MirPass
for CleanEndRegions
{
41 fn run_pass
<'a
, 'tcx
>(&self,
42 tcx
: TyCtxt
<'a
, 'tcx
, 'tcx
>,
44 mir
: &mut Mir
<'tcx
>) {
45 if !tcx
.sess
.emit_end_regions() { return; }
47 let mut gather
= GatherBorrowedRegions
{
48 seen_regions
: FxHashSet()
50 gather
.visit_mir(mir
);
52 let mut delete
= DeleteTrivialEndRegions { seen_regions: &mut gather.seen_regions }
;
53 delete
.visit_mir(mir
);
57 impl<'tcx
> Visitor
<'tcx
> for GatherBorrowedRegions
{
58 fn visit_rvalue(&mut self,
59 rvalue
: &Rvalue
<'tcx
>,
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
);
67 self.super_rvalue(rvalue
, location
);
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()) {
74 RegionKind
::ReScope(ce
) => { self.seen_regions.insert(ce); }
82 impl<'a
, 'tcx
> MutVisitor
<'tcx
> for DeleteTrivialEndRegions
<'a
> {
83 fn visit_statement(&mut self,
85 statement
: &mut Statement
<'tcx
>,
87 let mut delete_it
= false;
89 if let StatementKind
::EndRegion(ref region_scope
) = statement
.kind
{
90 if !self.seen_regions
.contains(region_scope
) {
96 statement
.kind
= StatementKind
::Nop
;
98 self.super_statement(block
, statement
, location
);