]> git.lizzy.rs Git - rust.git/blob - src/librustc/infer/region_constraints/taint.rs
9f08fdcad7eea39a5308357a31d92493782dcf95
[rust.git] / src / librustc / infer / region_constraints / taint.rs
1 // Copyright 2012-2014 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 use super::*;
12
13 #[derive(Debug)]
14 pub(super) struct TaintSet<'tcx> {
15     directions: TaintDirections,
16     regions: FxHashSet<ty::Region<'tcx>>,
17 }
18
19 impl<'tcx> TaintSet<'tcx> {
20     pub(super) fn new(directions: TaintDirections, initial_region: ty::Region<'tcx>) -> Self {
21         let mut regions = FxHashSet::default();
22         regions.insert(initial_region);
23         TaintSet {
24             directions: directions,
25             regions: regions,
26         }
27     }
28
29     pub(super) fn fixed_point(
30         &mut self,
31         tcx: TyCtxt<'_, '_, 'tcx>,
32         undo_log: &[UndoLog<'tcx>],
33         verifys: &[Verify<'tcx>],
34     ) {
35         let mut prev_len = 0;
36         while prev_len < self.len() {
37             debug!(
38                 "tainted: prev_len = {:?} new_len = {:?}",
39                 prev_len,
40                 self.len()
41             );
42
43             prev_len = self.len();
44
45             for undo_entry in undo_log {
46                 match undo_entry {
47                     &AddConstraint(Constraint::VarSubVar(a, b)) => {
48                         self.add_edge(tcx.mk_region(ReVar(a)), tcx.mk_region(ReVar(b)));
49                     }
50                     &AddConstraint(Constraint::RegSubVar(a, b)) => {
51                         self.add_edge(a, tcx.mk_region(ReVar(b)));
52                     }
53                     &AddConstraint(Constraint::VarSubReg(a, b)) => {
54                         self.add_edge(tcx.mk_region(ReVar(a)), b);
55                     }
56                     &AddConstraint(Constraint::RegSubReg(a, b)) => {
57                         self.add_edge(a, b);
58                     }
59                     &AddGiven(a, b) => {
60                         self.add_edge(a, tcx.mk_region(ReVar(b)));
61                     }
62                     &AddVerify(i) => {
63                         span_bug!(
64                             verifys[i].origin.span(),
65                             "we never add verifications while doing higher-ranked things",
66                         )
67                     }
68                     &Purged | &AddCombination(..) | &AddVar(..) | &OpenSnapshot
69                     | &CommitedSnapshot => {}
70                 }
71             }
72         }
73     }
74
75     pub(super) fn into_set(self) -> FxHashSet<ty::Region<'tcx>> {
76         self.regions
77     }
78
79     fn len(&self) -> usize {
80         self.regions.len()
81     }
82
83     fn add_edge(&mut self, source: ty::Region<'tcx>, target: ty::Region<'tcx>) {
84         if self.directions.incoming {
85             if self.regions.contains(&target) {
86                 self.regions.insert(source);
87             }
88         }
89
90         if self.directions.outgoing {
91             if self.regions.contains(&source) {
92                 self.regions.insert(target);
93             }
94         }
95     }
96 }