Skip to content

Commit bedd810

Browse files
authored
Unify implementations of custom measurements and custom resets (#1985)
This PR unifies the implementations of custom measurements and custom resets. It does two things: - Removes the `CallableKind::Measurement` variant from HIR and FIR. - Uses the `Attr::Measurement` to identify that a callable is a measurement.
1 parent 082cba5 commit bedd810

File tree

11 files changed

+32
-114
lines changed

11 files changed

+32
-114
lines changed

compiler/qsc_doc_gen/src/display.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ impl HirCallableDecl<'_> {
158158
fn get_param_offset(&self) -> u32 {
159159
let offset = match self.decl.kind {
160160
hir::CallableKind::Function => "function".len(),
161-
hir::CallableKind::Operation | hir::CallableKind::Measurement => "operation".len(),
161+
hir::CallableKind::Operation => "operation".len(),
162162
} + 1 // this is for the space between keyword and name
163163
+ self.decl.name.name.len()
164164
+ display_type_params(&self.decl.generics).len();
@@ -172,7 +172,7 @@ impl Display for HirCallableDecl<'_> {
172172
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
173173
let kind = match self.decl.kind {
174174
hir::CallableKind::Function => "function",
175-
hir::CallableKind::Operation | hir::CallableKind::Measurement => "operation",
175+
hir::CallableKind::Operation => "operation",
176176
};
177177

178178
write!(f, "{} {}", kind, self.decl.name.name)?;

compiler/qsc_doc_gen/src/generate_docs.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -426,7 +426,7 @@ fn get_metadata(
426426
display.hir_callable_decl(decl).to_string(),
427427
match &decl.kind {
428428
CallableKind::Function => MetadataKind::Function,
429-
CallableKind::Operation | CallableKind::Measurement => MetadataKind::Operation,
429+
CallableKind::Operation => MetadataKind::Operation,
430430
},
431431
)),
432432
ItemKind::Ty(ident, udt) => Some((

compiler/qsc_fir/src/fir.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1595,15 +1595,13 @@ pub enum CallableKind {
15951595
Function,
15961596
/// An operation.
15971597
Operation,
1598-
/// A measurement.
1599-
Measurement,
16001598
}
16011599

16021600
impl Display for CallableKind {
16031601
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
16041602
match self {
16051603
CallableKind::Function => f.write_str("function"),
1606-
CallableKind::Operation | CallableKind::Measurement => f.write_str("operation"),
1604+
CallableKind::Operation => f.write_str("operation"),
16071605
}
16081606
}
16091607
}

compiler/qsc_fir/src/ty.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -259,7 +259,7 @@ impl Display for Arrow {
259259
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
260260
let arrow = match self.kind {
261261
CallableKind::Function => "->",
262-
CallableKind::Operation | CallableKind::Measurement => "=>",
262+
CallableKind::Operation => "=>",
263263
};
264264
write!(f, "({} {arrow} {}", self.input, self.output)?;
265265
if self.functors != FunctorSet::Value(FunctorSetValue::Empty) {

compiler/qsc_frontend/src/lower.rs

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -466,13 +466,7 @@ impl With<'_> {
466466
self.check_invalid_attrs_on_function(attrs, span);
467467
hir::CallableKind::Function
468468
}
469-
ast::CallableKind::Operation => {
470-
if attrs.contains(&hir::Attr::Measurement) {
471-
hir::CallableKind::Measurement
472-
} else {
473-
hir::CallableKind::Operation
474-
}
475-
}
469+
ast::CallableKind::Operation => hir::CallableKind::Operation,
476470
}
477471
}
478472

compiler/qsc_hir/src/hir.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1445,15 +1445,13 @@ pub enum CallableKind {
14451445
Function,
14461446
/// An operation.
14471447
Operation,
1448-
/// A measurement.
1449-
Measurement,
14501448
}
14511449

14521450
impl Display for CallableKind {
14531451
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
14541452
match self {
14551453
CallableKind::Function => f.write_str("function"),
1456-
CallableKind::Operation | CallableKind::Measurement => f.write_str("operation"),
1454+
CallableKind::Operation => f.write_str("operation"),
14571455
}
14581456
}
14591457
}

compiler/qsc_hir/src/ty.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ impl Ty {
7373
Ty::Arrow(arrow) => {
7474
let arrow_symbol = match arrow.kind {
7575
CallableKind::Function => "->",
76-
CallableKind::Operation | CallableKind::Measurement => "=>",
76+
CallableKind::Operation => "=>",
7777
};
7878

7979
let functors = match arrow.functors {
@@ -370,7 +370,7 @@ impl Display for Arrow {
370370
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
371371
let arrow = match self.kind {
372372
CallableKind::Function => "->",
373-
CallableKind::Operation | CallableKind::Measurement => "=>",
373+
CallableKind::Operation => "=>",
374374
};
375375
write!(f, "({} {arrow} {}", self.input, self.output)?;
376376
if self.functors != FunctorSet::Value(FunctorSetValue::Empty) {

compiler/qsc_lowerer/src/lib.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -976,7 +976,6 @@ fn lower_callable_kind(kind: hir::CallableKind) -> fir::CallableKind {
976976
match kind {
977977
hir::CallableKind::Function => fir::CallableKind::Function,
978978
hir::CallableKind::Operation => fir::CallableKind::Operation,
979-
hir::CallableKind::Measurement => fir::CallableKind::Measurement,
980979
}
981980
}
982981

compiler/qsc_partial_eval/src/lib.rs

Lines changed: 21 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,7 @@ impl<'a> PartialEvaluator<'a> {
258258
&self,
259259
store_item_id: StoreItemId,
260260
callable_decl: &CallableDecl,
261+
call_type: CallableType,
261262
) -> Callable {
262263
let callable_package = self.package_store.get(store_item_id.package);
263264
let name = callable_decl.name.name.to_string();
@@ -275,7 +276,7 @@ impl<'a> PartialEvaluator<'a> {
275276
let call_type = if name.eq("__quantum__qis__reset__body") {
276277
CallableType::Reset
277278
} else {
278-
CallableType::Regular
279+
call_type
279280
};
280281
Callable {
281282
name,
@@ -1310,11 +1311,17 @@ impl<'a> PartialEvaluator<'a> {
13101311
args_span: PackageSpan, // For diagnostic purposes only.
13111312
callee_expr_span: PackageSpan, // For diagnostic puprposes only.
13121313
) -> Result<Value, Error> {
1313-
if matches!(callable_decl.kind, qsc_fir::fir::CallableKind::Measurement) {
1314-
return self.measure_qubits(callable_decl, args_value, args_span);
1314+
if callable_decl.attrs.contains(&fir::Attr::Measurement) {
1315+
return Ok(self.measure_qubits(callable_decl, args_value));
13151316
}
13161317
if callable_decl.attrs.contains(&fir::Attr::Reset) {
1317-
return self.reset_qubits(store_item_id, callable_decl, args_value);
1318+
return self.eval_expr_call_to_intrinsic_qis(
1319+
store_item_id,
1320+
callable_decl,
1321+
args_value,
1322+
callee_expr_span,
1323+
CallableType::Reset,
1324+
);
13181325
}
13191326

13201327
// There are a few special cases regarding intrinsic callables. Identify them and handle them properly.
@@ -1354,6 +1361,7 @@ impl<'a> PartialEvaluator<'a> {
13541361
callable_decl,
13551362
args_value,
13561363
callee_expr_span,
1364+
CallableType::Regular,
13571365
),
13581366
}
13591367
}
@@ -1364,6 +1372,7 @@ impl<'a> PartialEvaluator<'a> {
13641372
callable_decl: &CallableDecl,
13651373
args_value: Value,
13661374
callee_expr_span: PackageSpan,
1375+
call_type: CallableType,
13671376
) -> Result<Value, Error> {
13681377
// Intrinsic callables that make it to this point are expected to be unitary.
13691378
if callable_decl.output != Ty::UNIT {
@@ -1377,7 +1386,7 @@ impl<'a> PartialEvaluator<'a> {
13771386
}
13781387

13791388
// Check if the callable is already in the program, and if not add it.
1380-
let callable = self.create_intrinsic_callable(store_item_id, callable_decl);
1389+
let callable = self.create_intrinsic_callable(store_item_id, callable_decl, call_type);
13811390
let callable_id = self.get_or_insert_callable(callable);
13821391

13831392
// Resove the call arguments, create the call instruction and insert it to the current block.
@@ -2267,12 +2276,7 @@ impl<'a> PartialEvaluator<'a> {
22672276
Value::Qubit(qubit)
22682277
}
22692278

2270-
fn measure_qubits(
2271-
&mut self,
2272-
callable_decl: &CallableDecl,
2273-
args_value: Value,
2274-
args_span: PackageSpan, // For diagnostic purposes only.
2275-
) -> Result<Value, Error> {
2279+
fn measure_qubits(&mut self, callable_decl: &CallableDecl, args_value: Value) -> Value {
22762280
let mut input_type = Vec::new();
22772281
let mut operands = Vec::new();
22782282
let mut results_values = Vec::new();
@@ -2285,20 +2289,14 @@ impl<'a> PartialEvaluator<'a> {
22852289
Value::Tuple(values) => {
22862290
for value in &*values {
22872291
let Value::Qubit(qubit) = value else {
2288-
return Err(Error::EvaluationFailed(
2289-
"the arguments of a measurement should be Qubits".to_string(),
2290-
args_span,
2291-
));
2292+
panic!("by this point a qsc_pass should have checked that all arguments are Qubits")
22922293
};
22932294
input_type.push(qsc_rir::rir::Ty::Qubit);
22942295
operands.push(self.map_eval_value_to_rir_operand(&Value::Qubit(*qubit)));
22952296
}
22962297
}
22972298
_ => {
2298-
return Err(Error::EvaluationFailed(
2299-
"the arguments of a measurement should be Qubits".to_string(),
2300-
args_span,
2301-
))
2299+
panic!("by this point a qsc_pass should have checked that all arguments are Qubits")
23022300
}
23032301
}
23042302

@@ -2320,18 +2318,12 @@ impl<'a> PartialEvaluator<'a> {
23202318
operands.push(result_operand);
23212319
results_values.push(result_value);
23222320
} else {
2323-
return Err(Error::EvaluationFailed(
2324-
"the arguments of a measurement should be Qubits".to_string(),
2325-
args_span,
2326-
));
2321+
panic!("by this point a qsc_pass should have checked that all outputs are Results")
23272322
}
23282323
}
23292324
}
23302325
_ => {
2331-
return Err(Error::EvaluationFailed(
2332-
"the outputs of a measurement should be Results".to_string(),
2333-
args_span,
2334-
));
2326+
panic!("by this point a qsc_pass should have checked that all outputs are Results")
23352327
}
23362328
}
23372329

@@ -2351,8 +2343,8 @@ impl<'a> PartialEvaluator<'a> {
23512343

23522344
match results_values.len() {
23532345
0 => panic!("unexpected unitary measurement"),
2354-
1 => Ok(results_values[0].clone()),
2355-
2.. => Ok(Value::Tuple(results_values.into())),
2346+
1 => results_values[0].clone(),
2347+
2.. => Value::Tuple(results_values.into()),
23562348
}
23572349
}
23582350

@@ -2375,60 +2367,6 @@ impl<'a> PartialEvaluator<'a> {
23752367
result_value
23762368
}
23772369

2378-
fn reset_qubits(
2379-
&mut self,
2380-
store_item_id: StoreItemId,
2381-
callable_decl: &CallableDecl,
2382-
args_value: Value,
2383-
) -> Result<Value, Error> {
2384-
let callable_package = self.package_store.get(store_item_id.package);
2385-
let input_type: Vec<rir::Ty> = callable_package
2386-
.derive_callable_input_params(callable_decl)
2387-
.iter()
2388-
.map(|input_param| map_fir_type_to_rir_type(&input_param.ty))
2389-
.collect();
2390-
let output_type = if callable_decl.output == Ty::UNIT {
2391-
None
2392-
} else {
2393-
panic!("the expressions that make it to this point should return Unit");
2394-
};
2395-
2396-
let measurement_callable = Callable {
2397-
name: callable_decl.name.name.to_string(),
2398-
input_type,
2399-
output_type,
2400-
body: None,
2401-
call_type: CallableType::Reset,
2402-
};
2403-
2404-
// Resolve the call arguments, create the call instruction and insert it to the current block.
2405-
let (args, ctls_arg) = self
2406-
.resolve_args(
2407-
(store_item_id.package, callable_decl.input).into(),
2408-
args_value,
2409-
None,
2410-
None,
2411-
None,
2412-
)
2413-
.expect("no controls to verify");
2414-
assert!(
2415-
ctls_arg.is_none(),
2416-
"intrinsic operations cannot have controls"
2417-
);
2418-
let operands = args
2419-
.into_iter()
2420-
.map(|arg| self.map_eval_value_to_rir_operand(&arg.into_value()))
2421-
.collect();
2422-
2423-
// Check if the callable has already been added to the program and if not do so now.
2424-
let measure_callable_id = self.get_or_insert_callable(measurement_callable);
2425-
let instruction = Instruction::Call(measure_callable_id, operands, None);
2426-
let current_block = self.get_current_rir_block_mut();
2427-
current_block.0.push(instruction);
2428-
2429-
Ok(Value::unit())
2430-
}
2431-
24322370
fn release_qubit(&mut self, args_value: Value) -> Value {
24332371
let qubit = args_value.unwrap_qubit();
24342372
self.resource_manager.release_qubit(qubit);

compiler/qsc_rca/src/core.rs

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1156,7 +1156,7 @@ impl<'a> Analyzer<'a> {
11561156
CallableKind::Function => {
11571157
derive_intrinsic_function_application_generator_set(callable_context)
11581158
}
1159-
CallableKind::Operation | CallableKind::Measurement => {
1159+
CallableKind::Operation => {
11601160
derive_instrinsic_operation_application_generator_set(callable_context)
11611161
}
11621162
};
@@ -2248,10 +2248,7 @@ fn array_param_application_from_runtime_features(
22482248
fn derive_instrinsic_operation_application_generator_set(
22492249
callable_context: &CallableContext,
22502250
) -> ApplicationGeneratorSet {
2251-
assert!(matches!(
2252-
callable_context.kind,
2253-
CallableKind::Operation | CallableKind::Measurement
2254-
));
2251+
assert!(matches!(callable_context.kind, CallableKind::Operation));
22552252

22562253
// The value kind of intrinsic operations is inherently dynamic if their output is not `Unit` or `Qubit`.
22572254
let value_kind = if callable_context.output_type == Ty::UNIT
@@ -2398,9 +2395,6 @@ fn derive_runtime_features_for_value_kind_associated_to_type(
23982395
match arrow.kind {
23992396
CallableKind::Function => RuntimeFeatureFlags::UseOfDynamicArrowFunction,
24002397
CallableKind::Operation => RuntimeFeatureFlags::UseOfDynamicArrowOperation,
2401-
CallableKind::Measurement => {
2402-
panic!("measurements are intrinsics, and arrow kinds cannot be intrinsics");
2403-
}
24042398
}
24052399
}
24062400

0 commit comments

Comments
 (0)