2
2
3
3
use crate :: build:: expr:: category:: Category ;
4
4
use crate :: build:: ForGuard :: { OutsideGuard , RefWithinGuard } ;
5
- use crate :: build:: { BlockAnd , BlockAndExtension , Builder } ;
5
+ use crate :: build:: { BlockAnd , BlockAndExtension , Builder , Capture , CaptureMap } ;
6
6
use rustc_hir:: def_id:: LocalDefId ;
7
7
use rustc_middle:: hir:: place:: Projection as HirProjection ;
8
8
use rustc_middle:: hir:: place:: ProjectionKind as HirProjectionKind ;
@@ -59,8 +59,6 @@ pub(crate) enum PlaceBase {
59
59
var_hir_id : LocalVarId ,
60
60
/// DefId of the closure
61
61
closure_def_id : LocalDefId ,
62
- /// The trait closure implements, `Fn`, `FnMut`, `FnOnce`
63
- closure_kind : ty:: ClosureKind ,
64
62
} ,
65
63
}
66
64
@@ -145,27 +143,6 @@ fn is_ancestor_or_same_capture(
145
143
iter:: zip ( proj_possible_ancestor, proj_capture) . all ( |( a, b) | a == b)
146
144
}
147
145
148
- /// Computes the index of a capture within the desugared closure provided the closure's
149
- /// `closure_min_captures` and the capture's index of the capture in the
150
- /// `ty::MinCaptureList` of the root variable `var_hir_id`.
151
- fn compute_capture_idx < ' tcx > (
152
- closure_min_captures : & ty:: RootVariableMinCaptureList < ' tcx > ,
153
- var_hir_id : LocalVarId ,
154
- root_var_idx : usize ,
155
- ) -> usize {
156
- let mut res = 0 ;
157
- for ( var_id, capture_list) in closure_min_captures {
158
- if * var_id == var_hir_id. 0 {
159
- res += root_var_idx;
160
- break ;
161
- } else {
162
- res += capture_list. len ( ) ;
163
- }
164
- }
165
-
166
- res
167
- }
168
-
169
146
/// Given a closure, returns the index of a capture within the desugared closure struct and the
170
147
/// `ty::CapturedPlace` which is the ancestor of the Place represented using the `var_hir_id`
171
148
/// and `projection`.
@@ -174,27 +151,17 @@ fn compute_capture_idx<'tcx>(
174
151
///
175
152
/// Returns None, when the ancestor is not found.
176
153
fn find_capture_matching_projections < ' a , ' tcx > (
177
- typeck_results : & ' a ty :: TypeckResults < ' tcx > ,
154
+ upvars : & ' a CaptureMap < ' tcx > ,
178
155
var_hir_id : LocalVarId ,
179
- closure_def_id : LocalDefId ,
180
156
projections : & [ PlaceElem < ' tcx > ] ,
181
- ) -> Option < ( usize , & ' a ty:: CapturedPlace < ' tcx > ) > {
182
- let closure_min_captures = typeck_results. closure_min_captures . get ( & closure_def_id) ?;
183
- let root_variable_min_captures = closure_min_captures. get ( & var_hir_id. 0 ) ?;
184
-
157
+ ) -> Option < ( usize , & ' a Capture < ' tcx > ) > {
185
158
let hir_projections = convert_to_hir_projections_and_truncate_for_capture ( projections) ;
186
159
187
- // If an ancestor is found, `idx` is the index within the list of captured places
188
- // for root variable `var_hir_id` and `capture` is the `ty::CapturedPlace` itself.
189
- let ( idx, capture) = root_variable_min_captures. iter ( ) . enumerate ( ) . find ( |( _, capture) | {
160
+ upvars. get_by_key_enumerated ( var_hir_id. 0 ) . find ( |( _, capture) | {
190
161
let possible_ancestor_proj_kinds: Vec < _ > =
191
- capture. place . projections . iter ( ) . map ( |proj| proj. kind ) . collect ( ) ;
162
+ capture. captured_place . place . projections . iter ( ) . map ( |proj| proj. kind ) . collect ( ) ;
192
163
is_ancestor_or_same_capture ( & possible_ancestor_proj_kinds, & hir_projections)
193
- } ) ?;
194
-
195
- // Convert index to be from the perspective of the entire closure_min_captures map
196
- // instead of just the root variable capture list
197
- Some ( ( compute_capture_idx ( closure_min_captures, var_hir_id, idx) , capture) )
164
+ } )
198
165
}
199
166
200
167
/// Takes a PlaceBuilder and resolves the upvar (if any) within it, so that the
@@ -204,24 +171,15 @@ fn find_capture_matching_projections<'a, 'tcx>(
204
171
fn to_upvars_resolved_place_builder < ' a , ' tcx > (
205
172
from_builder : PlaceBuilder < ' tcx > ,
206
173
tcx : TyCtxt < ' tcx > ,
207
- typeck_results : & ' a ty :: TypeckResults < ' tcx > ,
174
+ upvars : & ' a CaptureMap < ' tcx > ,
208
175
) -> Result < PlaceBuilder < ' tcx > , PlaceBuilder < ' tcx > > {
209
176
match from_builder. base {
210
177
PlaceBase :: Local ( _) => Ok ( from_builder) ,
211
- PlaceBase :: Upvar { var_hir_id, closure_def_id, closure_kind } => {
212
- let mut upvar_resolved_place_builder = PlaceBuilder :: from ( ty:: CAPTURE_STRUCT_LOCAL ) ;
213
- match closure_kind {
214
- ty:: ClosureKind :: Fn | ty:: ClosureKind :: FnMut => {
215
- upvar_resolved_place_builder = upvar_resolved_place_builder. deref ( ) ;
216
- }
217
- ty:: ClosureKind :: FnOnce => { }
218
- }
219
-
178
+ PlaceBase :: Upvar { var_hir_id, closure_def_id } => {
220
179
let Some ( ( capture_index, capture) ) =
221
180
find_capture_matching_projections (
222
- typeck_results ,
181
+ upvars ,
223
182
var_hir_id,
224
- closure_def_id,
225
183
& from_builder. projection ,
226
184
) else {
227
185
let closure_span = tcx. def_span ( closure_def_id) ;
@@ -241,39 +199,17 @@ fn to_upvars_resolved_place_builder<'a, 'tcx>(
241
199
return Err ( from_builder) ;
242
200
} ;
243
201
244
- // We won't be building MIR if the closure wasn't local
245
- let closure_hir_id = tcx. hir ( ) . local_def_id_to_hir_id ( closure_def_id) ;
246
- let closure_ty = typeck_results. node_type ( closure_hir_id) ;
247
-
248
- let substs = match closure_ty. kind ( ) {
249
- ty:: Closure ( _, substs) => ty:: UpvarSubsts :: Closure ( substs) ,
250
- ty:: Generator ( _, substs, _) => ty:: UpvarSubsts :: Generator ( substs) ,
251
- _ => bug ! ( "Lowering capture for non-closure type {:?}" , closure_ty) ,
252
- } ;
253
-
254
202
// Access the capture by accessing the field within the Closure struct.
255
- //
256
- // We must have inferred the capture types since we are building MIR, therefore
257
- // it's safe to call `tuple_element_ty` and we can unwrap here because
258
- // we know that the capture exists and is the `capture_index`-th capture.
259
- let var_ty = substs. tupled_upvars_ty ( ) . tuple_fields ( ) [ capture_index] ;
260
-
261
- upvar_resolved_place_builder =
262
- upvar_resolved_place_builder. field ( Field :: new ( capture_index) , var_ty) ;
263
-
264
- // If the variable is captured via ByRef(Immutable/Mutable) Borrow,
265
- // we need to deref it
266
- upvar_resolved_place_builder = match capture. info . capture_kind {
267
- ty:: UpvarCapture :: ByRef ( _) => upvar_resolved_place_builder. deref ( ) ,
268
- ty:: UpvarCapture :: ByValue => upvar_resolved_place_builder,
269
- } ;
203
+ let capture_info = & upvars[ capture_index] ;
204
+
205
+ let mut upvar_resolved_place_builder = PlaceBuilder :: from ( capture_info. use_place ) ;
270
206
271
207
// We used some of the projections to build the capture itself,
272
208
// now we apply the remaining to the upvar resolved place.
273
209
let remaining_projections = strip_prefix (
274
- capture. place . base_ty ,
210
+ capture. captured_place . place . base_ty ,
275
211
from_builder. projection ,
276
- & capture. place . projections ,
212
+ & capture. captured_place . place . projections ,
277
213
) ;
278
214
upvar_resolved_place_builder. projection . extend ( remaining_projections) ;
279
215
@@ -315,24 +251,24 @@ fn strip_prefix<'tcx>(
315
251
}
316
252
317
253
impl < ' tcx > PlaceBuilder < ' tcx > {
318
- pub ( crate ) fn into_place < ' a > (
254
+ pub ( in crate :: build ) fn into_place < ' a > (
319
255
self ,
320
256
tcx : TyCtxt < ' tcx > ,
321
- typeck_results : & ' a ty :: TypeckResults < ' tcx > ,
257
+ upvars : & ' a CaptureMap < ' tcx > ,
322
258
) -> Place < ' tcx > {
323
259
if let PlaceBase :: Local ( local) = self . base {
324
260
Place { local, projection : tcx. intern_place_elems ( & self . projection ) }
325
261
} else {
326
- self . expect_upvars_resolved ( tcx, typeck_results ) . into_place ( tcx, typeck_results )
262
+ self . expect_upvars_resolved ( tcx, upvars ) . into_place ( tcx, upvars )
327
263
}
328
264
}
329
265
330
266
fn expect_upvars_resolved < ' a > (
331
267
self ,
332
268
tcx : TyCtxt < ' tcx > ,
333
- typeck_results : & ' a ty :: TypeckResults < ' tcx > ,
269
+ upvars : & ' a CaptureMap < ' tcx > ,
334
270
) -> PlaceBuilder < ' tcx > {
335
- to_upvars_resolved_place_builder ( self , tcx, typeck_results ) . unwrap ( )
271
+ to_upvars_resolved_place_builder ( self , tcx, upvars ) . unwrap ( )
336
272
}
337
273
338
274
/// Attempts to resolve the `PlaceBuilder`.
@@ -346,12 +282,12 @@ impl<'tcx> PlaceBuilder<'tcx> {
346
282
/// not captured. This can happen because the final mir that will be
347
283
/// generated doesn't require a read for this place. Failures will only
348
284
/// happen inside closures.
349
- pub ( crate ) fn try_upvars_resolved < ' a > (
285
+ pub ( in crate :: build ) fn try_upvars_resolved < ' a > (
350
286
self ,
351
287
tcx : TyCtxt < ' tcx > ,
352
- typeck_results : & ' a ty :: TypeckResults < ' tcx > ,
288
+ upvars : & ' a CaptureMap < ' tcx > ,
353
289
) -> Result < PlaceBuilder < ' tcx > , PlaceBuilder < ' tcx > > {
354
- to_upvars_resolved_place_builder ( self , tcx, typeck_results )
290
+ to_upvars_resolved_place_builder ( self , tcx, upvars )
355
291
}
356
292
357
293
pub ( crate ) fn base ( & self ) -> PlaceBase {
@@ -392,6 +328,12 @@ impl<'tcx> From<PlaceBase> for PlaceBuilder<'tcx> {
392
328
}
393
329
}
394
330
331
+ impl < ' tcx > From < Place < ' tcx > > for PlaceBuilder < ' tcx > {
332
+ fn from ( p : Place < ' tcx > ) -> Self {
333
+ Self { base : PlaceBase :: Local ( p. local ) , projection : p. projection . to_vec ( ) }
334
+ }
335
+ }
336
+
395
337
impl < ' a , ' tcx > Builder < ' a , ' tcx > {
396
338
/// Compile `expr`, yielding a place that we can move from etc.
397
339
///
@@ -411,7 +353,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
411
353
expr : & Expr < ' tcx > ,
412
354
) -> BlockAnd < Place < ' tcx > > {
413
355
let place_builder = unpack ! ( block = self . as_place_builder( block, expr) ) ;
414
- block. and ( place_builder. into_place ( self . tcx , self . typeck_results ) )
356
+ block. and ( place_builder. into_place ( self . tcx , & self . upvars ) )
415
357
}
416
358
417
359
/// This is used when constructing a compound `Place`, so that we can avoid creating
@@ -435,7 +377,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
435
377
expr : & Expr < ' tcx > ,
436
378
) -> BlockAnd < Place < ' tcx > > {
437
379
let place_builder = unpack ! ( block = self . as_read_only_place_builder( block, expr) ) ;
438
- block. and ( place_builder. into_place ( self . tcx , self . typeck_results ) )
380
+ block. and ( place_builder. into_place ( self . tcx , & self . upvars ) )
439
381
}
440
382
441
383
/// This is used when constructing a compound `Place`, so that we can avoid creating
@@ -530,7 +472,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
530
472
inferred_ty : expr. ty ,
531
473
} ) ;
532
474
533
- let place = place_builder. clone ( ) . into_place ( this. tcx , this. typeck_results ) ;
475
+ let place = place_builder. clone ( ) . into_place ( this. tcx , & this. upvars ) ;
534
476
this. cfg . push (
535
477
block,
536
478
Statement {
@@ -629,17 +571,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
629
571
closure_def_id : LocalDefId ,
630
572
var_hir_id : LocalVarId ,
631
573
) -> BlockAnd < PlaceBuilder < ' tcx > > {
632
- let closure_ty =
633
- self . typeck_results . node_type ( self . tcx . hir ( ) . local_def_id_to_hir_id ( closure_def_id) ) ;
634
-
635
- let closure_kind = if let ty:: Closure ( _, closure_substs) = closure_ty. kind ( ) {
636
- self . infcx . closure_kind ( closure_substs) . unwrap ( )
637
- } else {
638
- // Generators are considered FnOnce.
639
- ty:: ClosureKind :: FnOnce
640
- } ;
641
-
642
- block. and ( PlaceBuilder :: from ( PlaceBase :: Upvar { var_hir_id, closure_def_id, closure_kind } ) )
574
+ block. and ( PlaceBuilder :: from ( PlaceBase :: Upvar { var_hir_id, closure_def_id } ) )
643
575
}
644
576
645
577
/// Lower an index expression
@@ -678,7 +610,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
678
610
if is_outermost_index {
679
611
self . read_fake_borrows ( block, fake_borrow_temps, source_info)
680
612
} else {
681
- base_place = base_place. expect_upvars_resolved ( self . tcx , self . typeck_results ) ;
613
+ base_place = base_place. expect_upvars_resolved ( self . tcx , & self . upvars ) ;
682
614
self . add_fake_borrows_of_base (
683
615
& base_place,
684
616
block,
@@ -710,7 +642,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
710
642
block,
711
643
source_info,
712
644
len,
713
- Rvalue :: Len ( slice. into_place ( self . tcx , self . typeck_results ) ) ,
645
+ Rvalue :: Len ( slice. into_place ( self . tcx , & self . upvars ) ) ,
714
646
) ;
715
647
// lt = idx < len
716
648
self . cfg . push_assign (
0 commit comments