@@ -187,70 +187,79 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> {
187187 }
188188 }
189189
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" ) ;
220205 }
221206 }
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+ }
222213 _ => return None ,
223214 }
224215 }
216+ _ => return None ,
217+ }
225218
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+ }
240221
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+ } ;
250235
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+ }
252243 }
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 ) ) ;
254263 }
255264 }
256265 }
@@ -261,11 +270,11 @@ pub(super) fn mir_abstract_const<'tcx>(
261270 tcx : TyCtxt < ' tcx > ,
262271 def : ty:: WithOptConstParam < LocalDefId > ,
263272) -> Option < & ' tcx [ Node < ' tcx > ] > {
264- if !tcx. features ( ) . const_evaluatable_checked {
265- None
266- } else {
273+ if tcx. features ( ) . const_evaluatable_checked {
267274 let body = tcx. mir_const ( def) . borrow ( ) ;
268275 AbstractConstBuilder :: new ( tcx, & body) ?. build ( )
276+ } else {
277+ None
269278 }
270279}
271280
0 commit comments