]> git.lizzy.rs Git - rust.git/commitdiff
refactor AbstractConstBuilder
authorBastian Kauschke <bastian_kauschke@hotmail.de>
Fri, 11 Sep 2020 07:00:21 +0000 (09:00 +0200)
committerBastian Kauschke <bastian_kauschke@hotmail.de>
Fri, 18 Sep 2020 15:11:34 +0000 (17:11 +0200)
compiler/rustc_trait_selection/src/traits/const_evaluatable.rs

index e14af1a27ef447be9449de339e0187eca81d59b3..337276fd811e75219ff838aa1b18acc6d835fcbe 100644 (file)
@@ -187,70 +187,79 @@ fn check_binop(op: mir::BinOp) -> bool {
         }
     }
 
-    fn build(mut self) -> Option<&'tcx [Node<'tcx>]> {
-        let mut block = &self.body.basic_blocks()[mir::START_BLOCK];
-        loop {
-            debug!("AbstractConstBuilder: block={:?}", block);
-            for stmt in block.statements.iter() {
-                debug!("AbstractConstBuilder: stmt={:?}", stmt);
-                match stmt.kind {
-                    StatementKind::Assign(box (ref place, ref rvalue)) => {
-                        let local = place.as_local()?;
-                        match *rvalue {
-                            Rvalue::Use(ref operand) => {
-                                self.locals[local] = self.operand_to_node(operand)?;
-                            }
-                            Rvalue::BinaryOp(op, ref lhs, ref rhs) if Self::check_binop(op) => {
-                                let lhs = self.operand_to_node(lhs)?;
-                                let rhs = self.operand_to_node(rhs)?;
-                                self.locals[local] = self.add_node(Node::Binop(op, lhs, rhs));
-                                if op.is_checkable() {
-                                    bug!("unexpected unchecked checkable binary operation");
-                                }
-                            }
-                            Rvalue::CheckedBinaryOp(op, ref lhs, ref rhs)
-                                if Self::check_binop(op) =>
-                            {
-                                let lhs = self.operand_to_node(lhs)?;
-                                let rhs = self.operand_to_node(rhs)?;
-                                self.locals[local] = self.add_node(Node::Binop(op, lhs, rhs));
-                                self.checked_op_locals.insert(local);
-                            }
-                            _ => return None,
+    fn build_statement(&mut self, stmt: &mir::Statement<'tcx>) -> Option<()> {
+        debug!("AbstractConstBuilder: stmt={:?}", stmt);
+        match stmt.kind {
+            StatementKind::Assign(box (ref place, ref rvalue)) => {
+                let local = place.as_local()?;
+                match *rvalue {
+                    Rvalue::Use(ref operand) => {
+                        self.locals[local] = self.operand_to_node(operand)?;
+                    }
+                    Rvalue::BinaryOp(op, ref lhs, ref rhs) if Self::check_binop(op) => {
+                        let lhs = self.operand_to_node(lhs)?;
+                        let rhs = self.operand_to_node(rhs)?;
+                        self.locals[local] = self.add_node(Node::Binop(op, lhs, rhs));
+                        if op.is_checkable() {
+                            bug!("unexpected unchecked checkable binary operation");
                         }
                     }
+                    Rvalue::CheckedBinaryOp(op, ref lhs, ref rhs) if Self::check_binop(op) => {
+                        let lhs = self.operand_to_node(lhs)?;
+                        let rhs = self.operand_to_node(rhs)?;
+                        self.locals[local] = self.add_node(Node::Binop(op, lhs, rhs));
+                        self.checked_op_locals.insert(local);
+                    }
                     _ => return None,
                 }
             }
+            _ => return None,
+        }
 
-            debug!("AbstractConstBuilder: terminator={:?}", block.terminator());
-            match block.terminator().kind {
-                TerminatorKind::Goto { target } => {
-                    block = &self.body.basic_blocks()[target];
-                }
-                TerminatorKind::Return => {
-                    warn!(?self.nodes);
-                    return { Some(self.tcx.arena.alloc_from_iter(self.nodes)) };
-                }
-                TerminatorKind::Assert { ref cond, expected: false, target, .. } => {
-                    let p = match cond {
-                        mir::Operand::Copy(p) | mir::Operand::Move(p) => p,
-                        mir::Operand::Constant(_) => bug!("Unexpected assert"),
-                    };
+        Some(())
+    }
 
-                    const ONE_FIELD: mir::Field = mir::Field::from_usize(1);
-                    debug!("proj: {:?}", p.projection);
-                    if let &[mir::ProjectionElem::Field(ONE_FIELD, _)] = p.projection.as_ref() {
-                        // Only allow asserts checking the result of a checked operation.
-                        if self.checked_op_locals.contains(p.local) {
-                            block = &self.body.basic_blocks()[target];
-                            continue;
-                        }
-                    }
+    fn build_terminator(
+        &mut self,
+        terminator: &mir::Terminator<'tcx>,
+    ) -> Option<Option<mir::BasicBlock>> {
+        debug!("AbstractConstBuilder: terminator={:?}", terminator);
+        match terminator.kind {
+            TerminatorKind::Goto { target } => Some(Some(target)),
+            TerminatorKind::Return => Some(None),
+            TerminatorKind::Assert { ref cond, expected: false, target, .. } => {
+                let p = match cond {
+                    mir::Operand::Copy(p) | mir::Operand::Move(p) => p,
+                    mir::Operand::Constant(_) => bug!("Unexpected assert"),
+                };
 
-                    return None;
+                const ONE_FIELD: mir::Field = mir::Field::from_usize(1);
+                debug!("proj: {:?}", p.projection);
+                if let &[mir::ProjectionElem::Field(ONE_FIELD, _)] = p.projection.as_ref() {
+                    // Only allow asserts checking the result of a checked operation.
+                    if self.checked_op_locals.contains(p.local) {
+                        return Some(Some(target));
+                    }
                 }
-                _ => return None,
+
+                None
+            }
+            _ => None,
+        }
+    }
+
+    fn build(mut self) -> Option<&'tcx [Node<'tcx>]> {
+        let mut block = &self.body.basic_blocks()[mir::START_BLOCK];
+        loop {
+            debug!("AbstractConstBuilder: block={:?}", block);
+            for stmt in block.statements.iter() {
+                self.build_statement(stmt)?;
+            }
+
+            if let Some(next) = self.build_terminator(block.terminator())? {
+                block = &self.body.basic_blocks()[next];
+            } else {
+                return Some(self.tcx.arena.alloc_from_iter(self.nodes));
             }
         }
     }
@@ -261,11 +270,11 @@ pub(super) fn mir_abstract_const<'tcx>(
     tcx: TyCtxt<'tcx>,
     def: ty::WithOptConstParam<LocalDefId>,
 ) -> Option<&'tcx [Node<'tcx>]> {
-    if !tcx.features().const_evaluatable_checked {
-        None
-    } else {
+    if tcx.features().const_evaluatable_checked {
         let body = tcx.mir_const(def).borrow();
         AbstractConstBuilder::new(tcx, &body)?.build()
+    } else {
+        None
     }
 }