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.
14 use rustc::mir::visit::Visitor;
15 use dataflow::BitDenotation;
17 /// This calculates if any part of a MIR local could have previously been borrowed.
18 /// This means that once a local has been borrowed, its bit will always be set
19 /// from that point and onwards, even if the borrow ends. You could also think of this
20 /// as computing the lifetimes of infinite borrows.
21 /// This is used to compute which locals are live during a yield expression for
22 /// immovable generators.
23 #[derive(Copy, Clone)]
24 pub struct HaveBeenBorrowedLocals<'a, 'tcx: 'a> {
28 impl<'a, 'tcx: 'a> HaveBeenBorrowedLocals<'a, 'tcx> {
29 pub fn new(mir: &'a Mir<'tcx>)
31 HaveBeenBorrowedLocals { mir: mir }
34 pub fn mir(&self) -> &Mir<'tcx> {
39 impl<'a, 'tcx> BitDenotation for HaveBeenBorrowedLocals<'a, 'tcx> {
41 fn name() -> &'static str { "has_been_borrowed_locals" }
42 fn bits_per_block(&self) -> usize {
43 self.mir.local_decls.len()
46 fn start_block_effect(&self, _sets: &mut IdxSet<Local>) {
47 // Nothing is borrowed on function entry
50 fn statement_effect(&self,
51 sets: &mut BlockSets<Local>,
53 BorrowedLocalsVisitor {
55 }.visit_statement(loc.block, &self.mir[loc.block].statements[loc.statement_index], loc);
58 fn terminator_effect(&self,
59 sets: &mut BlockSets<Local>,
61 BorrowedLocalsVisitor {
63 }.visit_terminator(loc.block, self.mir[loc.block].terminator(), loc);
66 fn propagate_call_return(&self,
67 _in_out: &mut IdxSet<Local>,
68 _call_bb: mir::BasicBlock,
69 _dest_bb: mir::BasicBlock,
70 _dest_place: &mir::Place) {
71 // Nothing to do when a call returns successfully
75 impl<'a, 'tcx> BitwiseOperator for HaveBeenBorrowedLocals<'a, 'tcx> {
77 fn join(&self, pred1: Word, pred2: Word) -> Word {
78 pred1 | pred2 // "maybe" means we union effects of both preds
82 impl<'a, 'tcx> InitialFlow for HaveBeenBorrowedLocals<'a, 'tcx> {
84 fn bottom_value() -> bool {
85 false // bottom = unborrowed
89 struct BorrowedLocalsVisitor<'b, 'c: 'b> {
90 sets: &'b mut BlockSets<'c, Local>,
93 fn find_local<'tcx>(place: &Place<'tcx>) -> Option<Local> {
95 Place::Local(l) => Some(l),
97 Place::Static(..) => None,
98 Place::Projection(ref proj) => {
100 ProjectionElem::Deref => None,
101 _ => find_local(&proj.base)
107 impl<'tcx, 'b, 'c> Visitor<'tcx> for BorrowedLocalsVisitor<'b, 'c> {
108 fn visit_rvalue(&mut self,
109 rvalue: &Rvalue<'tcx>,
110 location: Location) {
111 if let Rvalue::Ref(_, _, ref place) = *rvalue {
112 if let Some(local) = find_local(place) {
113 self.sets.gen(&local);
117 self.super_rvalue(rvalue, location)