Skip to content

Commit d14d6c2

Browse files
cesarzcswernli
andauthored
Fix to partial evaluation generating branch instructions on constant conditions (#1963)
RCA can categorize an expression as dynamic even if it is in fact purely classical. This can happen in cases where a data structure such an array, tuple or UDT contains a mix of static and dynamic values. In such instances, RCA identifies all the contents of the data structure as dynamic even if some values are static. This causes partial evaluation to generate branch instructions on constant conditions under certain circumstances. This change fixes this issue. --------- Co-authored-by: Stefan J. Wernli <[email protected]>
1 parent 0d05c9f commit d14d6c2

File tree

2 files changed

+773
-0
lines changed

2 files changed

+773
-0
lines changed

compiler/qsc_partial_eval/src/lib.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -488,6 +488,28 @@ impl<'a> PartialEvaluator<'a> {
488488
panic!("expected result value from RHS expression");
489489
};
490490

491+
// Even though to get to this path, an expression would have to be categorized as hybrid by RCA, it is
492+
// possible that the expression is in fact purely classical.
493+
// This can happen in cases where a data structure such an array, tuple or UDT contains a mix of static and
494+
// dynamic values. In such instances, RCA identifies all the contents of the data structure as dynamic even if
495+
// some values are static.
496+
// Here we handle this case and if both operands are purely classical we evaluate them.
497+
if let (val::Result::Val(lhs_result_value), val::Result::Val(rhs_result_value)) =
498+
(lhs_result, rhs_result)
499+
{
500+
let bool_value = match bin_op {
501+
BinOp::Eq => lhs_result_value == rhs_result_value,
502+
BinOp::Neq => lhs_result_value != rhs_result_value,
503+
_ => {
504+
return Err(Error::Unexpected(
505+
format!("invalid binary operator for Result operands: {bin_op:?})"),
506+
bin_op_expr_span,
507+
))
508+
}
509+
};
510+
return Ok(EvalControlFlow::Continue(Value::Bool(bool_value)));
511+
}
512+
491513
// Get the operands to use when generating the binary operation instruction.
492514
let lhs_operand = self.eval_result_as_bool_operand(lhs_result);
493515
let rhs_operand = self.eval_result_as_bool_operand(rhs_result);

0 commit comments

Comments
 (0)