33
33
use super :: FnCtxt ;
34
34
35
35
use crate :: expr_use_visitor as euv;
36
- use rustc_data_structures:: fx:: FxIndexMap ;
37
36
use rustc_errors:: Applicability ;
38
37
use rustc_hir as hir;
39
38
use rustc_hir:: def_id:: DefId ;
@@ -72,7 +71,7 @@ enum PlaceAncestryRelation {
72
71
/// Intermediate format to store a captured `Place` and associated `ty::CaptureInfo`
73
72
/// during capture analysis. Information in this map feeds into the minimum capture
74
73
/// analysis pass.
75
- type InferredCaptureInformation < ' tcx > = FxIndexMap < Place < ' tcx > , ty:: CaptureInfo > ;
74
+ type InferredCaptureInformation < ' tcx > = Vec < ( Place < ' tcx > , ty:: CaptureInfo ) > ;
76
75
77
76
impl < ' a , ' tcx > FnCtxt < ' a , ' tcx > {
78
77
pub fn closure_analyze ( & self , body : & ' tcx hir:: Body < ' tcx > ) {
@@ -258,7 +257,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
258
257
capture_kind,
259
258
} ;
260
259
261
- capture_information. insert ( place, fake_info) ;
260
+ capture_information. push ( ( place, fake_info) ) ;
262
261
}
263
262
}
264
263
@@ -384,76 +383,68 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
384
383
capture_clause : hir:: CaptureBy ,
385
384
capture_information : InferredCaptureInformation < ' tcx > ,
386
385
) -> ( InferredCaptureInformation < ' tcx > , ty:: ClosureKind , Option < ( Span , Place < ' tcx > ) > ) {
387
- let mut processed: InferredCaptureInformation < ' tcx > = Default :: default ( ) ;
388
-
389
386
let mut closure_kind = ty:: ClosureKind :: LATTICE_BOTTOM ;
390
387
let mut origin: Option < ( Span , Place < ' tcx > ) > = None ;
391
388
392
- for ( place, mut capture_info) in capture_information {
393
- // Apply rules for safety before inferring closure kind
394
- let ( place, capture_kind) =
395
- restrict_capture_precision ( place, capture_info. capture_kind ) ;
396
- capture_info. capture_kind = capture_kind;
389
+ let processed = capture_information
390
+ . into_iter ( )
391
+ . map ( |( place, mut capture_info) | {
392
+ // Apply rules for safety before inferring closure kind
393
+ let ( place, capture_kind) =
394
+ restrict_capture_precision ( place, capture_info. capture_kind ) ;
397
395
398
- let ( place, capture_kind) =
399
- truncate_capture_for_optimization ( place, capture_info. capture_kind ) ;
400
- capture_info. capture_kind = capture_kind;
396
+ let ( place, capture_kind) = truncate_capture_for_optimization ( place, capture_kind) ;
401
397
402
- let usage_span = if let Some ( usage_expr) = capture_info. path_expr_id {
403
- self . tcx . hir ( ) . span ( usage_expr)
404
- } else {
405
- unreachable ! ( )
406
- } ;
398
+ let usage_span = if let Some ( usage_expr) = capture_info. path_expr_id {
399
+ self . tcx . hir ( ) . span ( usage_expr)
400
+ } else {
401
+ unreachable ! ( )
402
+ } ;
407
403
408
- let updated = match capture_info . capture_kind {
409
- ty:: UpvarCapture :: ByValue => match closure_kind {
410
- ty:: ClosureKind :: Fn | ty:: ClosureKind :: FnMut => {
411
- ( ty:: ClosureKind :: FnOnce , Some ( ( usage_span, place. clone ( ) ) ) )
412
- }
413
- // If closure is already FnOnce, don't update
414
- ty:: ClosureKind :: FnOnce => ( closure_kind, origin) ,
415
- } ,
404
+ let updated = match capture_kind {
405
+ ty:: UpvarCapture :: ByValue => match closure_kind {
406
+ ty:: ClosureKind :: Fn | ty:: ClosureKind :: FnMut => {
407
+ ( ty:: ClosureKind :: FnOnce , Some ( ( usage_span, place. clone ( ) ) ) )
408
+ }
409
+ // If closure is already FnOnce, don't update
410
+ ty:: ClosureKind :: FnOnce => ( closure_kind, origin. take ( ) ) ,
411
+ } ,
416
412
417
- ty:: UpvarCapture :: ByRef (
418
- ty:: BorrowKind :: MutBorrow | ty:: BorrowKind :: UniqueImmBorrow ,
419
- ) => {
420
- match closure_kind {
421
- ty:: ClosureKind :: Fn => {
422
- ( ty:: ClosureKind :: FnMut , Some ( ( usage_span, place. clone ( ) ) ) )
413
+ ty:: UpvarCapture :: ByRef (
414
+ ty:: BorrowKind :: MutBorrow | ty:: BorrowKind :: UniqueImmBorrow ,
415
+ ) => {
416
+ match closure_kind {
417
+ ty:: ClosureKind :: Fn => {
418
+ ( ty:: ClosureKind :: FnMut , Some ( ( usage_span, place. clone ( ) ) ) )
419
+ }
420
+ // Don't update the origin
421
+ ty:: ClosureKind :: FnMut | ty:: ClosureKind :: FnOnce => {
422
+ ( closure_kind, origin. take ( ) )
423
+ }
423
424
}
424
- // Don't update the origin
425
- ty:: ClosureKind :: FnMut | ty:: ClosureKind :: FnOnce => ( closure_kind, origin) ,
426
425
}
427
- }
428
-
429
- _ => ( closure_kind, origin) ,
430
- } ;
431
426
432
- closure_kind = updated . 0 ;
433
- origin = updated . 1 ;
427
+ _ => ( closure_kind , origin . take ( ) ) ,
428
+ } ;
434
429
435
- let ( place, capture_kind) = match capture_clause {
436
- hir:: CaptureBy :: Value => adjust_for_move_closure ( place, capture_info. capture_kind ) ,
437
- hir:: CaptureBy :: Ref => {
438
- adjust_for_non_move_closure ( place, capture_info. capture_kind )
439
- }
440
- } ;
430
+ closure_kind = updated. 0 ;
431
+ origin = updated. 1 ;
441
432
442
- // This restriction needs to be applied after we have handled adjustments for `move`
443
- // closures. We want to make sure any adjustment that might make us move the place into
444
- // the closure gets handled.
445
- let ( place, capture_kind) =
446
- restrict_precision_for_drop_types ( self , place, capture_kind, usage_span) ;
433
+ let ( place, capture_kind) = match capture_clause {
434
+ hir:: CaptureBy :: Value => adjust_for_move_closure ( place, capture_kind) ,
435
+ hir:: CaptureBy :: Ref => adjust_for_non_move_closure ( place, capture_kind) ,
436
+ } ;
447
437
448
- capture_info. capture_kind = capture_kind;
438
+ // This restriction needs to be applied after we have handled adjustments for `move`
439
+ // closures. We want to make sure any adjustment that might make us move the place into
440
+ // the closure gets handled.
441
+ let ( place, capture_kind) =
442
+ restrict_precision_for_drop_types ( self , place, capture_kind, usage_span) ;
449
443
450
- let capture_info = if let Some ( existing) = processed. get ( & place) {
451
- determine_capture_info ( * existing, capture_info)
452
- } else {
453
- capture_info
454
- } ;
455
- processed. insert ( place, capture_info) ;
456
- }
444
+ capture_info. capture_kind = capture_kind;
445
+ ( place, capture_info)
446
+ } )
447
+ . collect ( ) ;
457
448
458
449
( processed, closure_kind, origin)
459
450
}
@@ -609,8 +600,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
609
600
if !descendant_found {
610
601
for possible_ancestor in min_cap_list. iter_mut ( ) {
611
602
match determine_place_ancestry_relation ( & place, & possible_ancestor. place ) {
603
+ PlaceAncestryRelation :: SamePlace => {
604
+ ancestor_found = true ;
605
+ possible_ancestor. info = determine_capture_info (
606
+ possible_ancestor. info ,
607
+ updated_capture_info,
608
+ ) ;
609
+
610
+ // Only one related place will be in the list.
611
+ break ;
612
+ }
612
613
// current place is descendant of possible_ancestor
613
- PlaceAncestryRelation :: Descendant | PlaceAncestryRelation :: SamePlace => {
614
+ PlaceAncestryRelation :: Descendant => {
614
615
ancestor_found = true ;
615
616
let backup_path_expr_id = possible_ancestor. info . path_expr_id ;
616
617
@@ -630,7 +631,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
630
631
// we need to keep the ancestor's `path_expr_id`
631
632
possible_ancestor. info . path_expr_id = backup_path_expr_id;
632
633
633
- // Only one ancestor of the current place will be in the list.
634
+ // Only one related place will be in the list.
634
635
break ;
635
636
}
636
637
_ => { }
@@ -1532,7 +1533,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1532
1533
fn log_capture_analysis_first_pass (
1533
1534
& self ,
1534
1535
closure_def_id : rustc_hir:: def_id:: DefId ,
1535
- capture_information : & FxIndexMap < Place < ' tcx > , ty :: CaptureInfo > ,
1536
+ capture_information : & InferredCaptureInformation < ' tcx > ,
1536
1537
closure_span : Span ,
1537
1538
) {
1538
1539
if self . should_log_capture_analysis ( closure_def_id) {
@@ -1759,20 +1760,6 @@ struct InferBorrowKind<'a, 'tcx> {
1759
1760
fake_reads : Vec < ( Place < ' tcx > , FakeReadCause , hir:: HirId ) > ,
1760
1761
}
1761
1762
1762
- impl < ' a , ' tcx > InferBorrowKind < ' a , ' tcx > {
1763
- fn adjust_capture_info ( & mut self , place : Place < ' tcx > , capture_info : ty:: CaptureInfo ) {
1764
- match self . capture_information . get_mut ( & place) {
1765
- Some ( curr_info) => {
1766
- * curr_info = determine_capture_info ( * curr_info, capture_info) ;
1767
- }
1768
- None => {
1769
- debug ! ( "Capturing new place {:?}, capture_info={:?}" , place, capture_info) ;
1770
- self . capture_information . insert ( place, capture_info) ;
1771
- }
1772
- }
1773
- }
1774
- }
1775
-
1776
1763
impl < ' a , ' tcx > euv:: Delegate < ' tcx > for InferBorrowKind < ' a , ' tcx > {
1777
1764
fn fake_read ( & mut self , place : Place < ' tcx > , cause : FakeReadCause , diag_expr_id : hir:: HirId ) {
1778
1765
let PlaceBase :: Upvar ( _) = place. base else { return } ;
@@ -1797,14 +1784,14 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for InferBorrowKind<'a, 'tcx> {
1797
1784
let PlaceBase :: Upvar ( upvar_id) = place_with_id. place . base else { return } ;
1798
1785
assert_eq ! ( self . closure_def_id, upvar_id. closure_expr_id) ;
1799
1786
1800
- self . adjust_capture_info (
1787
+ self . capture_information . push ( (
1801
1788
place_with_id. place . clone ( ) ,
1802
1789
ty:: CaptureInfo {
1803
1790
capture_kind_expr_id : Some ( diag_expr_id) ,
1804
1791
path_expr_id : Some ( diag_expr_id) ,
1805
1792
capture_kind : ty:: UpvarCapture :: ByValue ,
1806
1793
} ,
1807
- ) ;
1794
+ ) ) ;
1808
1795
}
1809
1796
1810
1797
#[ instrument( skip( self ) , level = "debug" ) ]
@@ -1835,14 +1822,14 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for InferBorrowKind<'a, 'tcx> {
1835
1822
capture_kind = ty:: UpvarCapture :: ByRef ( ty:: BorrowKind :: ImmBorrow ) ;
1836
1823
}
1837
1824
1838
- self . adjust_capture_info (
1825
+ self . capture_information . push ( (
1839
1826
place,
1840
1827
ty:: CaptureInfo {
1841
1828
capture_kind_expr_id : Some ( diag_expr_id) ,
1842
1829
path_expr_id : Some ( diag_expr_id) ,
1843
1830
capture_kind,
1844
1831
} ,
1845
- ) ;
1832
+ ) ) ;
1846
1833
}
1847
1834
1848
1835
#[ instrument( skip( self ) , level = "debug" ) ]
0 commit comments