Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit f24d532

Browse files
committed
refactor AbstractConstBuilder
1 parent c3a772f commit f24d532

File tree

1 file changed

+67
-58
lines changed

1 file changed

+67
-58
lines changed

compiler/rustc_trait_selection/src/traits/const_evaluatable.rs

Lines changed: 67 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)