Skip to content

Commit e6b92db

Browse files
authored
[OpenQASM]: Properly detect zero step in const ranges (#2715)
We were trying to detect if a step in a const range was zero by manually inspecting the `step` expression before being const evaluated. This only works if the `step` expr is the `0` literal, but it won't work if it is a const-expression evaluating to zero. This PR changes that logic to check the `step` value after being const-evaluated. Fixes #2702
1 parent e428ee9 commit e6b92db

File tree

3 files changed

+34
-2
lines changed

3 files changed

+34
-2
lines changed

source/compiler/qsc_qasm/src/semantic/lowerer.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4589,8 +4589,8 @@ impl Lowerer {
45894589
// The spec says that the step cannot be zero, so we push an error in that case.
45904590
// <https://openqasm.com/language/types.html#register-concatenation-and-slicing>
45914591
if let Some(Some(step)) = &step {
4592-
if let semantic::ExprKind::Lit(semantic::LiteralKind::Int(val)) = &*step.kind {
4593-
if *val == 0 {
4592+
if let Some(semantic::LiteralKind::Int(val)) = step.get_const_value() {
4593+
if val == 0 {
45944594
self.push_semantic_error(SemanticErrorKind::ZeroStepInRange(range.span));
45954595
return None;
45964596
}

source/compiler/qsc_qasm/src/tests/expression/indexed.rs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -442,3 +442,26 @@ fn positive_index_out_of_bounds_errors() {
442442
"#]],
443443
);
444444
}
445+
446+
#[test]
447+
fn const_zero_step_errors() {
448+
let source = r#"
449+
const bit[4] a = "1010";
450+
const bit b = a[:"0":];
451+
"#;
452+
453+
check_qasm_to_qsharp(
454+
source,
455+
&expect![[r#"
456+
Qasm.Lowerer.ZeroStepInRange
457+
458+
x range step cannot be zero
459+
,-[Test.qasm:3:25]
460+
2 | const bit[4] a = "1010";
461+
3 | const bit b = a[:"0":];
462+
: ^^^^^
463+
4 |
464+
`----
465+
"#]],
466+
);
467+
}

source/compiler/qsc_qasm/src/tests/fuzz.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,3 +171,12 @@ fn fuzz_2669() {
171171
let source = "gphase(1E1000);";
172172
compile_qasm_best_effort(source);
173173
}
174+
175+
/// We weren't detecting that the step of a range was zero if it was
176+
/// something other than a literal int. For example, a literal zero
177+
/// bitstring wasn't been detected.
178+
#[test]
179+
fn fuzz_2702() {
180+
let source = r#""0"[0:"0":0]"#;
181+
compile_qasm_best_effort(source);
182+
}

0 commit comments

Comments
 (0)