microsoft/qdk

Public

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

CodeCommitsIssuesPull requestsActionsInsightsSecurity
v1.0.33

Branches

Tags

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

Clone

HTTPS

Download ZIP

compiler/qsc_frontend/src/compile/tests.rs

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