@@ -187,70 +187,79 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> {
187
187
}
188
188
}
189
189
190
- fn build ( mut self ) -> Option < & ' tcx [ Node < ' tcx > ] > {
191
- let mut block = & self . body . basic_blocks ( ) [ mir:: START_BLOCK ] ;
192
- loop {
193
- debug ! ( "AbstractConstBuilder: block={:?}" , block) ;
194
- for stmt in block. statements . iter ( ) {
195
- debug ! ( "AbstractConstBuilder: stmt={:?}" , stmt) ;
196
- match stmt. kind {
197
- StatementKind :: Assign ( box ( ref place, ref rvalue) ) => {
198
- let local = place. as_local ( ) ?;
199
- match * rvalue {
200
- Rvalue :: Use ( ref operand) => {
201
- self . locals [ local] = self . operand_to_node ( operand) ?;
202
- }
203
- Rvalue :: BinaryOp ( op, ref lhs, ref rhs) if Self :: check_binop ( op) => {
204
- let lhs = self . operand_to_node ( lhs) ?;
205
- let rhs = self . operand_to_node ( rhs) ?;
206
- self . locals [ local] = self . add_node ( Node :: Binop ( op, lhs, rhs) ) ;
207
- if op. is_checkable ( ) {
208
- bug ! ( "unexpected unchecked checkable binary operation" ) ;
209
- }
210
- }
211
- Rvalue :: CheckedBinaryOp ( op, ref lhs, ref rhs)
212
- if Self :: check_binop ( op) =>
213
- {
214
- let lhs = self . operand_to_node ( lhs) ?;
215
- let rhs = self . operand_to_node ( rhs) ?;
216
- self . locals [ local] = self . add_node ( Node :: Binop ( op, lhs, rhs) ) ;
217
- self . checked_op_locals . insert ( local) ;
218
- }
219
- _ => return None ,
190
+ fn build_statement ( & mut self , stmt : & mir:: Statement < ' tcx > ) -> Option < ( ) > {
191
+ debug ! ( "AbstractConstBuilder: stmt={:?}" , stmt) ;
192
+ match stmt. kind {
193
+ StatementKind :: Assign ( box ( ref place, ref rvalue) ) => {
194
+ let local = place. as_local ( ) ?;
195
+ match * rvalue {
196
+ Rvalue :: Use ( ref operand) => {
197
+ self . locals [ local] = self . operand_to_node ( operand) ?;
198
+ }
199
+ Rvalue :: BinaryOp ( op, ref lhs, ref rhs) if Self :: check_binop ( op) => {
200
+ let lhs = self . operand_to_node ( lhs) ?;
201
+ let rhs = self . operand_to_node ( rhs) ?;
202
+ self . locals [ local] = self . add_node ( Node :: Binop ( op, lhs, rhs) ) ;
203
+ if op. is_checkable ( ) {
204
+ bug ! ( "unexpected unchecked checkable binary operation" ) ;
220
205
}
221
206
}
207
+ Rvalue :: CheckedBinaryOp ( op, ref lhs, ref rhs) if Self :: check_binop ( op) => {
208
+ let lhs = self . operand_to_node ( lhs) ?;
209
+ let rhs = self . operand_to_node ( rhs) ?;
210
+ self . locals [ local] = self . add_node ( Node :: Binop ( op, lhs, rhs) ) ;
211
+ self . checked_op_locals . insert ( local) ;
212
+ }
222
213
_ => return None ,
223
214
}
224
215
}
216
+ _ => return None ,
217
+ }
225
218
226
- debug ! ( "AbstractConstBuilder: terminator={:?}" , block. terminator( ) ) ;
227
- match block. terminator ( ) . kind {
228
- TerminatorKind :: Goto { target } => {
229
- block = & self . body . basic_blocks ( ) [ target] ;
230
- }
231
- TerminatorKind :: Return => {
232
- warn ! ( ?self . nodes) ;
233
- return { Some ( self . tcx . arena . alloc_from_iter ( self . nodes ) ) } ;
234
- }
235
- TerminatorKind :: Assert { ref cond, expected : false , target, .. } => {
236
- let p = match cond {
237
- mir:: Operand :: Copy ( p) | mir:: Operand :: Move ( p) => p,
238
- mir:: Operand :: Constant ( _) => bug ! ( "Unexpected assert" ) ,
239
- } ;
219
+ Some ( ( ) )
220
+ }
240
221
241
- const ONE_FIELD : mir:: Field = mir:: Field :: from_usize ( 1 ) ;
242
- debug ! ( "proj: {:?}" , p. projection) ;
243
- if let & [ mir:: ProjectionElem :: Field ( ONE_FIELD , _) ] = p. projection . as_ref ( ) {
244
- // Only allow asserts checking the result of a checked operation.
245
- if self . checked_op_locals . contains ( p. local ) {
246
- block = & self . body . basic_blocks ( ) [ target] ;
247
- continue ;
248
- }
249
- }
222
+ fn build_terminator (
223
+ & mut self ,
224
+ terminator : & mir:: Terminator < ' tcx > ,
225
+ ) -> Option < Option < mir:: BasicBlock > > {
226
+ debug ! ( "AbstractConstBuilder: terminator={:?}" , terminator) ;
227
+ match terminator. kind {
228
+ TerminatorKind :: Goto { target } => Some ( Some ( target) ) ,
229
+ TerminatorKind :: Return => Some ( None ) ,
230
+ TerminatorKind :: Assert { ref cond, expected : false , target, .. } => {
231
+ let p = match cond {
232
+ mir:: Operand :: Copy ( p) | mir:: Operand :: Move ( p) => p,
233
+ mir:: Operand :: Constant ( _) => bug ! ( "Unexpected assert" ) ,
234
+ } ;
250
235
251
- return None ;
236
+ const ONE_FIELD : mir:: Field = mir:: Field :: from_usize ( 1 ) ;
237
+ debug ! ( "proj: {:?}" , p. projection) ;
238
+ if let & [ mir:: ProjectionElem :: Field ( ONE_FIELD , _) ] = p. projection . as_ref ( ) {
239
+ // Only allow asserts checking the result of a checked operation.
240
+ if self . checked_op_locals . contains ( p. local ) {
241
+ return Some ( Some ( target) ) ;
242
+ }
252
243
}
253
- _ => return None ,
244
+
245
+ None
246
+ }
247
+ _ => None ,
248
+ }
249
+ }
250
+
251
+ fn build ( mut self ) -> Option < & ' tcx [ Node < ' tcx > ] > {
252
+ let mut block = & self . body . basic_blocks ( ) [ mir:: START_BLOCK ] ;
253
+ loop {
254
+ debug ! ( "AbstractConstBuilder: block={:?}" , block) ;
255
+ for stmt in block. statements . iter ( ) {
256
+ self . build_statement ( stmt) ?;
257
+ }
258
+
259
+ if let Some ( next) = self . build_terminator ( block. terminator ( ) ) ? {
260
+ block = & self . body . basic_blocks ( ) [ next] ;
261
+ } else {
262
+ return Some ( self . tcx . arena . alloc_from_iter ( self . nodes ) ) ;
254
263
}
255
264
}
256
265
}
@@ -261,11 +270,11 @@ pub(super) fn mir_abstract_const<'tcx>(
261
270
tcx : TyCtxt < ' tcx > ,
262
271
def : ty:: WithOptConstParam < LocalDefId > ,
263
272
) -> Option < & ' tcx [ Node < ' tcx > ] > {
264
- if !tcx. features ( ) . const_evaluatable_checked {
265
- None
266
- } else {
273
+ if tcx. features ( ) . const_evaluatable_checked {
267
274
let body = tcx. mir_const ( def) . borrow ( ) ;
268
275
AbstractConstBuilder :: new ( tcx, & body) ?. build ( )
276
+ } else {
277
+ None
269
278
}
270
279
}
271
280
0 commit comments