refactor AbstractConstBuilder
This commit is contained in:
parent
c3a772f55f
commit
f24d532749
@ -187,11 +187,7 @@ 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() {
|
||||
fn build_statement(&mut self, stmt: &mir::Statement<'tcx>) -> Option<()> {
|
||||
debug!("AbstractConstBuilder: stmt={:?}", stmt);
|
||||
match stmt.kind {
|
||||
StatementKind::Assign(box (ref place, ref rvalue)) => {
|
||||
@ -208,9 +204,7 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> {
|
||||
bug!("unexpected unchecked checkable binary operation");
|
||||
}
|
||||
}
|
||||
Rvalue::CheckedBinaryOp(op, ref lhs, ref rhs)
|
||||
if Self::check_binop(op) =>
|
||||
{
|
||||
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));
|
||||
@ -221,17 +215,18 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> {
|
||||
}
|
||||
_ => return None,
|
||||
}
|
||||
|
||||
Some(())
|
||||
}
|
||||
|
||||
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)) };
|
||||
}
|
||||
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,
|
||||
@ -243,14 +238,28 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> {
|
||||
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;
|
||||
return Some(Some(target));
|
||||
}
|
||||
}
|
||||
|
||||
return None;
|
||||
None
|
||||
}
|
||||
_ => return 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
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user