@@ -48,10 +48,14 @@ pub(super) fn trace<'tcx>(
4848 move_data : & MoveData < ' tcx > ,
4949 relevant_live_locals : & [ Local ] ,
5050 boring_locals : & [ Local ] ,
51+ deferred : & [ Local ] ,
5152) -> ( DeferredLocals < ' tcx > , LocalUseMap ) {
5253 let _timer = typeck. tcx ( ) . prof . generic_activity ( "borrowck_liveness_trace" ) ;
5354
54- let local_use_map = LocalUseMap :: build ( & relevant_live_locals, location_map, typeck. body ) ;
55+ // The use map must also cover the deferred locals: their liveness is computed later, from
56+ // this same map, when the loan liveness traversal first reaches one of their regions.
57+ let use_map_locals: Vec < Local > = relevant_live_locals. iter ( ) . chain ( deferred) . copied ( ) . collect ( ) ;
58+ let local_use_map = LocalUseMap :: build ( & use_map_locals, location_map, typeck. body ) ;
5559 let calc = LivenessCalculation :: new (
5660 typeck. tcx ( ) ,
5761 typeck. body ,
@@ -61,13 +65,14 @@ pub(super) fn trace<'tcx>(
6165 ) ;
6266 let mut results = LivenessResults :: new ( typeck, calc) ;
6367
64- let deferred_locals = DeferredLocals :: default ( ) ;
68+ let deferred: FxIndexSet < Local > = deferred. iter ( ) . copied ( ) . collect ( ) ;
69+ let mut deferred_locals = DeferredLocals :: default ( ) ;
6570
66- results. add_extra_drop_facts ( relevant_live_locals) ;
71+ results. add_extra_drop_facts ( relevant_live_locals, & deferred ) ;
6772
6873 results. compute_for_all_locals ( relevant_live_locals) ;
6974
70- results. dropck_boring_locals ( boring_locals) ;
75+ results. dropck_boring_locals ( boring_locals, & deferred , & mut deferred_locals ) ;
7176
7277 ( deferred_locals, local_use_map)
7378}
@@ -174,19 +179,72 @@ impl<'a, 'typeck, 'tcx> LivenessResults<'a, 'typeck, 'tcx> {
174179 /// These are all the locals which do not potentially reference a region local
175180 /// to this body. Locals which only reference free regions are always drop-live
176181 /// and can therefore safely be dropped.
177- fn dropck_boring_locals ( & mut self , boring_locals : & [ Local ] ) {
182+ fn dropck_boring_locals (
183+ & mut self ,
184+ boring_locals : & [ Local ] ,
185+ deferred : & FxIndexSet < Local > ,
186+ deferred_locals : & mut DeferredLocals < ' tcx > ,
187+ ) {
178188 for & local in boring_locals {
179- let local_ty = self . calc . body . local_decls [ local] . ty ;
180- let local_span = self . calc . body . local_decls [ local] . source_info . span ;
181- dropck_local ( & self . typeck . infcx , & mut self . calc . drop_data , local_ty, local_span) ;
189+ self . dropck_boring_local ( local, deferred, deferred_locals) ;
182190 }
183191 }
184192
193+ fn dropck_boring_local (
194+ & mut self ,
195+ local : Local ,
196+ deferred : & FxIndexSet < Local > ,
197+ deferred_locals : & mut DeferredLocals < ' tcx > ,
198+ ) {
199+ let typeck = & mut * self . typeck ;
200+ let local_ty = self . calc . body . local_decls [ local] . ty ;
201+ let local_span = self . calc . body . local_decls [ local] . source_info . span ;
202+ let drop_data = dropck_local ( & typeck. infcx , & mut self . calc . drop_data , local_ty, local_span) ;
203+
204+ if !deferred. contains ( & local) {
205+ return ;
206+ }
207+
208+ if let Some ( data) = drop_data. region_constraint_data {
209+ let drop_locations =
210+ self . calc . local_use_map . drops ( local) . map ( |p| self . calc . location_map . to_location ( p) ) ;
211+ for drop_location in drop_locations {
212+ typeck. push_region_constraints (
213+ drop_location. to_locations ( ) ,
214+ ConstraintCategory :: Boring ,
215+ data,
216+ ) ;
217+ }
218+ }
219+
220+ for & kind in & drop_data. dropck_result . kinds {
221+ polonius:: legacy:: emit_drop_facts (
222+ typeck. tcx ( ) ,
223+ local,
224+ & kind,
225+ typeck. universal_regions ,
226+ typeck. polonius_facts ,
227+ ) ;
228+ }
229+
230+ deferred_locals. defer_local (
231+ typeck. infcx ,
232+ typeck. universal_regions ,
233+ local,
234+ local_ty,
235+ & drop_data. dropck_result . kinds ,
236+ ) ;
237+ }
238+
185239 /// Add extra drop facts needed for Polonius.
186240 ///
187241 /// Add facts for all locals with free regions, since regions may outlive
188242 /// the function body only at certain nodes in the CFG.
189- fn add_extra_drop_facts ( & mut self , relevant_live_locals : & [ Local ] ) {
243+ fn add_extra_drop_facts (
244+ & mut self ,
245+ relevant_live_locals : & [ Local ] ,
246+ deferred : & FxIndexSet < Local > ,
247+ ) {
190248 // This collect is more necessary than immediately apparent
191249 // because these facts go into `add_drop_live_facts_for()`,
192250 // which also writes to `polonius_facts`, and so this is genuinely
@@ -206,7 +264,10 @@ impl<'a, 'typeck, 'tcx> LivenessResults<'a, 'typeck, 'tcx> {
206264 . iter ( )
207265 . filter_map ( |& ( local, location_index) | {
208266 let local_ty = self . calc . body . local_decls [ local] . ty ;
209- if relevant_live_locals. contains ( & local) || !local_ty. has_free_regions ( ) {
267+ if relevant_live_locals. contains ( & local)
268+ || deferred. contains ( & local)
269+ || !local_ty. has_free_regions ( )
270+ {
210271 return None ;
211272 }
212273
0 commit comments