Skip to content

Commit 47e1c8e

Browse files
authored
Fix panic in RCA when using tuple variables as arguments to a lambda (#2701)
Fixes #2696
1 parent f567258 commit 47e1c8e

File tree

2 files changed

+61
-1
lines changed

2 files changed

+61
-1
lines changed

source/compiler/qsc_rca/src/core.rs

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2604,7 +2604,21 @@ fn map_input_pattern_to_input_expressions(
26042604
// All elements in the pattern map to the same expression.
26052605
// This is one of the boundaries where we can lose specific information since we are "unpacking" the
26062606
// tuple represented by a single expression.
2607-
vec![expr_id.expr; pats.len()]
2607+
let pats_len = if skip_ahead.is_some() {
2608+
// When skip_ahead is not None we know we are processing a lambda, so check if pattern is itself a tuple.
2609+
// If it is, that is the length we need to use rather than the original one.
2610+
if let PatKind::Tuple(pats) =
2611+
&package_store.get_pat((pat_id.package, pats[0]).into()).kind
2612+
{
2613+
pats.len()
2614+
} else {
2615+
pats.len()
2616+
}
2617+
} else {
2618+
pats.len()
2619+
};
2620+
2621+
vec![expr_id.expr; pats_len]
26082622
}
26092623
}
26102624
}

source/compiler/qsc_rca/src/tests/calls.rs

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -325,3 +325,49 @@ fn check_rca_for_call_to_function_that_receives_tuple_with_a_non_tuple_dynamic_a
325325
dynamic_param_applications: <empty>"#]],
326326
);
327327
}
328+
329+
#[test]
330+
fn check_rca_for_call_to_function_passed_single_tuple_variable_for_multiple_args() {
331+
let mut compilation_context = CompilationContext::default();
332+
compilation_context.update(
333+
r#"
334+
use q = Qubit();
335+
let x = (if MResetX(q) == One { 1 } else { 0 }, 2, 3);
336+
operation foo(a : Int, b : Int, c : Int) : Int { a + b + c };
337+
foo(x)
338+
"#,
339+
);
340+
let package_store_compute_properties = compilation_context.get_compute_properties();
341+
check_last_statement_compute_properties(
342+
package_store_compute_properties,
343+
&expect![[r#"
344+
ApplicationsGeneratorSet:
345+
inherent: Quantum: QuantumProperties:
346+
runtime_features: RuntimeFeatureFlags(UseOfDynamicBool | UseOfDynamicInt)
347+
value_kind: Element(Dynamic)
348+
dynamic_param_applications: <empty>"#]],
349+
);
350+
}
351+
352+
#[test]
353+
fn check_rca_for_call_to_lambda_passed_single_tuple_variable_for_multiple_args() {
354+
let mut compilation_context = CompilationContext::default();
355+
compilation_context.update(
356+
r#"
357+
use q = Qubit();
358+
let x = (if MResetX(q) == One { 1 } else { 0 }, 2, 3);
359+
let lambda = (a, b, c) -> { a + b + c };
360+
lambda(x)
361+
"#,
362+
);
363+
let package_store_compute_properties = compilation_context.get_compute_properties();
364+
check_last_statement_compute_properties(
365+
package_store_compute_properties,
366+
&expect![[r#"
367+
ApplicationsGeneratorSet:
368+
inherent: Quantum: QuantumProperties:
369+
runtime_features: RuntimeFeatureFlags(UseOfDynamicBool | UseOfDynamicInt)
370+
value_kind: Element(Dynamic)
371+
dynamic_param_applications: <empty>"#]],
372+
);
373+
}

0 commit comments

Comments
 (0)