8
8
// option. This file may not be copied, modified, or distributed
9
9
// except according to those terms.
10
10
11
- use borrow_check:: nll:: { NllLivenessMap , LocalWithRegion } ;
11
+ use borrow_check:: nll:: constraints :: ConstraintSet ;
12
12
use borrow_check:: nll:: type_check:: AtLocation ;
13
+ use borrow_check:: nll:: { LocalWithRegion , NllLivenessMap } ;
14
+ use borrow_check:: nll:: universal_regions:: UniversalRegions ;
13
15
use dataflow:: move_paths:: { HasMoveData , MoveData } ;
14
16
use dataflow:: MaybeInitializedPlaces ;
15
17
use dataflow:: { FlowAtLocation , FlowsAtLocation } ;
@@ -18,10 +20,10 @@ use rustc::mir::{BasicBlock, Location, Mir};
18
20
use rustc:: traits:: query:: dropck_outlives:: DropckOutlivesResult ;
19
21
use rustc:: traits:: query:: type_op:: outlives:: DropckOutlives ;
20
22
use rustc:: traits:: query:: type_op:: TypeOp ;
21
- use rustc:: ty:: { Ty , TypeFoldable } ;
22
- use rustc_data_structures:: fx:: FxHashMap ;
23
+ use rustc:: ty:: { RegionVid , Ty , TypeFoldable } ;
24
+ use rustc_data_structures:: fx:: { FxHashMap , FxHashSet } ;
23
25
use std:: rc:: Rc ;
24
- use util:: liveness:: { LivenessResults , LiveVariableMap } ;
26
+ use util:: liveness:: { LiveVariableMap , LivenessResults } ;
25
27
26
28
use super :: TypeChecker ;
27
29
@@ -41,9 +43,18 @@ pub(super) fn generate<'gcx, 'tcx>(
41
43
flow_inits : & mut FlowAtLocation < MaybeInitializedPlaces < ' _ , ' gcx , ' tcx > > ,
42
44
move_data : & MoveData < ' tcx > ,
43
45
) -> ( LivenessResults < LocalWithRegion > , NllLivenessMap ) {
44
- let liveness_map = NllLivenessMap :: compute ( & mir) ;
46
+ let free_regions = {
47
+ let borrowck_context = cx. borrowck_context . as_ref ( ) . unwrap ( ) ;
48
+ regions_that_outlive_free_regions (
49
+ cx. infcx . num_region_vars ( ) ,
50
+ & borrowck_context. universal_regions ,
51
+ & borrowck_context. constraints . outlives_constraints ,
52
+ )
53
+ } ;
54
+ let liveness_map = NllLivenessMap :: compute ( cx. tcx ( ) , & free_regions, mir) ;
45
55
let liveness = LivenessResults :: compute ( mir, & liveness_map) ;
46
56
57
+ // For everything else, it is only live where it is actually used.
47
58
{
48
59
let mut generator = TypeLivenessGenerator {
49
60
cx,
@@ -63,6 +74,45 @@ pub(super) fn generate<'gcx, 'tcx>(
63
74
( liveness, liveness_map)
64
75
}
65
76
77
+ /// Compute all regions that are (currently) known to outlive free
78
+ /// regions. For these regions, we do not need to compute
79
+ /// liveness, since the outlives constraints will ensure that they
80
+ /// are live over the whole fn body anyhow.
81
+ fn regions_that_outlive_free_regions (
82
+ num_region_vars : usize ,
83
+ universal_regions : & UniversalRegions < ' tcx > ,
84
+ constraint_set : & ConstraintSet ,
85
+ ) -> FxHashSet < RegionVid > {
86
+ // Build a graph of the outlives constraints thus far. This is
87
+ // a reverse graph, so for each constraint `R1: R2` we have an
88
+ // edge `R2 -> R1`. Therefore, if we find all regions
89
+ // reachable from each free region, we will have all the
90
+ // regions that are forced to outlive some free region.
91
+ let rev_constraint_graph = constraint_set. reverse_graph ( num_region_vars) ;
92
+ let rev_region_graph = rev_constraint_graph. region_graph ( constraint_set) ;
93
+
94
+ // Stack for the depth-first search. Start out with all the free regions.
95
+ let mut stack: Vec < _ > = universal_regions. universal_regions ( ) . collect ( ) ;
96
+
97
+ // Set of all free regions, plus anything that outlives them. Initially
98
+ // just contains the free regions.
99
+ let mut outlives_free_region: FxHashSet < _ > = stack. iter ( ) . cloned ( ) . collect ( ) ;
100
+
101
+ // Do the DFS -- for each thing in the stack, find all things
102
+ // that outlive it and add them to the set. If they are not,
103
+ // push them onto the stack for later.
104
+ while let Some ( sub_region) = stack. pop ( ) {
105
+ stack. extend (
106
+ rev_region_graph
107
+ . outgoing_regions ( sub_region)
108
+ . filter ( |& r| outlives_free_region. insert ( r) ) ,
109
+ ) ;
110
+ }
111
+
112
+ // Return the final set of things we visited.
113
+ outlives_free_region
114
+ }
115
+
66
116
struct TypeLivenessGenerator < ' gen , ' typeck , ' flow , ' gcx , ' tcx >
67
117
where
68
118
' typeck : ' gen ,
@@ -182,8 +232,13 @@ impl<'gen, 'typeck, 'flow, 'gcx, 'tcx> TypeLivenessGenerator<'gen, 'typeck, 'flo
182
232
183
233
cx. tcx ( ) . for_each_free_region ( & value, |live_region| {
184
234
if let Some ( ref mut borrowck_context) = cx. borrowck_context {
185
- let region_vid = borrowck_context. universal_regions . to_region_vid ( live_region) ;
186
- borrowck_context. constraints . liveness_constraints . add_element ( region_vid, location) ;
235
+ let region_vid = borrowck_context
236
+ . universal_regions
237
+ . to_region_vid ( live_region) ;
238
+ borrowck_context
239
+ . constraints
240
+ . liveness_constraints
241
+ . add_element ( region_vid, location) ;
187
242
188
243
if let Some ( all_facts) = borrowck_context. all_facts {
189
244
let start_index = borrowck_context. location_table . start_index ( location) ;
0 commit comments