3333use super :: FnCtxt ;
3434
3535use crate :: expr_use_visitor as euv;
36- use rustc_data_structures:: fx:: FxIndexMap ;
3736use rustc_errors:: Applicability ;
3837use rustc_hir as hir;
3938use rustc_hir:: def_id:: DefId ;
@@ -72,7 +71,7 @@ enum PlaceAncestryRelation {
7271/// Intermediate format to store a captured `Place` and associated `ty::CaptureInfo`
7372/// during capture analysis. Information in this map feeds into the minimum capture
7473/// analysis pass.
75- type InferredCaptureInformation < ' tcx > = FxIndexMap < Place < ' tcx > , ty:: CaptureInfo > ;
74+ type InferredCaptureInformation < ' tcx > = Vec < ( Place < ' tcx > , ty:: CaptureInfo ) > ;
7675
7776impl < ' a , ' tcx > FnCtxt < ' a , ' tcx > {
7877 pub fn closure_analyze ( & self , body : & ' tcx hir:: Body < ' tcx > ) {
@@ -258,7 +257,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
258257 capture_kind,
259258 } ;
260259
261- capture_information. insert ( place, fake_info) ;
260+ capture_information. push ( ( place, fake_info) ) ;
262261 }
263262 }
264263
@@ -384,76 +383,68 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
384383 capture_clause : hir:: CaptureBy ,
385384 capture_information : InferredCaptureInformation < ' tcx > ,
386385 ) -> ( InferredCaptureInformation < ' tcx > , ty:: ClosureKind , Option < ( Span , Place < ' tcx > ) > ) {
387- let mut processed: InferredCaptureInformation < ' tcx > = Default :: default ( ) ;
388-
389386 let mut closure_kind = ty:: ClosureKind :: LATTICE_BOTTOM ;
390387 let mut origin: Option < ( Span , Place < ' tcx > ) > = None ;
391388
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 ) ;
397395
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) ;
401397
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+ } ;
407403
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+ } ,
416412
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+ }
423424 }
424- // Don't update the origin
425- ty:: ClosureKind :: FnMut | ty:: ClosureKind :: FnOnce => ( closure_kind, origin) ,
426425 }
427- }
428-
429- _ => ( closure_kind, origin) ,
430- } ;
431426
432- closure_kind = updated . 0 ;
433- origin = updated . 1 ;
427+ _ => ( closure_kind , origin . take ( ) ) ,
428+ } ;
434429
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 ;
441432
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+ } ;
447437
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) ;
449443
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 ( ) ;
457448
458449 ( processed, closure_kind, origin)
459450 }
@@ -609,8 +600,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
609600 if !descendant_found {
610601 for possible_ancestor in min_cap_list. iter_mut ( ) {
611602 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+ }
612613 // current place is descendant of possible_ancestor
613- PlaceAncestryRelation :: Descendant | PlaceAncestryRelation :: SamePlace => {
614+ PlaceAncestryRelation :: Descendant => {
614615 ancestor_found = true ;
615616 let backup_path_expr_id = possible_ancestor. info . path_expr_id ;
616617
@@ -630,7 +631,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
630631 // we need to keep the ancestor's `path_expr_id`
631632 possible_ancestor. info . path_expr_id = backup_path_expr_id;
632633
633- // Only one ancestor of the current place will be in the list.
634+ // Only one related place will be in the list.
634635 break ;
635636 }
636637 _ => { }
@@ -1532,7 +1533,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
15321533 fn log_capture_analysis_first_pass (
15331534 & self ,
15341535 closure_def_id : rustc_hir:: def_id:: DefId ,
1535- capture_information : & FxIndexMap < Place < ' tcx > , ty :: CaptureInfo > ,
1536+ capture_information : & InferredCaptureInformation < ' tcx > ,
15361537 closure_span : Span ,
15371538 ) {
15381539 if self . should_log_capture_analysis ( closure_def_id) {
@@ -1759,20 +1760,6 @@ struct InferBorrowKind<'a, 'tcx> {
17591760 fake_reads : Vec < ( Place < ' tcx > , FakeReadCause , hir:: HirId ) > ,
17601761}
17611762
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-
17761763impl < ' a , ' tcx > euv:: Delegate < ' tcx > for InferBorrowKind < ' a , ' tcx > {
17771764 fn fake_read ( & mut self , place : Place < ' tcx > , cause : FakeReadCause , diag_expr_id : hir:: HirId ) {
17781765 let PlaceBase :: Upvar ( _) = place. base else { return } ;
@@ -1797,14 +1784,14 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for InferBorrowKind<'a, 'tcx> {
17971784 let PlaceBase :: Upvar ( upvar_id) = place_with_id. place . base else { return } ;
17981785 assert_eq ! ( self . closure_def_id, upvar_id. closure_expr_id) ;
17991786
1800- self . adjust_capture_info (
1787+ self . capture_information . push ( (
18011788 place_with_id. place . clone ( ) ,
18021789 ty:: CaptureInfo {
18031790 capture_kind_expr_id : Some ( diag_expr_id) ,
18041791 path_expr_id : Some ( diag_expr_id) ,
18051792 capture_kind : ty:: UpvarCapture :: ByValue ,
18061793 } ,
1807- ) ;
1794+ ) ) ;
18081795 }
18091796
18101797 #[ instrument( skip( self ) , level = "debug" ) ]
@@ -1835,14 +1822,14 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for InferBorrowKind<'a, 'tcx> {
18351822 capture_kind = ty:: UpvarCapture :: ByRef ( ty:: BorrowKind :: ImmBorrow ) ;
18361823 }
18371824
1838- self . adjust_capture_info (
1825+ self . capture_information . push ( (
18391826 place,
18401827 ty:: CaptureInfo {
18411828 capture_kind_expr_id : Some ( diag_expr_id) ,
18421829 path_expr_id : Some ( diag_expr_id) ,
18431830 capture_kind,
18441831 } ,
1845- ) ;
1832+ ) ) ;
18461833 }
18471834
18481835 #[ instrument( skip( self ) , level = "debug" ) ]
0 commit comments