microsoft/qdk

Public

mirrored from https://github.com/microsoft/qdkAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
v1.1.3

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

compiler/qsc/src/interpret/tests.rs

1311lines · modecode

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4#![allow(clippy::needless_raw_string_hashes)]
5
6mod given_interpreter {
7 use crate::interpret::{Error, InterpretResult, Interpreter};
8 use expect_test::Expect;
9 use miette::Diagnostic;
10 use qsc_eval::{output::CursorReceiver, val::Value};
11 use qsc_frontend::compile::{RuntimeCapabilityFlags, SourceMap};
12 use qsc_passes::PackageType;
13 use std::{fmt::Write, io::Cursor, iter, str::from_utf8};
14
15 fn line(interpreter: &mut Interpreter, line: &str) -> (InterpretResult, String) {
16 let mut cursor = Cursor::new(Vec::<u8>::new());
17 let mut receiver = CursorReceiver::new(&mut cursor);
18 (
19 interpreter.eval_fragments(&mut receiver, line),
20 receiver.dump(),
21 )
22 }
23
24 fn run(
25 interpreter: &mut Interpreter,
26 expr: &str,
27 ) -> (Result<InterpretResult, Vec<Error>>, String) {
28 let mut cursor = Cursor::new(Vec::<u8>::new());
29 let mut receiver = CursorReceiver::new(&mut cursor);
30 (interpreter.run(&mut receiver, expr), receiver.dump())
31 }
32
33 fn entry(
34 interpreter: &mut Interpreter,
35 ) -> (Result<Value, Vec<crate::interpret::Error>>, String) {
36 let mut cursor = Cursor::new(Vec::<u8>::new());
37 let mut receiver = CursorReceiver::new(&mut cursor);
38 (interpreter.eval_entry(&mut receiver), receiver.dump())
39 }
40
41 mod without_sources {
42 use expect_test::expect;
43 use indoc::indoc;
44 use qsc_frontend::compile::RuntimeCapabilityFlags;
45
46 use super::*;
47
48 mod without_stdlib {
49 use qsc_frontend::compile::SourceMap;
50 use qsc_passes::PackageType;
51
52 use super::*;
53
54 #[test]
55 fn stdlib_members_should_be_unavailable() {
56 let mut interpreter = Interpreter::new(
57 false,
58 SourceMap::default(),
59 PackageType::Lib,
60 RuntimeCapabilityFlags::all(),
61 )
62 .expect("interpreter should be created");
63
64 let (result, output) = line(&mut interpreter, "Message(\"_\")");
65 is_only_error(
66 &result,
67 &output,
68 &expect![[r#"
69 name error: `Message` not found
70 [line_0] [Message]
71 type error: insufficient type information to infer type
72 [line_0] [Message("_")]
73 "#]],
74 );
75 }
76 }
77
78 #[test]
79 fn stdlib_members_should_be_available() {
80 let mut interpreter = get_interpreter();
81 let (result, output) = line(&mut interpreter, "Message(\"_\")");
82 is_unit_with_output(&result, &output, "_");
83 }
84
85 #[test]
86 fn core_members_should_be_available() {
87 let mut interpreter = get_interpreter();
88 let (result, output) = line(&mut interpreter, "Length([1, 2, 3])");
89 is_only_value(&result, &output, &Value::Int(3));
90 }
91
92 #[test]
93 fn let_bindings_update_interpreter() {
94 let mut interpreter = get_interpreter();
95 line(&mut interpreter, "let y = 7;")
96 .0
97 .expect("line should succeed");
98 let (result, output) = line(&mut interpreter, "y");
99 is_only_value(&result, &output, &Value::Int(7));
100 }
101
102 #[test]
103 fn let_bindings_can_be_shadowed() {
104 let mut interpreter = get_interpreter();
105
106 let (result, output) = line(&mut interpreter, "let y = 7;");
107 is_only_value(&result, &output, &Value::unit());
108
109 let (result, output) = line(&mut interpreter, "y");
110 is_only_value(&result, &output, &Value::Int(7));
111
112 let (result, output) = line(&mut interpreter, "let y = \"Hello\";");
113 is_only_value(&result, &output, &Value::unit());
114
115 let (result, output) = line(&mut interpreter, "y");
116 is_only_value(&result, &output, &Value::String("Hello".into()));
117 }
118
119 #[test]
120 fn invalid_statements_return_error() {
121 let mut interpreter = get_interpreter();
122
123 let (result, output) = line(&mut interpreter, "let y = 7");
124 is_only_error(
125 &result,
126 &output,
127 &expect![[r#"
128 syntax error: expected `;`, found EOF
129 [line_0] []
130 "#]],
131 );
132
133 let (result, output) = line(&mut interpreter, "y");
134 is_only_error(
135 &result,
136 &output,
137 &expect![[r#"
138 name error: `y` not found
139 [line_1] [y]
140 "#]],
141 );
142 }
143
144 #[test]
145 fn invalid_statements_and_unbound_vars_return_error() {
146 let mut interpreter = get_interpreter();
147
148 let (result, output) = line(&mut interpreter, "let y = x;");
149 is_only_error(
150 &result,
151 &output,
152 &expect![[r#"
153 name error: `x` not found
154 [line_0] [x]
155 type error: insufficient type information to infer type
156 [line_0] [y]
157 "#]],
158 );
159
160 let (result, output) = line(&mut interpreter, "y");
161 is_only_error(
162 &result,
163 &output,
164 &expect![[r#"
165 runtime error: name is not bound
166 [line_1] [y]
167 "#]],
168 );
169 }
170
171 #[test]
172 fn failing_statements_return_early_error() {
173 let mut interpreter = get_interpreter();
174 let (result, output) = line(&mut interpreter, "let y = 7;y/0;y");
175 is_only_error(
176 &result,
177 &output,
178 &expect![[r#"
179 runtime error: division by zero
180 cannot divide by zero [line_0] [0]
181 "#]],
182 );
183 }
184
185 #[test]
186 fn passes_are_run_on_incremental() {
187 let mut interpreter = get_interpreter();
188 let (result, output) = line(
189 &mut interpreter,
190 "within {Message(\"A\");} apply {Message(\"B\");}",
191 );
192 is_unit_with_output(&result, &output, "A\nB\nA");
193 }
194
195 #[test]
196 fn declare_function() {
197 let mut interpreter = get_interpreter();
198 let (result, output) = line(&mut interpreter, "function Foo() : Int { 2 }");
199 is_only_value(&result, &output, &Value::unit());
200 let (result, output) = line(&mut interpreter, "Foo()");
201 is_only_value(&result, &output, &Value::Int(2));
202 }
203
204 #[test]
205 fn invalid_declare_function_and_unbound_call_return_error() {
206 let mut interpreter = get_interpreter();
207 let (result, output) = line(&mut interpreter, "function Foo() : Int { invalid }");
208 is_only_error(
209 &result,
210 &output,
211 &expect![[r#"
212 name error: `invalid` not found
213 [line_0] [invalid]
214 "#]],
215 );
216 let (result, output) = line(&mut interpreter, "Foo()");
217 is_only_error(
218 &result,
219 &output,
220 &expect![[r#"
221 runtime error: name is not bound
222 [line_1] [Foo]
223 "#]],
224 );
225 }
226
227 #[test]
228 fn declare_function_call_same_line() {
229 let mut interpreter = get_interpreter();
230 let (result, output) = line(&mut interpreter, "function Foo() : Int { 2 }; Foo()");
231 is_only_value(&result, &output, &Value::Int(2));
232 }
233
234 #[test]
235 fn let_binding_function_declaration_call_same_line() {
236 let mut interpreter = get_interpreter();
237 let (result, output) = line(
238 &mut interpreter,
239 "let x = 1; function Foo() : Int { 2 }; Foo() + 1",
240 );
241 is_only_value(&result, &output, &Value::Int(3));
242 }
243
244 #[test]
245 fn nested_function() {
246 let mut interpreter = get_interpreter();
247 let (result, output) = line(
248 &mut interpreter,
249 "function Foo() : Int { function Bar() : Int { 1 }; Bar() + 1 }; Foo() + 1",
250 );
251 is_only_value(&result, &output, &Value::Int(3));
252 }
253
254 #[test]
255 fn open_namespace() {
256 let mut interpreter = get_interpreter();
257 let (result, output) = line(&mut interpreter, "open Microsoft.Quantum.Diagnostics;");
258 is_only_value(&result, &output, &Value::unit());
259 let (result, output) = line(&mut interpreter, "DumpMachine()");
260 is_unit_with_output(&result, &output, "STATE:\n|0⟩: 1+0i");
261 }
262
263 #[test]
264 fn open_namespace_call_same_line() {
265 let mut interpreter = get_interpreter();
266 let (result, output) = line(
267 &mut interpreter,
268 "open Microsoft.Quantum.Diagnostics; DumpMachine()",
269 );
270 is_unit_with_output(&result, &output, "STATE:\n|0⟩: 1+0i");
271 }
272
273 #[test]
274 fn declare_namespace_call() {
275 let mut interpreter = get_interpreter();
276 let (result, output) = line(
277 &mut interpreter,
278 "namespace Foo { function Bar() : Int { 5 } }",
279 );
280 is_only_value(&result, &output, &Value::unit());
281 let (result, output) = line(&mut interpreter, "Foo.Bar()");
282 is_only_value(&result, &output, &Value::Int(5));
283 }
284
285 #[test]
286 fn declare_namespace_open_call() {
287 let mut interpreter = get_interpreter();
288 let (result, output) = line(
289 &mut interpreter,
290 "namespace Foo { function Bar() : Int { 5 } }",
291 );
292 is_only_value(&result, &output, &Value::unit());
293 let (result, output) = line(&mut interpreter, "open Foo;");
294 is_only_value(&result, &output, &Value::unit());
295 let (result, output) = line(&mut interpreter, "Bar()");
296 is_only_value(&result, &output, &Value::Int(5));
297 }
298
299 #[test]
300 fn declare_namespace_open_call_same_line() {
301 let mut interpreter = get_interpreter();
302 let (result, output) = line(
303 &mut interpreter,
304 "namespace Foo { function Bar() : Int { 5 } } open Foo; Bar()",
305 );
306 is_only_value(&result, &output, &Value::Int(5));
307 }
308
309 #[test]
310 fn mix_stmts_and_namespace_same_line() {
311 let mut interpreter = get_interpreter();
312 let (result, output) = line(
313 &mut interpreter,
314 "Message(\"before\"); namespace Foo { function Bar() : Int { 5 } } Message(\"after\")",
315 );
316 is_unit_with_output(&result, &output, "before\nafter");
317 }
318
319 #[test]
320 fn global_qubits() {
321 let mut interpreter = get_interpreter();
322 let (result, output) = line(&mut interpreter, "open Microsoft.Quantum.Diagnostics;");
323 is_only_value(&result, &output, &Value::unit());
324 let (result, output) = line(&mut interpreter, "DumpMachine()");
325 is_unit_with_output(&result, &output, "STATE:\n|0⟩: 1+0i");
326 let (result, output) = line(&mut interpreter, "use (q0, qs) = (Qubit(), Qubit[3]);");
327 is_only_value(&result, &output, &Value::unit());
328 let (result, output) = line(&mut interpreter, "DumpMachine()");
329 is_unit_with_output(&result, &output, "STATE:\n|0000⟩: 1+0i");
330 let (result, output) = line(&mut interpreter, "X(q0); X(qs[1]);");
331 is_only_value(&result, &output, &Value::unit());
332 let (result, output) = line(&mut interpreter, "DumpMachine()");
333 is_unit_with_output(&result, &output, "STATE:\n|1010⟩: 1+0i");
334 }
335
336 #[test]
337 fn ambiguous_type_error_in_top_level_stmts() {
338 let mut interpreter = get_interpreter();
339 let (result, output) = line(&mut interpreter, "let x = [];");
340 is_only_error(
341 &result,
342 &output,
343 &expect![[r#"
344 type error: insufficient type information to infer type
345 [line_0] [[]]
346 "#]],
347 );
348 let (result, output) = line(&mut interpreter, "let x = []; let y = [0] + x;");
349 is_only_value(&result, &output, &Value::unit());
350 let (result, output) = line(&mut interpreter, "function Foo() : Unit { let x = []; }");
351 is_only_error(
352 &result,
353 &output,
354 &expect![[r#"
355 type error: insufficient type information to infer type
356 [line_2] [[]]
357 "#]],
358 );
359 }
360
361 #[test]
362 fn resolved_type_persists_across_stmts() {
363 let mut interpreter = get_interpreter();
364 let (result, output) = line(&mut interpreter, "let x = []; let y = [0] + x;");
365 is_only_value(&result, &output, &Value::unit());
366 let (result, output) = line(&mut interpreter, "let z = [0.0] + x;");
367 is_only_error(
368 &result,
369 &output,
370 &expect![[r#"
371 type error: expected Double, found Int
372 [line_1] [x]
373 "#]],
374 );
375 }
376
377 #[test]
378 fn incremental_lambas_work() {
379 let mut interpreter = get_interpreter();
380 let (result, output) = line(&mut interpreter, "let x = 1; let f = (y) -> x + y;");
381 is_only_value(&result, &output, &Value::unit());
382 let (result, output) = line(&mut interpreter, "f(1)");
383 is_only_value(&result, &output, &Value::Int(2));
384 }
385
386 #[test]
387 fn mutability_persists_across_stmts() {
388 let mut interpreter = get_interpreter();
389 let (result, output) = line(
390 &mut interpreter,
391 "mutable x : Int[] = []; let y : Int[] = [];",
392 );
393 is_only_value(&result, &output, &Value::unit());
394 let (result, output) = line(&mut interpreter, "set x += [0];");
395 is_only_value(&result, &output, &Value::unit());
396 let (result, output) = line(&mut interpreter, "set y += [0];");
397 is_only_error(
398 &result,
399 &output,
400 &expect![[r#"
401 cannot update immutable variable
402 [line_2] [y]
403 "#]],
404 );
405 let (result, output) = line(&mut interpreter, "let lam = () -> y + [0];");
406 is_only_value(&result, &output, &Value::unit());
407 let (result, output) = line(&mut interpreter, "let lam = () -> x + [0];");
408 is_only_error(
409 &result,
410 &output,
411 &expect![[r#"
412 lambdas cannot close over mutable variables
413 [line_4] [() -> x + [0]]
414 "#]],
415 );
416 }
417
418 #[test]
419 fn runtime_error_across_lines() {
420 let mut interpreter = get_interpreter();
421 let (result, output) = line(
422 &mut interpreter,
423 "operation Main() : Unit { Microsoft.Quantum.Random.DrawRandomInt(2,1); }",
424 );
425 is_only_value(&result, &output, &Value::unit());
426 let (result, output) = line(&mut interpreter, "Main()");
427 is_only_error(
428 &result,
429 &output,
430 &expect![[r#"
431 runtime error: empty range
432 the range cannot be empty [line_0] [(2,1)]
433 "#]],
434 );
435 }
436
437 #[test]
438 fn compiler_error_across_lines() {
439 let mut interpreter = get_interpreter();
440 let (result, output) = line(
441 &mut interpreter,
442 "namespace Other { operation DumpMachine() : Unit { } }",
443 );
444 is_only_value(&result, &output, &Value::unit());
445 let (result, output) = line(&mut interpreter, "open Other;");
446 is_only_value(&result, &output, &Value::unit());
447 let (result, output) = line(&mut interpreter, "open Microsoft.Quantum.Diagnostics;");
448 is_only_value(&result, &output, &Value::unit());
449 let (result, output) = line(&mut interpreter, "DumpMachine();");
450 is_only_error(
451 &result,
452 &output,
453 &expect![[r#"
454 name error: `DumpMachine` could refer to the item in `Other` or `Microsoft.Quantum.Diagnostics`
455 ambiguous name [line_3] [DumpMachine]
456 found in this namespace [line_1] [Other]
457 and also in this namespace [line_2] [Microsoft.Quantum.Diagnostics]
458 type error: insufficient type information to infer type
459 [line_3] [DumpMachine()]
460 "#]],
461 );
462 }
463
464 #[test]
465 fn runtime_error_from_stdlib() {
466 let mut interpreter = get_interpreter();
467 let (result, output) = line(&mut interpreter, "use q = Qubit(); CNOT(q,q)");
468 is_only_error(
469 &result,
470 &output,
471 &expect![[r#"
472 runtime error: qubits in gate invocation are not unique
473 [intrinsic.qs] [(control, target)]
474 "#]],
475 );
476 }
477
478 #[test]
479 fn items_usable_before_definition() {
480 let mut interpreter = get_interpreter();
481 let (result, output) = line(
482 &mut interpreter,
483 indoc! {r#"
484 function A() : Unit {
485 B();
486 }
487 function B() : Unit {}
488 A()
489 "#},
490 );
491 is_only_value(&result, &output, &Value::unit());
492 }
493
494 #[test]
495 fn items_usable_before_definition_top_level() {
496 let mut interpreter = get_interpreter();
497 let (result, output) = line(
498 &mut interpreter,
499 indoc! {r#"
500 B();
501 function B() : Unit {}
502 "#},
503 );
504 is_only_value(&result, &output, &Value::unit());
505 }
506
507 #[test]
508 fn namespace_usable_before_definition() {
509 let mut interpreter = get_interpreter();
510 let (result, output) = line(
511 &mut interpreter,
512 indoc! {r#"
513 A.B();
514 namespace A {
515 function B() : Unit {}
516 }
517 "#},
518 );
519 is_only_value(&result, &output, &Value::unit());
520 }
521
522 #[test]
523 fn mutually_recursive_namespaces_work() {
524 let mut interpreter = get_interpreter();
525 let (result, output) = line(
526 &mut interpreter,
527 indoc! {r#"
528 A.B();
529 namespace A {
530 open C;
531 function B() : Unit {
532 D();
533 }
534 function E() : Unit {}
535 }
536 namespace C {
537 open A;
538 function D() : Unit {
539 E();
540 }
541 }
542 "#},
543 );
544 is_only_value(&result, &output, &Value::unit());
545 }
546
547 #[test]
548 fn normal_qirgen() {
549 let mut interpreter = Interpreter::new(
550 true,
551 SourceMap::default(),
552 PackageType::Lib,
553 RuntimeCapabilityFlags::empty(),
554 )
555 .expect("interpreter should be created");
556 let (result, output) = line(
557 &mut interpreter,
558 indoc! {"operation Foo() : Result { use q = Qubit(); let r = M(q); Reset(q); return r; } "},
559 );
560 is_only_value(&result, &output, &Value::unit());
561 let res = interpreter.qirgen("Foo()").expect("expected success");
562 expect![[r#"
563 %Result = type opaque
564 %Qubit = type opaque
565
566 define void @ENTRYPOINT__main() #0 {
567 call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 1 to %Qubit*))
568 call void @__quantum__qis__cz__body(%Qubit* inttoptr (i64 1 to %Qubit*), %Qubit* inttoptr (i64 0 to %Qubit*))
569 call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 1 to %Qubit*))
570 call void @__quantum__qis__mz__body(%Qubit* inttoptr (i64 1 to %Qubit*), %Result* inttoptr (i64 0 to %Result*)) #1
571 call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 0 to %Result*), i8* null)
572 ret void
573 }
574
575 declare void @__quantum__qis__ccx__body(%Qubit*, %Qubit*, %Qubit*)
576 declare void @__quantum__qis__cx__body(%Qubit*, %Qubit*)
577 declare void @__quantum__qis__cy__body(%Qubit*, %Qubit*)
578 declare void @__quantum__qis__cz__body(%Qubit*, %Qubit*)
579 declare void @__quantum__qis__rx__body(double, %Qubit*)
580 declare void @__quantum__qis__rxx__body(double, %Qubit*, %Qubit*)
581 declare void @__quantum__qis__ry__body(double, %Qubit*)
582 declare void @__quantum__qis__ryy__body(double, %Qubit*, %Qubit*)
583 declare void @__quantum__qis__rz__body(double, %Qubit*)
584 declare void @__quantum__qis__rzz__body(double, %Qubit*, %Qubit*)
585 declare void @__quantum__qis__h__body(%Qubit*)
586 declare void @__quantum__qis__s__body(%Qubit*)
587 declare void @__quantum__qis__s__adj(%Qubit*)
588 declare void @__quantum__qis__t__body(%Qubit*)
589 declare void @__quantum__qis__t__adj(%Qubit*)
590 declare void @__quantum__qis__x__body(%Qubit*)
591 declare void @__quantum__qis__y__body(%Qubit*)
592 declare void @__quantum__qis__z__body(%Qubit*)
593 declare void @__quantum__qis__swap__body(%Qubit*, %Qubit*)
594 declare void @__quantum__qis__mz__body(%Qubit*, %Result* writeonly) #1
595 declare void @__quantum__rt__result_record_output(%Result*, i8*)
596 declare void @__quantum__rt__array_record_output(i64, i8*)
597 declare void @__quantum__rt__tuple_record_output(i64, i8*)
598
599 attributes #0 = { "entry_point" "output_labeling_schema" "qir_profiles"="base_profile" "required_num_qubits"="2" "required_num_results"="1" }
600 attributes #1 = { "irreversible" }
601
602 ; module flags
603
604 !llvm.module.flags = !{!0, !1, !2, !3}
605
606 !0 = !{i32 1, !"qir_major_version", i32 1}
607 !1 = !{i32 7, !"qir_minor_version", i32 0}
608 !2 = !{i32 1, !"dynamic_qubit_management", i1 false}
609 !3 = !{i32 1, !"dynamic_result_management", i1 false}
610 "#]].assert_eq(&res);
611 }
612
613 #[test]
614 fn qirgen_entry_expr_in_block() {
615 let mut interpreter = Interpreter::new(
616 true,
617 SourceMap::default(),
618 PackageType::Lib,
619 RuntimeCapabilityFlags::empty(),
620 )
621 .expect("interpreter should be created");
622 let (result, output) = line(
623 &mut interpreter,
624 indoc! {"operation Foo() : Result { use q = Qubit(); let r = M(q); Reset(q); return r; } "},
625 );
626 is_only_value(&result, &output, &Value::unit());
627 let res = interpreter.qirgen("{Foo()}").expect("expected success");
628 expect![[r#"
629 %Result = type opaque
630 %Qubit = type opaque
631
632 define void @ENTRYPOINT__main() #0 {
633 call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 1 to %Qubit*))
634 call void @__quantum__qis__cz__body(%Qubit* inttoptr (i64 1 to %Qubit*), %Qubit* inttoptr (i64 0 to %Qubit*))
635 call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 1 to %Qubit*))
636 call void @__quantum__qis__mz__body(%Qubit* inttoptr (i64 1 to %Qubit*), %Result* inttoptr (i64 0 to %Result*)) #1
637 call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 0 to %Result*), i8* null)
638 ret void
639 }
640
641 declare void @__quantum__qis__ccx__body(%Qubit*, %Qubit*, %Qubit*)
642 declare void @__quantum__qis__cx__body(%Qubit*, %Qubit*)
643 declare void @__quantum__qis__cy__body(%Qubit*, %Qubit*)
644 declare void @__quantum__qis__cz__body(%Qubit*, %Qubit*)
645 declare void @__quantum__qis__rx__body(double, %Qubit*)
646 declare void @__quantum__qis__rxx__body(double, %Qubit*, %Qubit*)
647 declare void @__quantum__qis__ry__body(double, %Qubit*)
648 declare void @__quantum__qis__ryy__body(double, %Qubit*, %Qubit*)
649 declare void @__quantum__qis__rz__body(double, %Qubit*)
650 declare void @__quantum__qis__rzz__body(double, %Qubit*, %Qubit*)
651 declare void @__quantum__qis__h__body(%Qubit*)
652 declare void @__quantum__qis__s__body(%Qubit*)
653 declare void @__quantum__qis__s__adj(%Qubit*)
654 declare void @__quantum__qis__t__body(%Qubit*)
655 declare void @__quantum__qis__t__adj(%Qubit*)
656 declare void @__quantum__qis__x__body(%Qubit*)
657 declare void @__quantum__qis__y__body(%Qubit*)
658 declare void @__quantum__qis__z__body(%Qubit*)
659 declare void @__quantum__qis__swap__body(%Qubit*, %Qubit*)
660 declare void @__quantum__qis__mz__body(%Qubit*, %Result* writeonly) #1
661 declare void @__quantum__rt__result_record_output(%Result*, i8*)
662 declare void @__quantum__rt__array_record_output(i64, i8*)
663 declare void @__quantum__rt__tuple_record_output(i64, i8*)
664
665 attributes #0 = { "entry_point" "output_labeling_schema" "qir_profiles"="base_profile" "required_num_qubits"="2" "required_num_results"="1" }
666 attributes #1 = { "irreversible" }
667
668 ; module flags
669
670 !llvm.module.flags = !{!0, !1, !2, !3}
671
672 !0 = !{i32 1, !"qir_major_version", i32 1}
673 !1 = !{i32 7, !"qir_minor_version", i32 0}
674 !2 = !{i32 1, !"dynamic_qubit_management", i1 false}
675 !3 = !{i32 1, !"dynamic_result_management", i1 false}
676 "#]].assert_eq(&res);
677 }
678
679 #[test]
680 fn qirgen_entry_expr_defines_operation() {
681 let mut interpreter = Interpreter::new(
682 true,
683 SourceMap::default(),
684 PackageType::Lib,
685 RuntimeCapabilityFlags::empty(),
686 )
687 .expect("interpreter should be created");
688 let (result, output) = line(
689 &mut interpreter,
690 indoc! {"operation Foo() : Result { use q = Qubit(); let r = M(q); Reset(q); return r; } "},
691 );
692 is_only_value(&result, &output, &Value::unit());
693 let res = interpreter
694 .qirgen("{operation Bar() : Unit {}; Foo()}")
695 .expect("expected success");
696 expect![[r#"
697 %Result = type opaque
698 %Qubit = type opaque
699
700 define void @ENTRYPOINT__main() #0 {
701 call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 1 to %Qubit*))
702 call void @__quantum__qis__cz__body(%Qubit* inttoptr (i64 1 to %Qubit*), %Qubit* inttoptr (i64 0 to %Qubit*))
703 call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 1 to %Qubit*))
704 call void @__quantum__qis__mz__body(%Qubit* inttoptr (i64 1 to %Qubit*), %Result* inttoptr (i64 0 to %Result*)) #1
705 call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 0 to %Result*), i8* null)
706 ret void
707 }
708
709 declare void @__quantum__qis__ccx__body(%Qubit*, %Qubit*, %Qubit*)
710 declare void @__quantum__qis__cx__body(%Qubit*, %Qubit*)
711 declare void @__quantum__qis__cy__body(%Qubit*, %Qubit*)
712 declare void @__quantum__qis__cz__body(%Qubit*, %Qubit*)
713 declare void @__quantum__qis__rx__body(double, %Qubit*)
714 declare void @__quantum__qis__rxx__body(double, %Qubit*, %Qubit*)
715 declare void @__quantum__qis__ry__body(double, %Qubit*)
716 declare void @__quantum__qis__ryy__body(double, %Qubit*, %Qubit*)
717 declare void @__quantum__qis__rz__body(double, %Qubit*)
718 declare void @__quantum__qis__rzz__body(double, %Qubit*, %Qubit*)
719 declare void @__quantum__qis__h__body(%Qubit*)
720 declare void @__quantum__qis__s__body(%Qubit*)
721 declare void @__quantum__qis__s__adj(%Qubit*)
722 declare void @__quantum__qis__t__body(%Qubit*)
723 declare void @__quantum__qis__t__adj(%Qubit*)
724 declare void @__quantum__qis__x__body(%Qubit*)
725 declare void @__quantum__qis__y__body(%Qubit*)
726 declare void @__quantum__qis__z__body(%Qubit*)
727 declare void @__quantum__qis__swap__body(%Qubit*, %Qubit*)
728 declare void @__quantum__qis__mz__body(%Qubit*, %Result* writeonly) #1
729 declare void @__quantum__rt__result_record_output(%Result*, i8*)
730 declare void @__quantum__rt__array_record_output(i64, i8*)
731 declare void @__quantum__rt__tuple_record_output(i64, i8*)
732
733 attributes #0 = { "entry_point" "output_labeling_schema" "qir_profiles"="base_profile" "required_num_qubits"="2" "required_num_results"="1" }
734 attributes #1 = { "irreversible" }
735
736 ; module flags
737
738 !llvm.module.flags = !{!0, !1, !2, !3}
739
740 !0 = !{i32 1, !"qir_major_version", i32 1}
741 !1 = !{i32 7, !"qir_minor_version", i32 0}
742 !2 = !{i32 1, !"dynamic_qubit_management", i1 false}
743 !3 = !{i32 1, !"dynamic_result_management", i1 false}
744 "#]].assert_eq(&res);
745
746 // Operation should not be visible from global scope
747 let (result, output) = line(&mut interpreter, indoc! {"Bar()"});
748 is_only_error(
749 &result,
750 &output,
751 &expect![[r#"
752 name error: `Bar` not found
753 [line_1] [Bar]
754 type error: insufficient type information to infer type
755 [line_1] [Bar()]
756 "#]],
757 );
758 }
759
760 #[test]
761 fn qirgen_multiple_exprs_parse_fail() {
762 let mut interpreter = Interpreter::new(
763 true,
764 SourceMap::default(),
765 PackageType::Lib,
766 RuntimeCapabilityFlags::empty(),
767 )
768 .expect("interpreter should be created");
769 let (result, output) = line(
770 &mut interpreter,
771 indoc! {"operation Foo() : Result { use q = Qubit(); let r = M(q); Reset(q); return r; } "},
772 );
773 is_only_value(&result, &output, &Value::unit());
774 let res = interpreter
775 .qirgen("Foo(); operation Bar() : Unit {}; Foo()")
776 .expect_err("expected error");
777 is_error(
778 &res,
779 &expect![[r#"
780 syntax error: expected EOF, found `;`
781 [<entry>] [;]
782 "#]],
783 );
784 }
785
786 #[test]
787 fn qirgen_entry_expr_defines_operation_then_more_operations() {
788 let mut interpreter = Interpreter::new(
789 true,
790 SourceMap::default(),
791 PackageType::Lib,
792 RuntimeCapabilityFlags::empty(),
793 )
794 .expect("interpreter should be created");
795 let (result, output) = line(
796 &mut interpreter,
797 indoc! {"operation Foo() : Result { use q = Qubit(); let r = M(q); Reset(q); return r; } "},
798 );
799 is_only_value(&result, &output, &Value::unit());
800 let res = interpreter
801 .qirgen("{operation Bar() : Unit {}; Foo()}")
802 .expect("expected success");
803 expect![[r#"
804 %Result = type opaque
805 %Qubit = type opaque
806
807 define void @ENTRYPOINT__main() #0 {
808 call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 1 to %Qubit*))
809 call void @__quantum__qis__cz__body(%Qubit* inttoptr (i64 1 to %Qubit*), %Qubit* inttoptr (i64 0 to %Qubit*))
810 call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 1 to %Qubit*))
811 call void @__quantum__qis__mz__body(%Qubit* inttoptr (i64 1 to %Qubit*), %Result* inttoptr (i64 0 to %Result*)) #1
812 call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 0 to %Result*), i8* null)
813 ret void
814 }
815
816 declare void @__quantum__qis__ccx__body(%Qubit*, %Qubit*, %Qubit*)
817 declare void @__quantum__qis__cx__body(%Qubit*, %Qubit*)
818 declare void @__quantum__qis__cy__body(%Qubit*, %Qubit*)
819 declare void @__quantum__qis__cz__body(%Qubit*, %Qubit*)
820 declare void @__quantum__qis__rx__body(double, %Qubit*)
821 declare void @__quantum__qis__rxx__body(double, %Qubit*, %Qubit*)
822 declare void @__quantum__qis__ry__body(double, %Qubit*)
823 declare void @__quantum__qis__ryy__body(double, %Qubit*, %Qubit*)
824 declare void @__quantum__qis__rz__body(double, %Qubit*)
825 declare void @__quantum__qis__rzz__body(double, %Qubit*, %Qubit*)
826 declare void @__quantum__qis__h__body(%Qubit*)
827 declare void @__quantum__qis__s__body(%Qubit*)
828 declare void @__quantum__qis__s__adj(%Qubit*)
829 declare void @__quantum__qis__t__body(%Qubit*)
830 declare void @__quantum__qis__t__adj(%Qubit*)
831 declare void @__quantum__qis__x__body(%Qubit*)
832 declare void @__quantum__qis__y__body(%Qubit*)
833 declare void @__quantum__qis__z__body(%Qubit*)
834 declare void @__quantum__qis__swap__body(%Qubit*, %Qubit*)
835 declare void @__quantum__qis__mz__body(%Qubit*, %Result* writeonly) #1
836 declare void @__quantum__rt__result_record_output(%Result*, i8*)
837 declare void @__quantum__rt__array_record_output(i64, i8*)
838 declare void @__quantum__rt__tuple_record_output(i64, i8*)
839
840 attributes #0 = { "entry_point" "output_labeling_schema" "qir_profiles"="base_profile" "required_num_qubits"="2" "required_num_results"="1" }
841 attributes #1 = { "irreversible" }
842
843 ; module flags
844
845 !llvm.module.flags = !{!0, !1, !2, !3}
846
847 !0 = !{i32 1, !"qir_major_version", i32 1}
848 !1 = !{i32 7, !"qir_minor_version", i32 0}
849 !2 = !{i32 1, !"dynamic_qubit_management", i1 false}
850 !3 = !{i32 1, !"dynamic_result_management", i1 false}
851 "#]].assert_eq(&res);
852
853 let (result, output) = line(
854 &mut interpreter,
855 indoc! {"operation Baz() : Result { use q = Qubit(); let r = M(q); Reset(q); return r; } "},
856 );
857 is_only_value(&result, &output, &Value::unit());
858
859 let (result, output) = line(&mut interpreter, indoc! {"Bar()"});
860 is_only_error(
861 &result,
862 &output,
863 &expect![[r#"
864 name error: `Bar` not found
865 [line_2] [Bar]
866 type error: insufficient type information to infer type
867 [line_2] [Bar()]
868 "#]],
869 );
870 }
871
872 #[test]
873 fn qirgen_define_operation_use_it() {
874 let mut interpreter = Interpreter::new(
875 true,
876 SourceMap::default(),
877 PackageType::Lib,
878 RuntimeCapabilityFlags::empty(),
879 )
880 .expect("interpreter should be created");
881 let res = interpreter
882 .qirgen("{ operation Foo() : Result { use q = Qubit(); let r = M(q); Reset(q); return r; }; Foo() }")
883 .expect("expected success");
884 expect![[r#"
885 %Result = type opaque
886 %Qubit = type opaque
887
888 define void @ENTRYPOINT__main() #0 {
889 call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 1 to %Qubit*))
890 call void @__quantum__qis__cz__body(%Qubit* inttoptr (i64 1 to %Qubit*), %Qubit* inttoptr (i64 0 to %Qubit*))
891 call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 1 to %Qubit*))
892 call void @__quantum__qis__mz__body(%Qubit* inttoptr (i64 1 to %Qubit*), %Result* inttoptr (i64 0 to %Result*)) #1
893 call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 0 to %Result*), i8* null)
894 ret void
895 }
896
897 declare void @__quantum__qis__ccx__body(%Qubit*, %Qubit*, %Qubit*)
898 declare void @__quantum__qis__cx__body(%Qubit*, %Qubit*)
899 declare void @__quantum__qis__cy__body(%Qubit*, %Qubit*)
900 declare void @__quantum__qis__cz__body(%Qubit*, %Qubit*)
901 declare void @__quantum__qis__rx__body(double, %Qubit*)
902 declare void @__quantum__qis__rxx__body(double, %Qubit*, %Qubit*)
903 declare void @__quantum__qis__ry__body(double, %Qubit*)
904 declare void @__quantum__qis__ryy__body(double, %Qubit*, %Qubit*)
905 declare void @__quantum__qis__rz__body(double, %Qubit*)
906 declare void @__quantum__qis__rzz__body(double, %Qubit*, %Qubit*)
907 declare void @__quantum__qis__h__body(%Qubit*)
908 declare void @__quantum__qis__s__body(%Qubit*)
909 declare void @__quantum__qis__s__adj(%Qubit*)
910 declare void @__quantum__qis__t__body(%Qubit*)
911 declare void @__quantum__qis__t__adj(%Qubit*)
912 declare void @__quantum__qis__x__body(%Qubit*)
913 declare void @__quantum__qis__y__body(%Qubit*)
914 declare void @__quantum__qis__z__body(%Qubit*)
915 declare void @__quantum__qis__swap__body(%Qubit*, %Qubit*)
916 declare void @__quantum__qis__mz__body(%Qubit*, %Result* writeonly) #1
917 declare void @__quantum__rt__result_record_output(%Result*, i8*)
918 declare void @__quantum__rt__array_record_output(i64, i8*)
919 declare void @__quantum__rt__tuple_record_output(i64, i8*)
920
921 attributes #0 = { "entry_point" "output_labeling_schema" "qir_profiles"="base_profile" "required_num_qubits"="2" "required_num_results"="1" }
922 attributes #1 = { "irreversible" }
923
924 ; module flags
925
926 !llvm.module.flags = !{!0, !1, !2, !3}
927
928 !0 = !{i32 1, !"qir_major_version", i32 1}
929 !1 = !{i32 7, !"qir_minor_version", i32 0}
930 !2 = !{i32 1, !"dynamic_qubit_management", i1 false}
931 !3 = !{i32 1, !"dynamic_result_management", i1 false}
932 "#]].assert_eq(&res);
933 }
934
935 #[test]
936 fn qirgen_entry_expr_profile_incompatible() {
937 let mut interpreter = Interpreter::new(
938 true,
939 SourceMap::default(),
940 PackageType::Lib,
941 RuntimeCapabilityFlags::empty(),
942 )
943 .expect("interpreter should be created");
944 let res = interpreter
945 .qirgen("1")
946 .expect_err("expected qirgen to fail");
947 is_error(
948 &res,
949 &expect![[r#"
950 non-Result return type in entry expression
951 [<entry>] [1]
952 "#]],
953 );
954 }
955
956 #[test]
957 fn run_with_shots() {
958 let mut interpreter = get_interpreter();
959 let (result, output) = line(&mut interpreter, "operation Foo(qs : Qubit[]) : Unit { Microsoft.Quantum.Diagnostics.DumpMachine(); }");
960 is_only_value(&result, &output, &Value::unit());
961 for _ in 0..4 {
962 let (results, output) = run(&mut interpreter, "{use qs = Qubit[2]; Foo(qs)}");
963 is_unit_with_output(
964 &results.expect("compilation should succeed"),
965 &output,
966 "STATE:\n|00⟩: 1+0i",
967 );
968 }
969 }
970
971 #[test]
972 fn run_parse_error() {
973 let mut interpreter = get_interpreter();
974 let (results, _) = run(&mut interpreter, "Foo)");
975 results.expect_err("run() should fail");
976 }
977
978 #[test]
979 fn run_compile_error() {
980 let mut interpreter = get_interpreter();
981 let (results, _) = run(&mut interpreter, "Foo()");
982 results.expect_err("run() should fail");
983 }
984
985 #[test]
986 fn run_multiple_statements_with_return_value() {
987 let mut interpreter = get_interpreter();
988 let (result, output) = line(&mut interpreter, "operation Foo() : Int { 1 }");
989 is_only_value(&result, &output, &Value::unit());
990 let (result, output) = line(&mut interpreter, "operation Bar() : Int { 2 }");
991 is_only_value(&result, &output, &Value::unit());
992 let (result, output) = run(&mut interpreter, "{ Foo(); Bar() }");
993 is_only_value(
994 &result.expect("compilation should succeed"),
995 &output,
996 &Value::Int(2),
997 );
998 }
999
1000 #[test]
1001 fn run_runtime_failure() {
1002 let mut interpreter = get_interpreter();
1003 let (result, output) = line(
1004 &mut interpreter,
1005 r#"operation Foo() : Int { fail "failed" }"#,
1006 );
1007 is_only_value(&result, &output, &Value::unit());
1008 for _ in 0..1 {
1009 let (result, output) = run(&mut interpreter, "Foo()");
1010 is_only_error(
1011 &result.expect("compilation should succeed"),
1012 &output,
1013 &expect![[r#"
1014 runtime error: program failed: failed
1015 explicit fail [line_0] [fail "failed"]
1016 "#]],
1017 );
1018 }
1019 }
1020
1021 #[test]
1022 fn run_output_merged() {
1023 let mut interpreter = get_interpreter();
1024 let (result, output) = line(
1025 &mut interpreter,
1026 r#"operation Foo() : Unit { Message("hello!") }"#,
1027 );
1028 is_only_value(&result, &output, &Value::unit());
1029 for _ in 0..4 {
1030 let (result, output) = run(&mut interpreter, "Foo()");
1031 is_unit_with_output(
1032 &result.expect("compilation should succeed"),
1033 &output,
1034 "hello!",
1035 );
1036 }
1037 }
1038 }
1039
1040 fn get_interpreter() -> Interpreter {
1041 Interpreter::new(
1042 true,
1043 SourceMap::default(),
1044 PackageType::Lib,
1045 RuntimeCapabilityFlags::all(),
1046 )
1047 .expect("interpreter should be created")
1048 }
1049
1050 fn is_only_value(result: &InterpretResult, output: &str, value: &Value) {
1051 assert_eq!("", output);
1052
1053 match result {
1054 Ok(v) => assert_eq!(value, v),
1055 Err(e) => panic!("Expected unit value, got {e:?}"),
1056 }
1057 }
1058
1059 fn is_unit_with_output_eval_entry(
1060 result: &Result<Value, Vec<crate::interpret::Error>>,
1061 output: &str,
1062 expected_output: &str,
1063 ) {
1064 assert_eq!(expected_output, output);
1065
1066 match result {
1067 Ok(value) => assert_eq!(Value::unit(), *value),
1068 Err(e) => panic!("Expected unit value, got {e:?}"),
1069 }
1070 }
1071
1072 fn is_unit_with_output(result: &InterpretResult, output: &str, expected_output: &str) {
1073 assert_eq!(expected_output, output);
1074
1075 match result {
1076 Ok(value) => assert_eq!(Value::unit(), *value),
1077 Err(e) => panic!("Expected unit value, got {e:?}"),
1078 }
1079 }
1080
1081 fn is_only_error<E>(result: &Result<Value, Vec<E>>, output: &str, expected_errors: &Expect)
1082 where
1083 E: Diagnostic,
1084 {
1085 assert_eq!("", output);
1086
1087 match result {
1088 Ok(value) => panic!("Expected error , got {value:?}"),
1089 Err(errors) => is_error(errors, expected_errors),
1090 }
1091 }
1092
1093 fn is_error<E>(errors: &Vec<E>, expected_errors: &Expect)
1094 where
1095 E: Diagnostic,
1096 {
1097 let mut actual = String::new();
1098 for error in errors {
1099 write!(actual, "{error}").expect("writing should succeed");
1100 for s in iter::successors(error.source(), |&s| s.source()) {
1101 write!(actual, ": {s}").expect("writing should succeed");
1102 }
1103 for label in error.labels().into_iter().flatten() {
1104 let span = error
1105 .source_code()
1106 .expect("expected valid source code")
1107 .read_span(label.inner(), 0, 0)
1108 .expect("expected to be able to read span");
1109
1110 write!(
1111 actual,
1112 "\n {} [{}] [{}]",
1113 label.label().unwrap_or(""),
1114 span.name().expect("expected source file name"),
1115 from_utf8(span.data()).expect("expected valid utf-8 string"),
1116 )
1117 .expect("writing should succeed");
1118 }
1119 writeln!(actual).expect("writing should succeed");
1120 }
1121
1122 expected_errors.assert_eq(&actual);
1123 }
1124
1125 #[cfg(test)]
1126 mod with_sources {
1127 use std::sync::Arc;
1128
1129 use super::*;
1130 use crate::interpret::Debugger;
1131 use crate::line_column::Encoding;
1132 use expect_test::expect;
1133 use indoc::indoc;
1134 use qsc_frontend::compile::{RuntimeCapabilityFlags, SourceMap};
1135 use qsc_passes::PackageType;
1136
1137 #[test]
1138 fn entry_expr_is_executed() {
1139 let source = indoc! { r#"
1140 namespace Test {
1141 @EntryPoint()
1142 operation Main() : Unit {
1143 Message("hello there...")
1144 }
1145 }"#};
1146
1147 let sources = SourceMap::new([("test".into(), source.into())], None);
1148 let mut interpreter = Interpreter::new(
1149 true,
1150 sources,
1151 PackageType::Exe,
1152 RuntimeCapabilityFlags::all(),
1153 )
1154 .expect("interpreter should be created");
1155
1156 let (result, output) = entry(&mut interpreter);
1157 is_unit_with_output_eval_entry(&result, &output, "hello there...");
1158 }
1159
1160 #[test]
1161 fn stdlib_members_can_be_accessed_from_sources() {
1162 let source = indoc! { r#"
1163 namespace Test {
1164 operation Main() : Unit {
1165 Message("hello there...")
1166 }
1167 }"#};
1168
1169 let sources = SourceMap::new([("test".into(), source.into())], None);
1170 let mut interpreter = Interpreter::new(
1171 true,
1172 sources,
1173 PackageType::Lib,
1174 RuntimeCapabilityFlags::all(),
1175 )
1176 .expect("interpreter should be created");
1177
1178 let (result, output) = line(&mut interpreter, "Test.Main()");
1179 is_unit_with_output(&result, &output, "hello there...");
1180 }
1181
1182 #[test]
1183 fn members_from_namespaced_sources_are_in_context() {
1184 let source = indoc! { r#"
1185 namespace Test {
1186 function Hello() : String {
1187 "hello there..."
1188 }
1189
1190 operation Main() : String {
1191 Hello()
1192 }
1193 }"#};
1194
1195 let sources = SourceMap::new([("test".into(), source.into())], None);
1196 let mut interpreter = Interpreter::new(
1197 true,
1198 sources,
1199 PackageType::Lib,
1200 RuntimeCapabilityFlags::all(),
1201 )
1202 .expect("interpreter should be created");
1203
1204 let (result, output) = line(&mut interpreter, "Test.Hello()");
1205 is_only_value(&result, &output, &Value::String("hello there...".into()));
1206 let (result, output) = line(&mut interpreter, "Test.Main()");
1207 is_only_value(&result, &output, &Value::String("hello there...".into()));
1208 }
1209
1210 #[test]
1211 fn multiple_files_are_loaded_from_sources_into_eval_context() {
1212 let sources: [(Arc<str>, Arc<str>); 2] = [
1213 (
1214 "a.qs".into(),
1215 r#"
1216 namespace Test {
1217 function Hello() : String {
1218 "hello there..."
1219 }
1220 }"#
1221 .into(),
1222 ),
1223 (
1224 "b.qs".into(),
1225 r#"
1226 namespace Test2 {
1227 open Test;
1228 @EntryPoint()
1229 operation Main() : String {
1230 Hello();
1231 Hello()
1232 }
1233 }"#
1234 .into(),
1235 ),
1236 ];
1237
1238 let sources = SourceMap::new(sources, None);
1239 let debugger = Debugger::new(sources, RuntimeCapabilityFlags::all(), Encoding::Utf8)
1240 .expect("debugger should be created");
1241 let bps = debugger.get_breakpoints("a.qs");
1242 assert_eq!(1, bps.len());
1243 let bps = debugger.get_breakpoints("b.qs");
1244 assert_eq!(2, bps.len());
1245 }
1246
1247 #[test]
1248 fn multiple_namespaces_are_loaded_from_sources_into_eval_context() {
1249 let source = indoc! { r#"
1250 namespace Test {
1251 function Hello() : String {
1252 "hello there..."
1253 }
1254 }
1255 namespace Test2 {
1256 open Test;
1257 operation Main() : String {
1258 Hello()
1259 }
1260 }"#};
1261
1262 let sources = SourceMap::new([("test".into(), source.into())], None);
1263 let mut interpreter = Interpreter::new(
1264 true,
1265 sources,
1266 PackageType::Lib,
1267 RuntimeCapabilityFlags::all(),
1268 )
1269 .expect("interpreter should be created");
1270 let (result, output) = line(&mut interpreter, "Test.Hello()");
1271 is_only_value(&result, &output, &Value::String("hello there...".into()));
1272 let (result, output) = line(&mut interpreter, "Test2.Main()");
1273 is_only_value(&result, &output, &Value::String("hello there...".into()));
1274 }
1275
1276 #[test]
1277 fn runtime_error_from_stdlib() {
1278 let sources = SourceMap::new(
1279 [(
1280 "test".into(),
1281 "namespace Foo {
1282 operation Bar(): Unit {
1283 let x = -1;
1284 use qs = Qubit[x];
1285 }
1286 }
1287 "
1288 .into(),
1289 )],
1290 Some("Foo.Bar()".into()),
1291 );
1292
1293 let mut interpreter = Interpreter::new(
1294 true,
1295 sources,
1296 PackageType::Lib,
1297 RuntimeCapabilityFlags::all(),
1298 )
1299 .expect("interpreter should be created");
1300 let (result, output) = entry(&mut interpreter);
1301 is_only_error(
1302 &result,
1303 &output,
1304 &expect![[r#"
1305 runtime error: program failed: Cannot allocate qubit array with a negative length
1306 explicit fail [core/qir.qs] [fail "Cannot allocate qubit array with a negative length"]
1307 "#]],
1308 );
1309 }
1310 }
1311}
1312