@@ -112,19 +112,28 @@ fn borrowck<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, owner_def_id: DefId) {
112
112
// is not yet stolen.
113
113
tcx. mir_validated ( owner_def_id) . borrow ( ) ;
114
114
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
+ }
122
129
}
123
130
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
128
137
{
129
138
// Check the body of fn items.
130
139
let tcx = this. tcx ;
@@ -137,6 +146,18 @@ fn build_borrowck_dataflow_data<'a, 'tcx>(this: &mut BorrowckCtxt<'a, 'tcx>,
137
146
let ( all_loans, move_data) =
138
147
gather_loans:: gather_loans_in_fn ( this, body_id) ;
139
148
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) ;
140
161
let mut loan_dfcx =
141
162
DataFlowContext :: new ( this. tcx ,
142
163
"borrowck" ,
@@ -159,9 +180,9 @@ fn build_borrowck_dataflow_data<'a, 'tcx>(this: &mut BorrowckCtxt<'a, 'tcx>,
159
180
id_range,
160
181
body) ;
161
182
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 } )
165
186
}
166
187
167
188
/// Accessor for introspective clients inspecting `AnalysisData` and
@@ -178,8 +199,8 @@ pub fn build_borrowck_dataflow_data_for_fn<'a, 'tcx>(
178
199
let region_maps = tcx. region_maps ( owner_def_id) ;
179
200
let mut bccx = BorrowckCtxt { tcx, tables, region_maps, owner_def_id } ;
180
201
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 ( ) )
183
204
}
184
205
185
206
// ----------------------------------------------------------------------
0 commit comments