]> git.lizzy.rs Git - rust.git/blob - src/librustc_mir/dataflow/impls/borrowed_locals.rs
Rollup merge of #59432 - phansch:compiletest_docs, r=alexcrichton
[rust.git] / src / librustc_mir / dataflow / impls / borrowed_locals.rs
1 pub use super::*;
2
3 use rustc::mir::*;
4 use rustc::mir::visit::Visitor;
5 use crate::dataflow::BitDenotation;
6
7 /// This calculates if any part of a MIR local could have previously been borrowed.
8 /// This means that once a local has been borrowed, its bit will be set
9 /// from that point and onwards, until we see a StorageDead statement for the local,
10 /// at which points there is no memory associated with the local, so it cannot be borrowed.
11 /// This is used to compute which locals are live during a yield expression for
12 /// immovable generators.
13 #[derive(Copy, Clone)]
14 pub struct HaveBeenBorrowedLocals<'a, 'tcx: 'a> {
15     mir: &'a Mir<'tcx>,
16 }
17
18 impl<'a, 'tcx: 'a> HaveBeenBorrowedLocals<'a, 'tcx> {
19     pub fn new(mir: &'a Mir<'tcx>)
20                -> Self {
21         HaveBeenBorrowedLocals { mir }
22     }
23
24     pub fn mir(&self) -> &Mir<'tcx> {
25         self.mir
26     }
27 }
28
29 impl<'a, 'tcx> BitDenotation<'tcx> for HaveBeenBorrowedLocals<'a, 'tcx> {
30     type Idx = Local;
31     fn name() -> &'static str { "has_been_borrowed_locals" }
32     fn bits_per_block(&self) -> usize {
33         self.mir.local_decls.len()
34     }
35
36     fn start_block_effect(&self, _sets: &mut BitSet<Local>) {
37         // Nothing is borrowed on function entry
38     }
39
40     fn statement_effect(&self,
41                         sets: &mut BlockSets<'_, Local>,
42                         loc: Location) {
43         let stmt = &self.mir[loc.block].statements[loc.statement_index];
44
45         BorrowedLocalsVisitor {
46             sets,
47         }.visit_statement(loc.block, stmt, loc);
48
49         // StorageDead invalidates all borrows and raw pointers to a local
50         match stmt.kind {
51             StatementKind::StorageDead(l) => sets.kill(l),
52             _ => (),
53         }
54     }
55
56     fn terminator_effect(&self,
57                          sets: &mut BlockSets<'_, Local>,
58                          loc: Location) {
59         BorrowedLocalsVisitor {
60             sets,
61         }.visit_terminator(loc.block, self.mir[loc.block].terminator(), loc);
62     }
63
64     fn propagate_call_return(
65         &self,
66         _in_out: &mut BitSet<Local>,
67         _call_bb: mir::BasicBlock,
68         _dest_bb: mir::BasicBlock,
69         _dest_place: &mir::Place<'tcx>,
70     ) {
71         // Nothing to do when a call returns successfully
72     }
73 }
74
75 impl<'a, 'tcx> BitSetOperator for HaveBeenBorrowedLocals<'a, 'tcx> {
76     #[inline]
77     fn join<T: Idx>(&self, inout_set: &mut BitSet<T>, in_set: &BitSet<T>) -> bool {
78         inout_set.union(in_set) // "maybe" means we union effects of both preds
79     }
80 }
81
82 impl<'a, 'tcx> InitialFlow for HaveBeenBorrowedLocals<'a, 'tcx> {
83     #[inline]
84     fn bottom_value() -> bool {
85         false // bottom = unborrowed
86     }
87 }
88
89 struct BorrowedLocalsVisitor<'b, 'c: 'b> {
90     sets: &'b mut BlockSets<'c, Local>,
91 }
92
93 fn find_local<'tcx>(place: &Place<'tcx>) -> Option<Local> {
94     match *place {
95         Place::Base(PlaceBase::Local(l)) => Some(l),
96         Place::Base(PlaceBase::Static(..)) => None,
97         Place::Projection(ref proj) => {
98             match proj.elem {
99                 ProjectionElem::Deref => None,
100                 _ => find_local(&proj.base)
101             }
102         }
103     }
104 }
105
106 impl<'tcx, 'b, 'c> Visitor<'tcx> for BorrowedLocalsVisitor<'b, 'c> {
107     fn visit_rvalue(&mut self,
108                     rvalue: &Rvalue<'tcx>,
109                     location: Location) {
110         if let Rvalue::Ref(_, _, ref place) = *rvalue {
111             if let Some(local) = find_local(place) {
112                 self.sets.gen(local);
113             }
114         }
115
116         self.super_rvalue(rvalue, location)
117     }
118 }