@@ -112,19 +112,28 @@ fn borrowck<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, owner_def_id: DefId) {
112112 // is not yet stolen.
113113 tcx. mir_validated ( owner_def_id) . borrow ( ) ;
114114
115- let cfg = cfg:: CFG :: new ( bccx. tcx , & body) ;
116- let AnalysisData { all_loans,
117- loans : loan_dfcx,
118- move_data : flowed_moves } =
119- build_borrowck_dataflow_data ( bccx, & cfg, body_id) ;
120-
121- check_loans:: check_loans ( bccx, & loan_dfcx, & flowed_moves, & all_loans, body) ;
115+ // option dance because you can't capture an uninitialized variable
116+ // by mut-ref.
117+ let mut cfg = None ;
118+ if let Some ( AnalysisData { all_loans,
119+ loans : loan_dfcx,
120+ move_data : flowed_moves } ) =
121+ build_borrowck_dataflow_data ( bccx, false , body_id,
122+ |bccx| {
123+ cfg = Some ( cfg:: CFG :: new ( bccx. tcx , & body) ) ;
124+ cfg. as_mut ( ) . unwrap ( )
125+ } )
126+ {
127+ check_loans:: check_loans ( bccx, & loan_dfcx, & flowed_moves, & all_loans, body) ;
128+ }
122129}
123130
124- fn build_borrowck_dataflow_data < ' a , ' tcx > ( this : & mut BorrowckCtxt < ' a , ' tcx > ,
125- cfg : & cfg:: CFG ,
126- body_id : hir:: BodyId )
127- -> AnalysisData < ' a , ' tcx >
131+ fn build_borrowck_dataflow_data < ' a , ' c , ' tcx , F > ( this : & mut BorrowckCtxt < ' a , ' tcx > ,
132+ force_analysis : bool ,
133+ body_id : hir:: BodyId ,
134+ get_cfg : F )
135+ -> Option < AnalysisData < ' a , ' tcx > >
136+ where F : FnOnce ( & mut BorrowckCtxt < ' a , ' tcx > ) -> & ' c cfg:: CFG
128137{
129138 // Check the body of fn items.
130139 let tcx = this. tcx ;
@@ -137,6 +146,18 @@ fn build_borrowck_dataflow_data<'a, 'tcx>(this: &mut BorrowckCtxt<'a, 'tcx>,
137146 let ( all_loans, move_data) =
138147 gather_loans:: gather_loans_in_fn ( this, body_id) ;
139148
149+ if !force_analysis && move_data. is_empty ( ) && all_loans. is_empty ( ) {
150+ // large arrays of data inserted as constants can take a lot of
151+ // time and memory to borrow-check - see issue #36799. However,
152+ // they don't have lvalues, so no borrow-check is actually needed.
153+ // Recognize that case and skip borrow-checking.
154+ debug ! ( "skipping loan propagation for {:?} because of no loans" , body_id) ;
155+ return None ;
156+ } else {
157+ debug ! ( "propagating loans in {:?}" , body_id) ;
158+ }
159+
160+ let cfg = get_cfg ( this) ;
140161 let mut loan_dfcx =
141162 DataFlowContext :: new ( this. tcx ,
142163 "borrowck" ,
@@ -159,9 +180,9 @@ fn build_borrowck_dataflow_data<'a, 'tcx>(this: &mut BorrowckCtxt<'a, 'tcx>,
159180 id_range,
160181 body) ;
161182
162- AnalysisData { all_loans : all_loans,
163- loans : loan_dfcx,
164- move_data : flowed_moves }
183+ Some ( AnalysisData { all_loans : all_loans,
184+ loans : loan_dfcx,
185+ move_data : flowed_moves } )
165186}
166187
167188/// Accessor for introspective clients inspecting `AnalysisData` and
@@ -178,8 +199,8 @@ pub fn build_borrowck_dataflow_data_for_fn<'a, 'tcx>(
178199 let region_maps = tcx. region_maps ( owner_def_id) ;
179200 let mut bccx = BorrowckCtxt { tcx, tables, region_maps, owner_def_id } ;
180201
181- let dataflow_data = build_borrowck_dataflow_data ( & mut bccx, cfg , body_id) ;
182- ( bccx, dataflow_data)
202+ let dataflow_data = build_borrowck_dataflow_data ( & mut bccx, true , body_id, |_| cfg ) ;
203+ ( bccx, dataflow_data. unwrap ( ) )
183204}
184205
185206// ----------------------------------------------------------------------
0 commit comments