microsoft/qdk

Public

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

CodeCommitsIssuesPull requestsActionsInsightsSecurity
v1.2.0

Branches

Tags

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

Clone

HTTPS

Download ZIP

compiler/qsc_frontend/src/compile/tests.rs

1257lines · modecode

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4#![allow(clippy::needless_raw_string_hashes)]
5
6use crate::compile::RuntimeCapabilityFlags;
7
8use super::{compile, CompileUnit, Error, PackageStore, SourceMap};
9use expect_test::expect;
10use indoc::indoc;
11use miette::Diagnostic;
12use qsc_data_structures::{language_features::LanguageFeatures, span::Span};
13use qsc_hir::{
14 global,
15 hir::{
16 Block, Expr, ExprKind, ItemId, ItemKind, Lit, LocalItemId, NodeId, Res, SpecBody, Stmt,
17 StmtKind,
18 },
19 mut_visit::MutVisitor,
20 ty::{Prim, Ty},
21};
22
23fn error_span(error: &Error) -> Span {
24 let label = error
25 .labels()
26 .and_then(|mut ls| ls.next())
27 .expect("error should have at least one label");
28
29 let span = label.inner();
30 let offset = span
31 .offset()
32 .try_into()
33 .expect("span offset should fit into u32");
34 let len: u32 = span.len().try_into().expect("span len should fit into u32");
35 Span {
36 lo: offset,
37 hi: offset + len,
38 }
39}
40
41fn source_span<'a>(sources: &'a SourceMap, error: &Error) -> (&'a str, Span) {
42 let span = error_span(error);
43 let source = sources
44 .find_by_offset(span.lo)
45 .expect("offset should match at least one source");
46 (
47 &source.name,
48 Span {
49 lo: span.lo - source.offset,
50 hi: span.hi - source.offset,
51 },
52 )
53}
54
55/// runs a compile with the default configuration
56fn default_compile(sources: SourceMap) -> CompileUnit {
57 compile(
58 &PackageStore::new(super::core()),
59 &[],
60 sources,
61 RuntimeCapabilityFlags::all(),
62 LanguageFeatures::default(),
63 )
64}
65
66#[test]
67fn one_file_no_entry() {
68 let sources = SourceMap::new(
69 [(
70 "test".into(),
71 indoc! {"
72 namespace Foo {
73 function A() : Unit {}
74 }
75 "}
76 .into(),
77 )],
78 None,
79 );
80
81 let unit = default_compile(sources);
82 assert!(unit.errors.is_empty(), "{:#?}", unit.errors);
83
84 let entry = unit.package.entry.as_ref();
85 assert!(entry.is_none(), "{entry:#?}");
86}
87
88#[test]
89fn one_file_error() {
90 let sources = SourceMap::new(
91 [(
92 "test".into(),
93 indoc! {"
94 namespace Foo {
95 function A() : Unit {
96 x
97 }
98 }
99 "}
100 .into(),
101 )],
102 None,
103 );
104
105 let unit = default_compile(sources);
106 let errors: Vec<_> = unit
107 .errors
108 .iter()
109 .map(|error| source_span(&unit.sources, error))
110 .collect();
111
112 assert_eq!(vec![("test", Span { lo: 50, hi: 51 })], errors);
113}
114
115#[test]
116fn two_files_dependency() {
117 let sources = SourceMap::new(
118 [
119 (
120 "test1".into(),
121 indoc! {"
122 namespace Foo {
123 function A() : Unit {}
124 }
125 "}
126 .into(),
127 ),
128 (
129 "test2".into(),
130 indoc! {"
131 namespace Foo {
132 function B() : Unit {
133 A();
134 }
135 }
136 "}
137 .into(),
138 ),
139 ],
140 None,
141 );
142
143 let unit = default_compile(sources);
144 assert!(unit.errors.is_empty(), "{:#?}", unit.errors);
145}
146
147#[test]
148fn two_files_mutual_dependency() {
149 let sources = SourceMap::new(
150 [
151 (
152 "test1".into(),
153 indoc! {"
154 namespace Foo {
155 function A() : Unit {
156 B();
157 }
158 }
159 "}
160 .into(),
161 ),
162 (
163 "test2".into(),
164 indoc! {"
165 namespace Foo {
166 function B() : Unit {
167 A();
168 }
169 }
170 "}
171 .into(),
172 ),
173 ],
174 None,
175 );
176
177 let unit = default_compile(sources);
178 assert!(unit.errors.is_empty(), "{:#?}", unit.errors);
179}
180
181#[test]
182fn two_files_error() {
183 let sources = SourceMap::new(
184 [
185 (
186 "test1".into(),
187 indoc! {"
188 namespace Foo {
189 function A() : Unit {}
190 }
191 "}
192 .into(),
193 ),
194 (
195 "test2".into(),
196 indoc! {"
197 namespace Foo {
198 function B() : Unit {
199 C();
200 }
201 }
202 "}
203 .into(),
204 ),
205 ],
206 None,
207 );
208
209 let unit = default_compile(sources);
210 let errors: Vec<_> = unit
211 .errors
212 .iter()
213 .map(|error| source_span(&unit.sources, error))
214 .collect();
215
216 assert_eq!(
217 vec![
218 ("test2", Span { lo: 50, hi: 51 }),
219 ("test2", Span { lo: 50, hi: 53 }),
220 ],
221 errors
222 );
223}
224
225#[test]
226fn entry_call_operation() {
227 let sources = SourceMap::new(
228 [(
229 "test".into(),
230 indoc! {"
231 namespace Foo {
232 operation A() : Unit {}
233 }
234 "}
235 .into(),
236 )],
237 Some("Foo.A()".into()),
238 );
239
240 let unit = default_compile(sources);
241 assert!(unit.errors.is_empty(), "{:#?}", unit.errors);
242
243 let entry = &unit.package.entry.expect("package should have entry");
244 let ExprKind::Call(callee, _) = &entry.kind else {
245 panic!("entry should be a call")
246 };
247 let ExprKind::Var(res, _) = &callee.kind else {
248 panic!("callee should be a variable")
249 };
250 assert_eq!(
251 &Res::Item(ItemId {
252 package: None,
253 item: LocalItemId::from(1),
254 }),
255 res
256 );
257}
258
259#[test]
260fn entry_error() {
261 let sources = SourceMap::new(
262 [(
263 "test".into(),
264 indoc! {"
265 namespace Foo {
266 operation A() : Unit {}
267 }
268 "}
269 .into(),
270 )],
271 Some("Foo.B()".into()),
272 );
273
274 let unit = default_compile(sources);
275 assert_eq!(
276 ("<entry>", Span { lo: 4, hi: 5 }),
277 source_span(&unit.sources, &unit.errors[0])
278 );
279}
280
281#[test]
282fn replace_node() {
283 struct Replacer;
284
285 impl MutVisitor for Replacer {
286 fn visit_expr(&mut self, expr: &mut Expr) {
287 *expr = Expr {
288 id: NodeId::default(),
289 span: expr.span,
290 ty: Ty::Prim(Prim::Int),
291 kind: ExprKind::Lit(Lit::Int(2)),
292 };
293 }
294 }
295
296 let sources = SourceMap::new(
297 [(
298 "test".into(),
299 indoc! {"
300 namespace A {
301 function Foo() : Int {
302 1
303 }
304 }
305 "}
306 .into(),
307 )],
308 None,
309 );
310
311 let mut unit = default_compile(sources);
312 assert!(unit.errors.is_empty(), "{:#?}", unit.errors);
313 Replacer.visit_package(&mut unit.package);
314 unit.assigner.visit_package(&mut unit.package);
315
316 let ItemKind::Callable(callable) = &unit
317 .package
318 .items
319 .get(LocalItemId::from(1))
320 .expect("package should have item")
321 .kind
322 else {
323 panic!("item should be a callable");
324 };
325 let SpecBody::Impl(_, block) = &callable.body.body else {
326 panic!("callable body have a block")
327 };
328 expect![[r#"
329 Block 4 [39-56] [Type Int]:
330 Stmt 5 [49-50]: Expr: Expr 8 [49-50] [Type Int]: Lit: Int(2)"#]]
331 .assert_eq(&block.to_string());
332}
333
334#[test]
335fn insert_core_call() {
336 struct Inserter<'a> {
337 core: &'a global::Table,
338 }
339
340 impl MutVisitor for Inserter<'_> {
341 fn visit_block(&mut self, block: &mut Block) {
342 let allocate = self
343 .core
344 .resolve_term("QIR.Runtime", "__quantum__rt__qubit_allocate")
345 .expect("qubit allocation should be in core");
346 let allocate_ty = allocate
347 .scheme
348 .instantiate(&[])
349 .expect("qubit allocation scheme should instantiate");
350 let callee = Expr {
351 id: NodeId::default(),
352 span: Span::default(),
353 ty: Ty::Arrow(Box::new(allocate_ty)),
354 kind: ExprKind::Var(Res::Item(allocate.id), Vec::new()),
355 };
356
357 let arg = Expr {
358 id: NodeId::default(),
359 span: Span::default(),
360 ty: Ty::UNIT,
361 kind: ExprKind::Tuple(Vec::new()),
362 };
363
364 let call = Expr {
365 id: NodeId::default(),
366 span: Span::default(),
367 ty: Ty::Prim(Prim::Qubit),
368 kind: ExprKind::Call(Box::new(callee), Box::new(arg)),
369 };
370
371 block.stmts.push(Stmt {
372 id: NodeId::default(),
373 span: Span::default(),
374 kind: StmtKind::Semi(call),
375 });
376 }
377 }
378
379 let sources = SourceMap::new(
380 [(
381 "test".into(),
382 indoc! {"
383 namespace A {
384 operation Foo() : () {}
385 }
386 "}
387 .into(),
388 )],
389 None,
390 );
391
392 let store = PackageStore::new(super::core());
393 let mut unit = default_compile(sources);
394 assert!(unit.errors.is_empty(), "{:#?}", unit.errors);
395 let mut inserter = Inserter { core: store.core() };
396 inserter.visit_package(&mut unit.package);
397 unit.assigner.visit_package(&mut unit.package);
398
399 expect![[r#"
400 Package:
401 Item 0 [0-43] (Public):
402 Namespace (Ident 5 [10-11] "A"): Item 1
403 Item 1 [18-41] (Public):
404 Parent: 0
405 Callable 0 [18-41] (operation):
406 name: Ident 1 [28-31] "Foo"
407 input: Pat 2 [31-33] [Type Unit]: Unit
408 output: Unit
409 functors: empty set
410 body: SpecDecl 3 [18-41]: Impl:
411 Block 4 [39-41] [Type Unit]:
412 Stmt 6 [0-0]: Semi: Expr 7 [0-0] [Type Qubit]: Call:
413 Expr 8 [0-0] [Type (Unit => Qubit)]: Var: Item 4 (Package 0)
414 Expr 9 [0-0] [Type Unit]: Unit
415 adj: <none>
416 ctl: <none>
417 ctl-adj: <none>"#]]
418 .assert_eq(&unit.package.to_string());
419}
420
421#[test]
422fn package_dependency() {
423 let mut store = PackageStore::new(super::core());
424
425 let sources1 = SourceMap::new(
426 [(
427 "test".into(),
428 indoc! {"
429 namespace Package1 {
430 function Foo() : Int {
431 1
432 }
433 }
434 "}
435 .into(),
436 )],
437 None,
438 );
439 let unit1 = compile(
440 &store,
441 &[],
442 sources1,
443 RuntimeCapabilityFlags::all(),
444 LanguageFeatures::default(),
445 );
446 assert!(unit1.errors.is_empty(), "{:#?}", unit1.errors);
447 let package1 = store.insert(unit1);
448
449 let sources2 = SourceMap::new(
450 [(
451 "test".into(),
452 indoc! {"
453 namespace Package2 {
454 function Bar() : Int {
455 Package1.Foo()
456 }
457 }
458 "}
459 .into(),
460 )],
461 None,
462 );
463 let unit2 = compile(
464 &store,
465 &[package1],
466 sources2,
467 RuntimeCapabilityFlags::all(),
468 LanguageFeatures::default(),
469 );
470 assert!(unit2.errors.is_empty(), "{:#?}", unit2.errors);
471
472 expect![[r#"
473 Package:
474 Item 0 [0-78] (Public):
475 Namespace (Ident 9 [10-18] "Package2"): Item 1
476 Item 1 [25-76] (Public):
477 Parent: 0
478 Callable 0 [25-76] (function):
479 name: Ident 1 [34-37] "Bar"
480 input: Pat 2 [37-39] [Type Unit]: Unit
481 output: Int
482 functors: empty set
483 body: SpecDecl 3 [25-76]: Impl:
484 Block 4 [46-76] [Type Int]:
485 Stmt 5 [56-70]: Expr: Expr 6 [56-70] [Type Int]: Call:
486 Expr 7 [56-68] [Type (Unit -> Int)]: Var: Item 1 (Package 1)
487 Expr 8 [68-70] [Type Unit]: Unit
488 adj: <none>
489 ctl: <none>
490 ctl-adj: <none>"#]]
491 .assert_eq(&unit2.package.to_string());
492}
493
494#[test]
495fn package_dependency_internal_error() {
496 let mut store = PackageStore::new(super::core());
497
498 let sources1 = SourceMap::new(
499 [(
500 "test".into(),
501 indoc! {"
502 namespace Package1 {
503 internal function Foo() : Int {
504 1
505 }
506 }
507 "}
508 .into(),
509 )],
510 None,
511 );
512 let unit1 = compile(
513 &store,
514 &[],
515 sources1,
516 RuntimeCapabilityFlags::all(),
517 LanguageFeatures::default(),
518 );
519 assert!(unit1.errors.is_empty(), "{:#?}", unit1.errors);
520 let package1 = store.insert(unit1);
521
522 let sources2 = SourceMap::new(
523 [(
524 "test".into(),
525 indoc! {"
526 namespace Package2 {
527 function Bar() : Int {
528 Package1.Foo()
529 }
530 }
531 "}
532 .into(),
533 )],
534 None,
535 );
536 let unit2 = compile(
537 &store,
538 &[package1],
539 sources2,
540 RuntimeCapabilityFlags::all(),
541 LanguageFeatures::default(),
542 );
543
544 let errors: Vec<_> = unit2
545 .errors
546 .iter()
547 .map(|error| source_span(&unit2.sources, error))
548 .collect();
549 assert_eq!(vec![("test", Span { lo: 65, hi: 68 }),], errors);
550
551 expect![[r#"
552 Package:
553 Item 0 [0-78] (Public):
554 Namespace (Ident 9 [10-18] "Package2"): Item 1
555 Item 1 [25-76] (Public):
556 Parent: 0
557 Callable 0 [25-76] (function):
558 name: Ident 1 [34-37] "Bar"
559 input: Pat 2 [37-39] [Type Unit]: Unit
560 output: Int
561 functors: empty set
562 body: SpecDecl 3 [25-76]: Impl:
563 Block 4 [46-76] [Type Int]:
564 Stmt 5 [56-70]: Expr: Expr 6 [56-70] [Type Int]: Call:
565 Expr 7 [56-68] [Type ?]: Var: Err
566 Expr 8 [68-70] [Type Unit]: Unit
567 adj: <none>
568 ctl: <none>
569 ctl-adj: <none>"#]]
570 .assert_eq(&unit2.package.to_string());
571}
572
573#[test]
574fn package_dependency_udt() {
575 let mut store = PackageStore::new(super::core());
576
577 let sources1 = SourceMap::new(
578 [(
579 "test".into(),
580 indoc! {"
581 namespace Package1 {
582 newtype Bar = Int;
583 function Foo(bar : Bar) : Int {
584 bar!
585 }
586 }
587 "}
588 .into(),
589 )],
590 None,
591 );
592 let unit1 = compile(
593 &store,
594 &[],
595 sources1,
596 RuntimeCapabilityFlags::all(),
597 LanguageFeatures::default(),
598 );
599 assert!(unit1.errors.is_empty(), "{:#?}", unit1.errors);
600 let package1 = store.insert(unit1);
601
602 let sources2 = SourceMap::new(
603 [(
604 "test".into(),
605 indoc! {"
606 namespace Package2 {
607 function Baz() : Int {
608 Package1.Foo(Package1.Bar(1))
609 }
610 }
611 "}
612 .into(),
613 )],
614 None,
615 );
616 let unit2 = compile(
617 &store,
618 &[package1],
619 sources2,
620 RuntimeCapabilityFlags::all(),
621 LanguageFeatures::default(),
622 );
623 assert!(unit2.errors.is_empty(), "{:#?}", unit2.errors);
624
625 expect![[r#"
626 Package:
627 Item 0 [0-93] (Public):
628 Namespace (Ident 11 [10-18] "Package2"): Item 1
629 Item 1 [25-91] (Public):
630 Parent: 0
631 Callable 0 [25-91] (function):
632 name: Ident 1 [34-37] "Baz"
633 input: Pat 2 [37-39] [Type Unit]: Unit
634 output: Int
635 functors: empty set
636 body: SpecDecl 3 [25-91]: Impl:
637 Block 4 [46-91] [Type Int]:
638 Stmt 5 [56-85]: Expr: Expr 6 [56-85] [Type Int]: Call:
639 Expr 7 [56-68] [Type (UDT<"Bar": Item 1 (Package 1)> -> Int)]: Var: Item 2 (Package 1)
640 Expr 8 [69-84] [Type UDT<"Bar": Item 1 (Package 1)>]: Call:
641 Expr 9 [69-81] [Type (Int -> UDT<"Bar": Item 1 (Package 1)>)]: Var: Item 1 (Package 1)
642 Expr 10 [82-83] [Type Int]: Lit: Int(1)
643 adj: <none>
644 ctl: <none>
645 ctl-adj: <none>"#]]
646 .assert_eq(&unit2.package.to_string());
647}
648
649#[test]
650fn package_dependency_nested_udt() {
651 let mut store = PackageStore::new(super::core());
652
653 let sources1 = SourceMap::new(
654 [(
655 "test".into(),
656 indoc! {"
657 namespace Package1 {
658 newtype Bar = Int;
659 newtype Baz = Int;
660 newtype Foo = (bar : Bar, Baz);
661 }
662 "}
663 .into(),
664 )],
665 None,
666 );
667 let unit1 = compile(
668 &store,
669 &[],
670 sources1,
671 RuntimeCapabilityFlags::all(),
672 LanguageFeatures::default(),
673 );
674 assert!(unit1.errors.is_empty(), "{:#?}", unit1.errors);
675 let package1 = store.insert(unit1);
676
677 let sources2 = SourceMap::new(
678 [(
679 "test".into(),
680 indoc! {"
681 namespace Package2 {
682 function Test() : Int {
683 let bar = Package1.Bar(1);
684 let baz = Package1.Baz(2);
685 let foo = Package1.Foo(bar, baz);
686 let inner : Package1.Bar = foo::bar;
687 let (_, other : Package1.Baz) = foo!;
688 inner!
689 }
690 }
691 "}
692 .into(),
693 )],
694 None,
695 );
696 let unit2 = compile(
697 &store,
698 &[package1],
699 sources2,
700 RuntimeCapabilityFlags::all(),
701 LanguageFeatures::default(),
702 );
703 assert!(unit2.errors.is_empty(), "{:#?}", unit2.errors);
704
705 expect![[r#"
706 Package:
707 Item 0 [0-274] (Public):
708 Namespace (Ident 40 [10-18] "Package2"): Item 1
709 Item 1 [25-272] (Public):
710 Parent: 0
711 Callable 0 [25-272] (function):
712 name: Ident 1 [34-38] "Test"
713 input: Pat 2 [38-40] [Type Unit]: Unit
714 output: Int
715 functors: empty set
716 body: SpecDecl 3 [25-272]: Impl:
717 Block 4 [47-272] [Type Int]:
718 Stmt 5 [57-83]: Local (Immutable):
719 Pat 6 [61-64] [Type UDT<"Bar": Item 1 (Package 1)>]: Bind: Ident 7 [61-64] "bar"
720 Expr 8 [67-82] [Type UDT<"Bar": Item 1 (Package 1)>]: Call:
721 Expr 9 [67-79] [Type (Int -> UDT<"Bar": Item 1 (Package 1)>)]: Var: Item 1 (Package 1)
722 Expr 10 [80-81] [Type Int]: Lit: Int(1)
723 Stmt 11 [92-118]: Local (Immutable):
724 Pat 12 [96-99] [Type UDT<"Baz": Item 2 (Package 1)>]: Bind: Ident 13 [96-99] "baz"
725 Expr 14 [102-117] [Type UDT<"Baz": Item 2 (Package 1)>]: Call:
726 Expr 15 [102-114] [Type (Int -> UDT<"Baz": Item 2 (Package 1)>)]: Var: Item 2 (Package 1)
727 Expr 16 [115-116] [Type Int]: Lit: Int(2)
728 Stmt 17 [127-160]: Local (Immutable):
729 Pat 18 [131-134] [Type UDT<"Foo": Item 3 (Package 1)>]: Bind: Ident 19 [131-134] "foo"
730 Expr 20 [137-159] [Type UDT<"Foo": Item 3 (Package 1)>]: Call:
731 Expr 21 [137-149] [Type ((UDT<"Bar": Item 1 (Package 1)>, UDT<"Baz": Item 2 (Package 1)>) -> UDT<"Foo": Item 3 (Package 1)>)]: Var: Item 3 (Package 1)
732 Expr 22 [149-159] [Type (UDT<"Bar": Item 1 (Package 1)>, UDT<"Baz": Item 2 (Package 1)>)]: Tuple:
733 Expr 23 [150-153] [Type UDT<"Bar": Item 1 (Package 1)>]: Var: Local 7
734 Expr 24 [155-158] [Type UDT<"Baz": Item 2 (Package 1)>]: Var: Local 13
735 Stmt 25 [169-205]: Local (Immutable):
736 Pat 26 [173-193] [Type UDT<"Bar": Item 1 (Package 1)>]: Bind: Ident 27 [173-178] "inner"
737 Expr 28 [196-204] [Type UDT<"Bar": Item 1 (Package 1)>]: Field:
738 Expr 29 [196-199] [Type UDT<"Foo": Item 3 (Package 1)>]: Var: Local 19
739 Path(FieldPath { indices: [0] })
740 Stmt 30 [214-251]: Local (Immutable):
741 Pat 31 [218-243] [Type (UDT<"Bar": Item 1 (Package 1)>, UDT<"Baz": Item 2 (Package 1)>)]: Tuple:
742 Pat 32 [219-220] [Type UDT<"Bar": Item 1 (Package 1)>]: Discard
743 Pat 33 [222-242] [Type UDT<"Baz": Item 2 (Package 1)>]: Bind: Ident 34 [222-227] "other"
744 Expr 35 [246-250] [Type (UDT<"Bar": Item 1 (Package 1)>, UDT<"Baz": Item 2 (Package 1)>)]: UnOp (Unwrap):
745 Expr 36 [246-249] [Type UDT<"Foo": Item 3 (Package 1)>]: Var: Local 19
746 Stmt 37 [260-266]: Expr: Expr 38 [260-266] [Type Int]: UnOp (Unwrap):
747 Expr 39 [260-265] [Type UDT<"Bar": Item 1 (Package 1)>]: Var: Local 27
748 adj: <none>
749 ctl: <none>
750 ctl-adj: <none>"#]]
751 .assert_eq(&unit2.package.to_string());
752}
753
754#[test]
755fn std_dependency() {
756 let mut store = PackageStore::new(super::core());
757 let std = store.insert(super::std(&store, RuntimeCapabilityFlags::all()));
758 let sources = SourceMap::new(
759 [(
760 "test".into(),
761 indoc! {"
762 namespace Foo {
763 open Microsoft.Quantum.Intrinsic;
764
765 operation Main() : Unit {
766 use q = Qubit();
767 X(q);
768 }
769 }
770 "}
771 .into(),
772 )],
773 Some("Foo.Main()".into()),
774 );
775
776 let unit = compile(
777 &store,
778 &[std],
779 sources,
780 RuntimeCapabilityFlags::all(),
781 LanguageFeatures::default(),
782 );
783 assert!(unit.errors.is_empty(), "{:#?}", unit.errors);
784}
785
786#[test]
787fn std_dependency_base_profile() {
788 let mut store = PackageStore::new(super::core());
789 let std = store.insert(super::std(&store, RuntimeCapabilityFlags::empty()));
790 let sources = SourceMap::new(
791 [(
792 "test".into(),
793 indoc! {"
794 namespace Foo {
795 open Microsoft.Quantum.Intrinsic;
796
797 operation Main() : Unit {
798 use q = Qubit();
799 X(q);
800 }
801 }
802 "}
803 .into(),
804 )],
805 Some("Foo.Main()".into()),
806 );
807
808 let unit = compile(
809 &store,
810 &[std],
811 sources,
812 RuntimeCapabilityFlags::empty(),
813 LanguageFeatures::default(),
814 );
815 assert!(unit.errors.is_empty(), "{:#?}", unit.errors);
816}
817
818#[test]
819fn introduce_prelude_ambiguity() {
820 let mut store = PackageStore::new(super::core());
821 let std = store.insert(super::std(&store, RuntimeCapabilityFlags::all()));
822 let sources = SourceMap::new(
823 [(
824 "test".into(),
825 indoc! {"namespace Microsoft.Quantum.Canon {
826 function Length () : () { }
827 }
828 namespace Foo {
829 function Main (): () { Length }
830 }"}
831 .into(),
832 )],
833 Some("Foo.Main()".into()),
834 );
835
836 let unit = compile(
837 &store,
838 &[std],
839 sources,
840 RuntimeCapabilityFlags::all(),
841 LanguageFeatures::default(),
842 );
843 let errors: Vec<Error> = unit.errors;
844 assert!(
845 errors.len() == 1
846 && matches!(
847 errors[0],
848 Error(super::ErrorKind::Resolve(
849 super::resolve::Error::AmbiguousPrelude { .. }
850 ))
851 )
852 );
853}
854
855#[test]
856fn entry_parse_error() {
857 let sources = SourceMap::new(
858 [(
859 "test".into(),
860 "namespace Foo { operation B() : Unit {} }".into(),
861 )],
862 Some("Foo.B)".into()),
863 );
864
865 let unit = default_compile(sources);
866
867 assert_eq!(
868 unit.errors[0]
869 .code()
870 .expect("expected error code")
871 .to_string(),
872 "Qsc.Parse.Token"
873 );
874
875 assert_eq!(
876 ("<entry>", Span { lo: 5, hi: 6 }),
877 source_span(&unit.sources, &unit.errors[0])
878 );
879}
880
881#[test]
882fn two_files_error_eof() {
883 let sources = SourceMap::new(
884 [
885 ("test1".into(), "namespace Foo {".into()),
886 ("test2".into(), "namespace Bar {}".into()),
887 ],
888 None,
889 );
890
891 let unit = default_compile(sources);
892 let errors: Vec<_> = unit
893 .errors
894 .iter()
895 .map(|error| source_span(&unit.sources, error))
896 .collect();
897
898 assert_eq!(vec![("test1", Span { lo: 15, hi: 15 }),], errors);
899
900 expect![[r#"
901 Package:
902 Item 0 [0-15] (Public):
903 Namespace (Ident 0 [10-13] "Foo"): <empty>
904 Item 1 [16-32] (Public):
905 Namespace (Ident 1 [26-29] "Bar"): <empty>"#]]
906 .assert_eq(&unit.package.to_string());
907}
908
909#[test]
910fn unimplemented_call_from_dependency_produces_error() {
911 let lib_sources = SourceMap::new(
912 [(
913 "lib".into(),
914 indoc! {"
915 namespace Foo {
916 @Unimplemented()
917 operation Bar() : Unit {}
918 }
919 "}
920 .into(),
921 )],
922 None,
923 );
924 let mut store = PackageStore::new(super::core());
925 let lib = compile(
926 &store,
927 &[],
928 lib_sources,
929 RuntimeCapabilityFlags::all(),
930 LanguageFeatures::default(),
931 );
932 assert!(lib.errors.is_empty(), "{:#?}", lib.errors);
933 let lib = store.insert(lib);
934
935 let sources = SourceMap::new(
936 [(
937 "test".into(),
938 indoc! {"
939 namespace Test {
940 open Foo;
941 operation Main() : Unit {
942 Bar();
943 }
944 }
945 "}
946 .into(),
947 )],
948 None,
949 );
950 let unit = compile(
951 &store,
952 &[lib],
953 sources,
954 RuntimeCapabilityFlags::all(),
955 LanguageFeatures::default(),
956 );
957 expect![[r#"
958 [
959 Error(
960 Resolve(
961 Unimplemented(
962 "Bar",
963 Span {
964 lo: 69,
965 hi: 72,
966 },
967 ),
968 ),
969 ),
970 ]
971 "#]]
972 .assert_debug_eq(&unit.errors);
973}
974
975#[test]
976fn unimplemented_attribute_call_within_unit_error() {
977 let sources = SourceMap::new(
978 [(
979 "test".into(),
980 indoc! {"
981 namespace Foo {
982 @Unimplemented()
983 operation Bar() : Unit {}
984 operation Baz() : Unit {
985 Bar();
986 }
987 }
988 "}
989 .into(),
990 )],
991 None,
992 );
993 let unit = default_compile(sources);
994 expect![[r#"
995 [
996 Error(
997 Resolve(
998 Unimplemented(
999 "Bar",
1000 Span {
1001 lo: 104,
1002 hi: 107,
1003 },
1004 ),
1005 ),
1006 ),
1007 ]
1008 "#]]
1009 .assert_debug_eq(&unit.errors);
1010}
1011
1012#[test]
1013fn unimplemented_attribute_with_non_unit_expr_error() {
1014 let sources = SourceMap::new(
1015 [(
1016 "test".into(),
1017 indoc! {"
1018 namespace Foo {
1019 @Unimplemented(1)
1020 operation Bar() : Unit {}
1021 }
1022 "}
1023 .into(),
1024 )],
1025 None,
1026 );
1027 let unit = default_compile(sources);
1028 expect![[r#"
1029 [
1030 Error(
1031 Lower(
1032 InvalidAttrArgs(
1033 "()",
1034 Span {
1035 lo: 34,
1036 hi: 37,
1037 },
1038 ),
1039 ),
1040 ),
1041 ]
1042 "#]]
1043 .assert_debug_eq(&unit.errors);
1044}
1045
1046#[test]
1047fn unimplemented_attribute_avoids_ambiguous_error_with_duplicate_names_in_scope() {
1048 let lib_sources = SourceMap::new(
1049 [(
1050 "lib".into(),
1051 indoc! {"
1052 namespace Foo {
1053 @Unimplemented()
1054 operation Bar() : Unit {}
1055 }
1056 "}
1057 .into(),
1058 )],
1059 None,
1060 );
1061 let mut store = PackageStore::new(super::core());
1062 let lib = compile(
1063 &store,
1064 &[],
1065 lib_sources,
1066 RuntimeCapabilityFlags::all(),
1067 LanguageFeatures::default(),
1068 );
1069 assert!(lib.errors.is_empty(), "{:#?}", lib.errors);
1070 let lib = store.insert(lib);
1071
1072 let sources = SourceMap::new(
1073 [(
1074 "test".into(),
1075 indoc! {"
1076 namespace Dependency {
1077 operation Bar() : Unit {}
1078 }
1079 namespace Test {
1080 open Foo;
1081 open Dependency;
1082 operation Main() : Unit {
1083 Bar();
1084 }
1085 }
1086 "}
1087 .into(),
1088 )],
1089 None,
1090 );
1091 let unit = compile(
1092 &store,
1093 &[lib],
1094 sources,
1095 RuntimeCapabilityFlags::all(),
1096 LanguageFeatures::default(),
1097 );
1098 expect![[r#"
1099 []
1100 "#]]
1101 .assert_debug_eq(&unit.errors);
1102}
1103
1104#[test]
1105fn duplicate_intrinsic_from_dependency() {
1106 let lib_sources = SourceMap::new(
1107 [(
1108 "lib".into(),
1109 indoc! {"
1110 namespace Foo {
1111 operation Bar() : Unit { body intrinsic; }
1112 }
1113 "}
1114 .into(),
1115 )],
1116 None,
1117 );
1118
1119 let mut store = PackageStore::new(super::core());
1120 let lib = compile(
1121 &store,
1122 &[],
1123 lib_sources,
1124 RuntimeCapabilityFlags::all(),
1125 LanguageFeatures::default(),
1126 );
1127 assert!(lib.errors.is_empty(), "{:#?}", lib.errors);
1128 let lib = store.insert(lib);
1129
1130 let sources = SourceMap::new(
1131 [(
1132 "test".into(),
1133 indoc! {"
1134 namespace Test {
1135 operation Bar() : Unit { body intrinsic; }
1136 }
1137 "}
1138 .into(),
1139 )],
1140 None,
1141 );
1142
1143 let unit = compile(
1144 &store,
1145 &[lib],
1146 sources,
1147 RuntimeCapabilityFlags::all(),
1148 LanguageFeatures::default(),
1149 );
1150 expect![[r#"
1151 [
1152 Error(
1153 Resolve(
1154 DuplicateIntrinsic(
1155 "Bar",
1156 Span {
1157 lo: 31,
1158 hi: 34,
1159 },
1160 ),
1161 ),
1162 ),
1163 ]
1164 "#]]
1165 .assert_debug_eq(&unit.errors);
1166}
1167
1168#[test]
1169fn reject_use_qubit_block_syntax_if_preview_feature_is_on() {
1170 let mut store = PackageStore::new(super::core());
1171 let std = store.insert(super::std(&store, RuntimeCapabilityFlags::empty()));
1172 let sources = SourceMap::new(
1173 [(
1174 "test".into(),
1175 indoc! {"
1176 namespace Foo {
1177 open Microsoft.Quantum.Intrinsic;
1178 operation Main() : Unit {
1179 use q = Qubit() {
1180 // some qubit operation here
1181 // this should be a syntax error because
1182 // we have the v2 preview syntax feature enabled
1183 X(q);
1184 };
1185
1186 }
1187 }
1188 "}
1189 .into(),
1190 )],
1191 Some("Foo.Main()".into()),
1192 );
1193
1194 let unit = compile(
1195 &store,
1196 &[std],
1197 sources,
1198 RuntimeCapabilityFlags::empty(),
1199 LanguageFeatures::V2PreviewSyntax,
1200 );
1201 expect![[r#"
1202 [
1203 Error(
1204 Parse(
1205 Error(
1206 Token(
1207 Semi,
1208 Open(
1209 Brace,
1210 ),
1211 Span {
1212 lo: 119,
1213 hi: 120,
1214 },
1215 ),
1216 ),
1217 ),
1218 ),
1219 ]
1220 "#]]
1221 .assert_debug_eq(&unit.errors);
1222}
1223
1224#[test]
1225fn accept_use_qubit_block_syntax_if_preview_feature_is_off() {
1226 let mut store = PackageStore::new(super::core());
1227 let std = store.insert(super::std(&store, RuntimeCapabilityFlags::empty()));
1228 let sources = SourceMap::new(
1229 [(
1230 "test".into(),
1231 indoc! {"
1232 namespace Foo {
1233 open Microsoft.Quantum.Intrinsic;
1234 operation Main() : Unit {
1235 use q = Qubit() {
1236 // some qubit operation here
1237 // this should be a syntax error because
1238 // we have the v2 preview syntax feature enabled
1239 X(q);
1240 };
1241 }
1242 }
1243 "}
1244 .into(),
1245 )],
1246 Some("Foo.Main()".into()),
1247 );
1248
1249 let unit = compile(
1250 &store,
1251 &[std],
1252 sources,
1253 RuntimeCapabilityFlags::empty(),
1254 LanguageFeatures::default(),
1255 );
1256 assert!(unit.errors.is_empty(), "{:#?}", unit.errors);
1257}
1258