diff options
| author | Bastian Kauschke <bastian_kauschke@hotmail.de> | 2020-09-11 09:00:21 +0200 |
|---|---|---|
| committer | Bastian Kauschke <bastian_kauschke@hotmail.de> | 2020-09-18 17:11:34 +0200 |
| commit | f24d532749674c41940120866937860c8d4abcc8 (patch) | |
| tree | 4cd4bd1e7ec0a967d43d05ab06db51fea8b1d95a | |
| parent | c3a772f55f2263cd2f2709f2bb187f59a8b4a673 (diff) | |
| download | rust-f24d532749674c41940120866937860c8d4abcc8.tar.gz rust-f24d532749674c41940120866937860c8d4abcc8.zip | |
refactor AbstractConstBuilder
| -rw-r--r-- | compiler/rustc_trait_selection/src/traits/const_evaluatable.rs | 125 |
1 files changed, 67 insertions, 58 deletions
diff --git a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs index e14af1a27ef..337276fd811 100644 --- a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs +++ b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs @@ -187,70 +187,79 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> { } } - 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 } } |
