88// option. This file may not be copied, modified, or distributed
99// except according to those terms.
1010
11- use borrow_check:: nll:: { NllLivenessMap , LocalWithRegion } ;
11+ use borrow_check:: nll:: constraints :: ConstraintSet ;
1212use borrow_check:: nll:: type_check:: AtLocation ;
13+ use borrow_check:: nll:: { LocalWithRegion , NllLivenessMap } ;
14+ use borrow_check:: nll:: universal_regions:: UniversalRegions ;
1315use dataflow:: move_paths:: { HasMoveData , MoveData } ;
1416use dataflow:: MaybeInitializedPlaces ;
1517use dataflow:: { FlowAtLocation , FlowsAtLocation } ;
@@ -18,10 +20,10 @@ use rustc::mir::{BasicBlock, Location, Mir};
1820use rustc:: traits:: query:: dropck_outlives:: DropckOutlivesResult ;
1921use rustc:: traits:: query:: type_op:: outlives:: DropckOutlives ;
2022use 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 } ;
2325use std:: rc:: Rc ;
24- use util:: liveness:: { LivenessResults , LiveVariableMap } ;
26+ use util:: liveness:: { LiveVariableMap , LivenessResults } ;
2527
2628use super :: TypeChecker ;
2729
@@ -41,9 +43,18 @@ pub(super) fn generate<'gcx, 'tcx>(
4143 flow_inits : & mut FlowAtLocation < MaybeInitializedPlaces < ' _ , ' gcx , ' tcx > > ,
4244 move_data : & MoveData < ' tcx > ,
4345) -> ( 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) ;
4555 let liveness = LivenessResults :: compute ( mir, & liveness_map) ;
4656
57+ // For everything else, it is only live where it is actually used.
4758 {
4859 let mut generator = TypeLivenessGenerator {
4960 cx,
@@ -63,6 +74,45 @@ pub(super) fn generate<'gcx, 'tcx>(
6374 ( liveness, liveness_map)
6475}
6576
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+
66116struct TypeLivenessGenerator < ' gen , ' typeck , ' flow , ' gcx , ' tcx >
67117where
68118 ' typeck : ' gen ,
@@ -182,8 +232,13 @@ impl<'gen, 'typeck, 'flow, 'gcx, 'tcx> TypeLivenessGenerator<'gen, 'typeck, 'flo
182232
183233 cx. tcx ( ) . for_each_free_region ( & value, |live_region| {
184234 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) ;
187242
188243 if let Some ( all_facts) = borrowck_context. all_facts {
189244 let start_index = borrowck_context. location_table . start_index ( location) ;
0 commit comments