]>
Commit | Line | Data |
---|---|---|
041b39d2 XL |
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 | ||
0531ce1d | 11 | //! This module provides two passes: |
041b39d2 | 12 | //! |
a1dfa0c6 XL |
13 | //! - [CleanAscribeUserType], that replaces all |
14 | //! [StatementKind::AscribeUserType] statements with [StatementKind::Nop]. | |
15 | //! - [CleanFakeReadsAndBorrows], that replaces all [FakeRead] statements and | |
16 | //! borrows that are read by [FakeReadCause::ForMatchGuard] fake reads with | |
17 | //! [StatementKind::Nop]. | |
0531ce1d | 18 | //! |
a1dfa0c6 | 19 | //! The [CleanFakeReadsAndBorrows] "pass" is actually implemented as two |
0531ce1d | 20 | //! traversals (aka visits) of the input MIR. The first traversal, |
a1dfa0c6 XL |
21 | //! [DeleteAndRecordFakeReads], deletes the fake reads and finds the temporaries |
22 | //! read by [ForMatchGuard] reads, and [DeleteFakeBorrows] deletes the | |
23 | //! initialization of those temporaries. | |
041b39d2 XL |
24 | |
25 | use rustc_data_structures::fx::FxHashSet; | |
26 | ||
0bf4aa26 | 27 | use rustc::mir::{BasicBlock, FakeReadCause, Local, Location, Mir, Place}; |
a1dfa0c6 XL |
28 | use rustc::mir::{Statement, StatementKind}; |
29 | use rustc::mir::visit::MutVisitor; | |
30 | use rustc::ty::TyCtxt; | |
abe05a73 | 31 | use transform::{MirPass, MirSource}; |
041b39d2 | 32 | |
b7449926 | 33 | pub struct CleanAscribeUserType; |
0531ce1d | 34 | |
b7449926 | 35 | pub struct DeleteAscribeUserType; |
0531ce1d | 36 | |
b7449926 | 37 | impl MirPass for CleanAscribeUserType { |
0531ce1d XL |
38 | fn run_pass<'a, 'tcx>(&self, |
39 | _tcx: TyCtxt<'a, 'tcx, 'tcx>, | |
40 | _source: MirSource, | |
41 | mir: &mut Mir<'tcx>) { | |
b7449926 | 42 | let mut delete = DeleteAscribeUserType; |
0531ce1d XL |
43 | delete.visit_mir(mir); |
44 | } | |
45 | } | |
46 | ||
b7449926 | 47 | impl<'tcx> MutVisitor<'tcx> for DeleteAscribeUserType { |
0531ce1d XL |
48 | fn visit_statement(&mut self, |
49 | block: BasicBlock, | |
50 | statement: &mut Statement<'tcx>, | |
51 | location: Location) { | |
b7449926 | 52 | if let StatementKind::AscribeUserType(..) = statement.kind { |
0531ce1d | 53 | statement.make_nop(); |
041b39d2 XL |
54 | } |
55 | self.super_statement(block, statement, location); | |
56 | } | |
57 | } | |
0bf4aa26 XL |
58 | |
59 | pub struct CleanFakeReadsAndBorrows; | |
60 | ||
61 | #[derive(Default)] | |
62 | pub struct DeleteAndRecordFakeReads { | |
63 | fake_borrow_temporaries: FxHashSet<Local>, | |
64 | } | |
65 | ||
66 | pub struct DeleteFakeBorrows { | |
67 | fake_borrow_temporaries: FxHashSet<Local>, | |
68 | } | |
69 | ||
70 | // Removes any FakeReads from the MIR | |
71 | impl MirPass for CleanFakeReadsAndBorrows { | |
72 | fn run_pass<'a, 'tcx>(&self, | |
73 | _tcx: TyCtxt<'a, 'tcx, 'tcx>, | |
74 | _source: MirSource, | |
75 | mir: &mut Mir<'tcx>) { | |
76 | let mut delete_reads = DeleteAndRecordFakeReads::default(); | |
77 | delete_reads.visit_mir(mir); | |
78 | let mut delete_borrows = DeleteFakeBorrows { | |
79 | fake_borrow_temporaries: delete_reads.fake_borrow_temporaries, | |
80 | }; | |
81 | delete_borrows.visit_mir(mir); | |
82 | } | |
83 | } | |
84 | ||
85 | impl<'tcx> MutVisitor<'tcx> for DeleteAndRecordFakeReads { | |
86 | fn visit_statement(&mut self, | |
87 | block: BasicBlock, | |
88 | statement: &mut Statement<'tcx>, | |
89 | location: Location) { | |
90 | if let StatementKind::FakeRead(cause, ref place) = statement.kind { | |
91 | if let FakeReadCause::ForMatchGuard = cause { | |
92 | match *place { | |
93 | Place::Local(local) => self.fake_borrow_temporaries.insert(local), | |
94 | _ => bug!("Fake match guard read of non-local: {:?}", place), | |
95 | }; | |
96 | } | |
97 | statement.make_nop(); | |
98 | } | |
99 | self.super_statement(block, statement, location); | |
100 | } | |
101 | } | |
102 | ||
103 | impl<'tcx> MutVisitor<'tcx> for DeleteFakeBorrows { | |
104 | fn visit_statement(&mut self, | |
105 | block: BasicBlock, | |
106 | statement: &mut Statement<'tcx>, | |
107 | location: Location) { | |
108 | if let StatementKind::Assign(Place::Local(local), _) = statement.kind { | |
109 | if self.fake_borrow_temporaries.contains(&local) { | |
110 | statement.make_nop(); | |
111 | } | |
112 | } | |
113 | self.super_statement(block, statement, location); | |
114 | } | |
115 | } |