@@ -42,44 +42,70 @@ impl MirPass for NLL {
42
42
return ;
43
43
}
44
44
45
- tcx. infer_ctxt ( ) . enter ( |ref infcx| {
46
- // Clone mir so we can mutate it without disturbing the rest of the compiler
47
- let mir = & mut input_mir. clone ( ) ;
48
-
49
- // Replace all regions with fresh inference variables.
50
- let num_region_variables = renumber:: renumber_mir ( infcx, mir) ;
51
-
52
- // Compute what is live where.
53
- let liveness = & LivenessResults {
54
- regular : liveness:: liveness_of_locals (
55
- mir,
56
- LivenessMode {
57
- include_regular_use : true ,
58
- include_drops : false ,
59
- } ,
60
- ) ,
61
-
62
- drop : liveness:: liveness_of_locals (
63
- mir,
64
- LivenessMode {
65
- include_regular_use : false ,
66
- include_drops : true ,
67
- } ,
68
- ) ,
69
- } ;
70
-
71
- // Create the region inference context, generate the constraints,
72
- // and then solve them.
73
- let regioncx = & mut RegionInferenceContext :: new ( num_region_variables) ;
74
- constraint_generation:: generate_constraints ( infcx, regioncx, mir, source, liveness) ;
75
- regioncx. solve ( infcx, mir) ;
76
-
77
- // Dump MIR results into a file, if that is enabled.
78
- dump_mir_results ( infcx, liveness, source, regioncx, mir) ;
79
- } )
45
+ tcx. infer_ctxt ( )
46
+ . enter ( |ref infcx| drop ( compute_regions ( infcx, source, input_mir) ) ) ;
80
47
}
81
48
}
82
49
50
+ pub struct RegionComputation < ' tcx > {
51
+ /// A rewritten version of the input MIR where all the regions are
52
+ /// rewritten to refer to inference variables.
53
+ pub mir : Mir < ' tcx > ,
54
+
55
+ /// The definitions (along with their final values) for all regions.
56
+ pub regioncx : RegionInferenceContext ,
57
+ }
58
+
59
+ /// Computes the (non-lexical) regions from the input MIR.
60
+ ///
61
+ /// This may result in errors being reported.
62
+ pub fn compute_regions < ' a , ' gcx , ' tcx > (
63
+ infcx : & InferCtxt < ' a , ' gcx , ' tcx > ,
64
+ source : MirSource ,
65
+ input_mir : & Mir < ' tcx > ,
66
+ ) -> RegionComputation < ' tcx > {
67
+ // Clone mir so we can mutate it without disturbing the rest of the compiler
68
+ let mut mir = input_mir. clone ( ) ;
69
+
70
+ // Replace all regions with fresh inference variables.
71
+ let num_region_variables = renumber:: renumber_mir ( infcx, & mut mir) ;
72
+
73
+ // Compute what is live where.
74
+ let liveness = & LivenessResults {
75
+ regular : liveness:: liveness_of_locals (
76
+ & mir,
77
+ LivenessMode {
78
+ include_regular_use : true ,
79
+ include_drops : false ,
80
+ } ,
81
+ ) ,
82
+
83
+ drop : liveness:: liveness_of_locals (
84
+ & mir,
85
+ LivenessMode {
86
+ include_regular_use : false ,
87
+ include_drops : true ,
88
+ } ,
89
+ ) ,
90
+ } ;
91
+
92
+ // Create the region inference context, generate the constraints,
93
+ // and then solve them.
94
+ let mut regioncx = RegionInferenceContext :: new ( num_region_variables) ;
95
+ constraint_generation:: generate_constraints ( infcx, & mut regioncx, & mir, source, liveness) ;
96
+ let errors = regioncx. solve ( infcx, & mir) ;
97
+
98
+ assert ! ( errors. is_empty( ) , "FIXME: report region inference failures" ) ;
99
+
100
+ let computation = RegionComputation { mir, regioncx } ;
101
+
102
+ // Dump MIR results into a file, if that is enabled. This let us
103
+ // write unit-tests.
104
+ dump_mir_results ( infcx, liveness, source, & computation) ;
105
+
106
+ computation
107
+ }
108
+
83
109
struct LivenessResults {
84
110
regular : LivenessResult ,
85
111
drop : LivenessResult ,
@@ -89,13 +115,17 @@ fn dump_mir_results<'a, 'gcx, 'tcx>(
89
115
infcx : & InferCtxt < ' a , ' gcx , ' tcx > ,
90
116
liveness : & LivenessResults ,
91
117
source : MirSource ,
92
- regioncx : & RegionInferenceContext ,
93
- mir : & Mir < ' tcx > ,
118
+ computation : & RegionComputation < ' tcx > ,
94
119
) {
95
120
if !mir_util:: dump_enabled ( infcx. tcx , "nll" , source) {
96
121
return ;
97
122
}
98
123
124
+ let RegionComputation {
125
+ ref mir,
126
+ ref regioncx,
127
+ } = * computation;
128
+
99
129
let regular_liveness_per_location: FxHashMap < _ , _ > = mir. basic_blocks ( )
100
130
. indices ( )
101
131
. flat_map ( |bb| {
@@ -126,7 +156,12 @@ fn dump_mir_results<'a, 'gcx, 'tcx>(
126
156
match pass_where {
127
157
// Before the CFG, dump out the values for each region variable.
128
158
PassWhere :: BeforeCFG => for region in regioncx. regions ( ) {
129
- writeln ! ( out, "| {:?}: {:?}" , region, regioncx. region_value( region) ) ?;
159
+ writeln ! (
160
+ out,
161
+ "| {:?}: {:?}" ,
162
+ region,
163
+ regioncx. region_value( region)
164
+ ) ?;
130
165
} ,
131
166
132
167
// Before each basic block, dump out the values
@@ -141,12 +176,7 @@ fn dump_mir_results<'a, 'gcx, 'tcx>(
141
176
& regular_liveness_per_location[ & location] ,
142
177
& drop_liveness_per_location[ & location] ,
143
178
) ;
144
- writeln ! (
145
- out,
146
- " | Live variables at {:?}: {}" ,
147
- location,
148
- s
149
- ) ?;
179
+ writeln ! ( out, " | Live variables at {:?}: {}" , location, s) ?;
150
180
}
151
181
152
182
PassWhere :: AfterCFG => { }
@@ -217,7 +247,11 @@ fn live_variable_set(regular: &LocalSet, drops: &LocalSet) -> String {
217
247
string. push_str ( ", " ) ;
218
248
}
219
249
220
- let len = if string. is_empty ( ) { 0 } else { string. len ( ) - 2 } ;
250
+ let len = if string. is_empty ( ) {
251
+ 0
252
+ } else {
253
+ string. len ( ) - 2
254
+ } ;
221
255
222
256
format ! ( "[{}]" , & string[ ..len] )
223
257
}
0 commit comments