Skip to content

Commit

Permalink
Fix to RCA panic when assigning call result to tuple (#1359)
Browse files Browse the repository at this point in the history
This change fixes #1357.
  • Loading branch information
cesarzc authored Apr 4, 2024
1 parent 82c5d6b commit 597c39b
Show file tree
Hide file tree
Showing 2 changed files with 176 additions and 20 deletions.
52 changes: 32 additions & 20 deletions compiler/qsc_rca/src/core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1390,27 +1390,39 @@ impl<'a> Analyzer<'a> {
updated_compute_kind
}
ExprKind::Tuple(assignee_exprs) => {
let ExprKind::Tuple(value_exprs) = &value_expr.kind else {
panic!("expected a tuple");
};
assert!(assignee_exprs.len() == value_exprs.len());

// To determine the update compute kind, we aggregate the runtime features of each element.
let default_value_kind = ValueKind::new_static_from_type(&value_expr.ty);
let mut updated_compute_kind = ComputeKind::Classical;
for (element_assignee_expr_id, element_value_expr_id) in
assignee_exprs.iter().zip(value_exprs.iter())
{
let element_update_compute_kind = self.update_locals_compute_kind(
*element_assignee_expr_id,
*element_value_expr_id,
);
updated_compute_kind = updated_compute_kind.aggregate_runtime_features(
element_update_compute_kind,
default_value_kind,
);
if let ExprKind::Tuple(value_exprs) = &value_expr.kind {
assert!(assignee_exprs.len() == value_exprs.len());

// To determine the update compute kind, we aggregate the runtime features of each element.
let default_value_kind = ValueKind::new_static_from_type(&value_expr.ty);
let mut updated_compute_kind = ComputeKind::Classical;
for (element_assignee_expr_id, element_value_expr_id) in
assignee_exprs.iter().zip(value_exprs.iter())
{
let element_update_compute_kind = self.update_locals_compute_kind(
*element_assignee_expr_id,
*element_value_expr_id,
);
updated_compute_kind = updated_compute_kind.aggregate_runtime_features(
element_update_compute_kind,
default_value_kind,
);
}
updated_compute_kind
} else {
// To determine the update compute kind, we aggregate the runtime features of each update.
let default_value_kind = ValueKind::new_static_from_type(&value_expr.ty);
let mut updated_compute_kind = ComputeKind::Classical;
for element_assignee_expr_id in assignee_exprs {
let element_update_compute_kind = self
.update_locals_compute_kind(*element_assignee_expr_id, value_expr_id);
updated_compute_kind = updated_compute_kind.aggregate_runtime_features(
element_update_compute_kind,
default_value_kind,
);
}
updated_compute_kind
}
updated_compute_kind
}
_ => panic!("expected a local variable or a tuple"),
}
Expand Down
144 changes: 144 additions & 0 deletions compiler/qsc_rca/tests/assigns.rs
Original file line number Diff line number Diff line change
Expand Up @@ -132,3 +132,147 @@ fn check_rca_for_dynamic_double_assign_to_local() {
],
);
}

#[test]
fn chec_rca_for_assign_call_result_to_tuple_of_vars() {
let mut compilation_context = CompilationContext::default();
compilation_context.update(
r#"
function Foo() : (Int, Int) {
return (1,2);
}
mutable a = 1;
mutable b = 2;
set (a, b) = Foo();
"#,
);
let package_store_compute_properties = compilation_context.get_compute_properties();
check_last_statement_compute_properties(
package_store_compute_properties,
&expect![[r#"
ApplicationsGeneratorSet:
inherent: Classical
dynamic_param_applications: <empty>"#]],
);
}

#[test]
fn chec_rca_for_assign_var_binded_to_call_result_to_tuple_of_vars() {
let mut compilation_context = CompilationContext::default();
compilation_context.update(
r#"
function Foo() : (Int, Int) {
return (1,2);
}
let x = Foo();
mutable a = 1;
mutable b = 2;
set (a, b) = x;
"#,
);
let package_store_compute_properties = compilation_context.get_compute_properties();
check_last_statement_compute_properties(
package_store_compute_properties,
&expect![[r#"
ApplicationsGeneratorSet:
inherent: Classical
dynamic_param_applications: <empty>"#]],
);
}

#[test]
fn chec_rca_for_assign_tuple_var_to_tuple_of_vars() {
let mut compilation_context = CompilationContext::default();
compilation_context.update(
r#"
let x = (1, (2, 3));
mutable a = 4;
mutable b = (5, 6);
set (a, b) = x;
"#,
);
let package_store_compute_properties = compilation_context.get_compute_properties();
check_last_statement_compute_properties(
package_store_compute_properties,
&expect![[r#"
ApplicationsGeneratorSet:
inherent: Classical
dynamic_param_applications: <empty>"#]],
);
}

#[test]
fn check_rca_for_assign_classical_call_result_to_tuple_of_vars() {
let mut compilation_context = CompilationContext::default();
compilation_context.update(
r#"
function Foo(a : Int, b : Int) : (Int, Int) {
return (b, a);
}
mutable a = 1;
mutable b = 2;
set (a, b) = Foo(a, b);
a
"#,
);
check_last_statement_compute_properties(
compilation_context.get_compute_properties(),
&expect![[r#"
ApplicationsGeneratorSet:
inherent: Classical
dynamic_param_applications: <empty>"#]],
);
compilation_context.update(
r#"
b
"#,
);
check_last_statement_compute_properties(
compilation_context.get_compute_properties(),
&expect![[r#"
ApplicationsGeneratorSet:
inherent: Classical
dynamic_param_applications: <empty>"#]],
);
}

#[test]
fn check_rca_for_assign_dynamic_call_result_to_tuple_of_vars() {
let mut compilation_context = CompilationContext::default();
compilation_context.update(
r#"
function Foo(a : Int, b : Int) : (Int, Int) {
return (b, a);
}
use q = Qubit();
let r = MResetZ(q);
mutable a = r == Zero ? 0 | 1;
mutable b = 2;
set (a, b) = Foo(a, b);
a
"#,
);
check_last_statement_compute_properties(
compilation_context.get_compute_properties(),
&expect![[r#"
ApplicationsGeneratorSet:
inherent: Quantum: QuantumProperties:
runtime_features: RuntimeFeatureFlags(UseOfDynamicBool | UseOfDynamicInt)
value_kind: Element(Dynamic)
dynamic_param_applications: <empty>"#]],
);
compilation_context.update(
r#"
b
"#,
);
check_last_statement_compute_properties(
compilation_context.get_compute_properties(),
&expect![[r#"
ApplicationsGeneratorSet:
inherent: Quantum: QuantumProperties:
runtime_features: RuntimeFeatureFlags(UseOfDynamicBool | UseOfDynamicInt)
value_kind: Element(Dynamic)
dynamic_param_applications: <empty>"#]],
);
}

0 comments on commit 597c39b

Please sign in to comment.