@@ -284,30 +284,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
284
284
let var_hir_id = upvar_id. var_path . hir_id ;
285
285
closure_captures. insert ( var_hir_id, upvar_id) ;
286
286
287
- let mut new_capture_kind = capture_info. capture_kind ;
288
- if let Some ( existing_capture_kind) =
287
+ let new_capture_kind = if let Some ( capture_kind) =
289
288
self . typeck_results . borrow_mut ( ) . upvar_capture_map . get ( & upvar_id)
290
289
{
291
- // FIXME(@azhng): refactor this later
292
- new_capture_kind = match ( existing_capture_kind, new_capture_kind) {
293
- ( ty:: UpvarCapture :: ByValue ( Some ( _) ) , _) => * existing_capture_kind,
294
- ( _, ty:: UpvarCapture :: ByValue ( Some ( _) ) ) => new_capture_kind,
295
- ( ty:: UpvarCapture :: ByValue ( _) , _) | ( _, ty:: UpvarCapture :: ByValue ( _) ) => {
296
- ty:: UpvarCapture :: ByValue ( None )
297
- }
298
- ( ty:: UpvarCapture :: ByRef ( existing_ref) , ty:: UpvarCapture :: ByRef ( new_ref) ) => {
299
- match ( existing_ref. kind , new_ref. kind ) {
300
- // Take RHS:
301
- ( ty:: ImmBorrow , ty:: UniqueImmBorrow | ty:: MutBorrow )
302
- | ( ty:: UniqueImmBorrow , ty:: MutBorrow ) => new_capture_kind,
303
- // Take LHS:
304
- ( ty:: ImmBorrow , ty:: ImmBorrow )
305
- | ( ty:: UniqueImmBorrow , ty:: ImmBorrow | ty:: UniqueImmBorrow )
306
- | ( ty:: MutBorrow , _) => * existing_capture_kind,
307
- }
308
- }
309
- } ;
310
- }
290
+ // upvar_capture_map only stores the UpvarCapture (CaptureKind),
291
+ // so we create a fake capture info with no expression.
292
+ let fake_capture_info =
293
+ ty:: CaptureInfo { expr_id : None , capture_kind : capture_kind. clone ( ) } ;
294
+ self . determine_capture_info ( fake_capture_info, capture_info. clone ( ) ) . capture_kind
295
+ } else {
296
+ capture_info. capture_kind
297
+ } ;
311
298
self . typeck_results . borrow_mut ( ) . upvar_capture_map . insert ( upvar_id, new_capture_kind) ;
312
299
}
313
300
@@ -353,6 +340,60 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
353
340
fn should_log_capture_analysis ( & self , closure_def_id : DefId ) -> bool {
354
341
self . tcx . has_attr ( closure_def_id, sym:: rustc_capture_analysis)
355
342
}
343
+
344
+ /// Helper function to determine if we need to escalate CaptureKind from
345
+ /// CaptureInfo A to B and returns the escalated CaptureInfo.
346
+ /// (Note: CaptureInfo contains CaptureKind and an expression that led to capture it in that way)
347
+ ///
348
+ /// If both `CaptureKind`s are considered equivalent, then the CaptureInfo is selected based
349
+ /// on the `CaptureInfo` containing an associated expression id.
350
+ ///
351
+ /// If both the CaptureKind and Expression are considered to be equivalent,
352
+ /// then `CaptureInfo` A is preferred.
353
+ fn determine_capture_info (
354
+ & self ,
355
+ capture_info_a : ty:: CaptureInfo < ' tcx > ,
356
+ capture_info_b : ty:: CaptureInfo < ' tcx > ,
357
+ ) -> ty:: CaptureInfo < ' tcx > {
358
+ // If the capture kind is equivalent then, we don't need to escalate and can compare the
359
+ // expressions.
360
+ let eq_capture_kind = match ( capture_info_a. capture_kind , capture_info_b. capture_kind ) {
361
+ ( ty:: UpvarCapture :: ByValue ( _) , ty:: UpvarCapture :: ByValue ( _) ) => true ,
362
+ ( ty:: UpvarCapture :: ByRef ( ref_a) , ty:: UpvarCapture :: ByRef ( ref_b) ) => {
363
+ ref_a. kind == ref_b. kind
364
+ }
365
+ _ => false ,
366
+ } ;
367
+
368
+ if eq_capture_kind {
369
+ match ( capture_info_a. expr_id , capture_info_b. expr_id ) {
370
+ ( Some ( _) , _) | ( None , None ) => capture_info_a,
371
+ ( None , Some ( _) ) => capture_info_b,
372
+ }
373
+ } else {
374
+ match ( capture_info_a. capture_kind , capture_info_b. capture_kind ) {
375
+ ( ty:: UpvarCapture :: ByValue ( _) , _) => capture_info_a,
376
+ ( _, ty:: UpvarCapture :: ByValue ( _) ) => capture_info_b,
377
+ ( ty:: UpvarCapture :: ByRef ( ref_a) , ty:: UpvarCapture :: ByRef ( ref_b) ) => {
378
+ match ( ref_a. kind , ref_b. kind ) {
379
+ // Take LHS:
380
+ ( ty:: UniqueImmBorrow | ty:: MutBorrow , ty:: ImmBorrow )
381
+ | ( ty:: MutBorrow , ty:: UniqueImmBorrow ) => capture_info_a,
382
+
383
+ // Take RHS:
384
+ ( ty:: ImmBorrow , ty:: UniqueImmBorrow | ty:: MutBorrow )
385
+ | ( ty:: UniqueImmBorrow , ty:: MutBorrow ) => capture_info_b,
386
+
387
+ ( ty:: ImmBorrow , ty:: ImmBorrow )
388
+ | ( ty:: UniqueImmBorrow , ty:: UniqueImmBorrow )
389
+ | ( ty:: MutBorrow , ty:: MutBorrow ) => {
390
+ bug ! ( "Expected unequal capture kinds" ) ;
391
+ }
392
+ }
393
+ }
394
+ }
395
+ }
396
+ }
356
397
}
357
398
358
399
struct InferBorrowKind < ' a , ' tcx > {
@@ -426,16 +467,10 @@ impl<'a, 'tcx> InferBorrowKind<'a, 'tcx> {
426
467
capture_kind : ty:: UpvarCapture :: ByValue ( Some ( usage_span) ) ,
427
468
} ;
428
469
429
- let curr_info = self . capture_information . get ( & place_with_id. place ) ;
430
- let updated_info = match curr_info {
431
- Some ( info) => match info. capture_kind {
432
- ty:: UpvarCapture :: ByRef ( _) | ty:: UpvarCapture :: ByValue ( None ) => capture_info,
433
- _ => * info,
434
- } ,
435
- None => capture_info,
436
- } ;
470
+ let curr_info = self . capture_information [ & place_with_id. place ] ;
471
+ let updated_info = self . fcx . determine_capture_info ( curr_info, capture_info) ;
437
472
438
- self . capture_information . insert ( place_with_id. place . clone ( ) , updated_info) ;
473
+ self . capture_information [ & place_with_id. place ] = updated_info;
439
474
}
440
475
441
476
/// Indicates that `place_with_id` is being directly mutated (e.g., assigned
@@ -532,42 +567,28 @@ impl<'a, 'tcx> InferBorrowKind<'a, 'tcx> {
532
567
diag_expr_id : hir:: HirId ,
533
568
kind : ty:: BorrowKind ,
534
569
) {
535
- let capture_info = self
536
- . capture_information
537
- . get ( & place_with_id. place )
538
- . unwrap_or_else ( || bug ! ( "Upar capture info missing" ) ) ;
539
- // We init capture_information for each element
570
+ let curr_capture_info = self . capture_information [ & place_with_id. place ] ;
540
571
541
572
debug ! (
542
- "adjust_upvar_borrow_kind(place={:?}, , diag_expr_id={:?}, capture_info={:?}, kind={:?})" ,
543
- place_with_id, diag_expr_id, capture_info , kind
573
+ "adjust_upvar_borrow_kind(place={:?}, diag_expr_id={:?}, capture_info={:?}, kind={:?})" ,
574
+ place_with_id, diag_expr_id, curr_capture_info , kind
544
575
) ;
545
576
546
- match capture_info. capture_kind {
547
- ty:: UpvarCapture :: ByValue ( _) => {
548
- // Upvar is already by-value, the strongest criteria.
549
- }
550
- ty:: UpvarCapture :: ByRef ( upvar_borrow) => {
551
- match ( upvar_borrow. kind , kind) {
552
- // Take RHS:
553
- ( ty:: ImmBorrow , ty:: UniqueImmBorrow | ty:: MutBorrow )
554
- | ( ty:: UniqueImmBorrow , ty:: MutBorrow ) => {
555
- if let Some ( ty:: CaptureInfo { expr_id, capture_kind } ) =
556
- self . capture_information . get_mut ( & place_with_id. place )
557
- {
558
- * expr_id = Some ( diag_expr_id) ;
559
- if let ty:: UpvarCapture :: ByRef ( borrow_kind) = capture_kind {
560
- borrow_kind. kind = kind;
561
- }
562
- }
563
- }
564
- // Take LHS:
565
- ( ty:: ImmBorrow , ty:: ImmBorrow )
566
- | ( ty:: UniqueImmBorrow , ty:: ImmBorrow | ty:: UniqueImmBorrow )
567
- | ( ty:: MutBorrow , _) => { }
568
- }
569
- }
570
- }
577
+ if let ty:: UpvarCapture :: ByValue ( _) = curr_capture_info. capture_kind {
578
+ // It's already captured by value, we don't need to do anything here
579
+ return ;
580
+ } else if let ty:: UpvarCapture :: ByRef ( curr_upvar_borrow) = curr_capture_info. capture_kind {
581
+ // Use the same region as the current capture information
582
+ // Doesn't matter since only one of the UpvarBorrow will be used.
583
+ let new_upvar_borrow = ty:: UpvarBorrow { kind, region : curr_upvar_borrow. region } ;
584
+
585
+ let capture_info = ty:: CaptureInfo {
586
+ expr_id : Some ( diag_expr_id) ,
587
+ capture_kind : ty:: UpvarCapture :: ByRef ( new_upvar_borrow) ,
588
+ } ;
589
+ let updated_info = self . fcx . determine_capture_info ( curr_capture_info, capture_info) ;
590
+ self . capture_information [ & place_with_id. place ] = updated_info;
591
+ } ;
571
592
}
572
593
573
594
fn adjust_closure_kind (
@@ -622,7 +643,6 @@ impl<'a, 'tcx> InferBorrowKind<'a, 'tcx> {
622
643
623
644
debug ! ( "Capturing new place {:?}" , place_with_id) ;
624
645
625
- let tcx = self . fcx . tcx ;
626
646
let capture_kind =
627
647
self . fcx . init_capture_kind ( self . capture_clause , upvar_id, self . closure_span ) ;
628
648
0 commit comments