microsoft/qdk

Public

mirrored fromhttps://github.com/microsoft/qdkAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
iadavis/pipeline-issue-debugging

Branches

Tags

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

Clone

HTTPS

Download ZIP

source/compiler/qsc_frontend/src/compile/tests.rs

1484lines · modecode

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