microsoft/qdk

Public

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

CodeCommitsIssuesPull requestsActionsInsightsSecurity
billt/revert-mimalloc

Branches

Tags

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

Clone

HTTPS

Download ZIP

compiler/qsc_frontend/src/resolve/tests.rs

2656lines · modecode

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4#![allow(clippy::needless_raw_string_hashes)]
5
6use super::{Error, Locals, Names, Res};
7use crate::{
8 compile,
9 compile::RuntimeCapabilityFlags,
10 resolve::{LocalKind, Resolver},
11};
12use expect_test::{expect, Expect};
13use indoc::indoc;
14use qsc_ast::{
15 assigner::Assigner as AstAssigner,
16 ast::{Ident, NodeId, Package, Path, TopLevelNode},
17 mut_visit::MutVisitor,
18 visit::{self, Visitor},
19};
20use qsc_data_structures::{language_features::LanguageFeatures, span::Span};
21use qsc_hir::assigner::Assigner as HirAssigner;
22use std::fmt::Write;
23
24struct Renamer<'a> {
25 names: &'a Names,
26 changes: Vec<(Span, Res)>,
27}
28
29impl<'a> Renamer<'a> {
30 fn new(names: &'a Names) -> Self {
31 Self {
32 names,
33 changes: Vec::new(),
34 }
35 }
36
37 fn rename(&self, input: &mut String) {
38 for (span, res) in self.changes.iter().rev() {
39 let name = match res {
40 Res::Item(item, _) => match item.package {
41 None => format!("item{}", item.item),
42 Some(package) => format!("package{package}_item{}", item.item),
43 },
44 Res::Local(node) => format!("local{node}"),
45 Res::PrimTy(prim) => format!("{prim:?}"),
46 Res::UnitTy => "Unit".to_string(),
47 Res::Param(id) => format!("param{id}"),
48 };
49 input.replace_range((span.lo as usize)..(span.hi as usize), &name);
50 }
51 }
52}
53
54impl Visitor<'_> for Renamer<'_> {
55 fn visit_path(&mut self, path: &Path) {
56 if let Some(&id) = self.names.get(path.id) {
57 self.changes.push((path.span, id));
58 } else {
59 visit::walk_path(self, path);
60 }
61 }
62
63 fn visit_ident(&mut self, ident: &Ident) {
64 if let Some(&id) = self.names.get(ident.id) {
65 self.changes.push((ident.span, id));
66 }
67 }
68}
69
70fn check(input: &str, expect: &Expect) {
71 expect.assert_eq(&resolve_names(input));
72}
73
74fn resolve_names(input: &str) -> String {
75 let (package, names, _, errors) = compile(input, LanguageFeatures::default());
76 let mut renamer = Renamer::new(&names);
77 renamer.visit_package(&package);
78 let mut output = input.to_string();
79 renamer.rename(&mut output);
80 if !errors.is_empty() {
81 output += "\n";
82 }
83 for error in &errors {
84 writeln!(output, "// {error:?}").expect("string should be writable");
85 }
86 output
87}
88
89fn compile(
90 input: &str,
91 language_features: LanguageFeatures,
92) -> (Package, Names, Locals, Vec<Error>) {
93 let (namespaces, parse_errors) = qsc_parse::namespaces(input, language_features);
94 assert!(parse_errors.is_empty(), "parse failed: {parse_errors:#?}");
95 let mut package = Package {
96 id: NodeId::default(),
97 nodes: namespaces
98 .into_iter()
99 .map(TopLevelNode::Namespace)
100 .collect::<Vec<_>>()
101 .into_boxed_slice(),
102 entry: None,
103 };
104
105 AstAssigner::new().visit_package(&mut package);
106
107 let mut cond_compile = compile::preprocess::Conditional::new(RuntimeCapabilityFlags::all());
108 cond_compile.visit_package(&mut package);
109 let dropped_names = cond_compile.into_names();
110
111 let mut assigner = HirAssigner::new();
112 let mut globals = super::GlobalTable::new();
113 let mut errors = globals.add_local_package(&mut assigner, &package);
114 let mut resolver = Resolver::new(globals, dropped_names);
115 resolver.with(&mut assigner).visit_package(&package);
116 let (names, locals, mut resolve_errors) = resolver.into_result();
117 errors.append(&mut resolve_errors);
118 (package, names, locals, errors)
119}
120
121#[test]
122fn global_callable() {
123 check(
124 indoc! {"
125 namespace Foo {
126 function A() : Unit {}
127
128 function B() : Unit {
129 A();
130 }
131 }
132 "},
133 &expect![[r#"
134 namespace item0 {
135 function item1() : Unit {}
136
137 function item2() : Unit {
138 item1();
139 }
140 }
141 "#]],
142 );
143}
144
145#[test]
146fn global_callable_recursive() {
147 check(
148 indoc! {
149 "namespace Foo {
150 function A() : Unit {
151 A();
152 }
153 }
154 "},
155 &expect![[r#"
156 namespace item0 {
157 function item1() : Unit {
158 item1();
159 }
160 }
161 "#]],
162 );
163}
164
165#[test]
166fn global_callable_internal() {
167 check(
168 indoc! {"
169 namespace Foo {
170 internal function A() : Unit {}
171
172 function B() : Unit {
173 A();
174 }
175 }
176 "},
177 &expect![[r#"
178 namespace item0 {
179 internal function item1() : Unit {}
180
181 function item2() : Unit {
182 item1();
183 }
184 }
185 "#]],
186 );
187}
188
189#[test]
190fn global_callable_duplicate_error() {
191 check(
192 indoc! {"
193 namespace Foo {
194 function A() : Unit {}
195 operation A() : Unit {}
196 }
197 "},
198 &expect![[r#"
199 namespace item0 {
200 function item1() : Unit {}
201 operation item2() : Unit {}
202 }
203
204 // Duplicate("A", "Foo", Span { lo: 57, hi: 58 })
205 "#]],
206 );
207}
208
209#[test]
210fn global_path() {
211 check(
212 indoc! {"
213 namespace Foo {
214 function A() : Unit {}
215 }
216
217 namespace Bar {
218 function B() : Unit {
219 Foo.A();
220 }
221 }
222 "},
223 &expect![[r#"
224 namespace item0 {
225 function item1() : Unit {}
226 }
227
228 namespace item2 {
229 function item3() : Unit {
230 item1();
231 }
232 }
233 "#]],
234 );
235}
236
237#[test]
238fn open_namespace() {
239 check(
240 indoc! {"
241 namespace Foo {
242 function A() : Unit {}
243 }
244
245 namespace Bar {
246 open Foo;
247
248 function B() : Unit {
249 A();
250 }
251 }
252 "},
253 &expect![[r#"
254 namespace item0 {
255 function item1() : Unit {}
256 }
257
258 namespace item2 {
259 open Foo;
260
261 function item3() : Unit {
262 item1();
263 }
264 }
265 "#]],
266 );
267}
268
269#[test]
270fn open_alias() {
271 check(
272 indoc! {"
273 namespace Foo {
274 function A() : Unit {}
275 }
276
277 namespace Bar {
278 open Foo as F;
279
280 function B() : Unit {
281 F.A();
282 }
283 }
284 "},
285 &expect![[r#"
286 namespace item0 {
287 function item1() : Unit {}
288 }
289
290 namespace item2 {
291 open Foo as F;
292
293 function item3() : Unit {
294 item1();
295 }
296 }
297 "#]],
298 );
299}
300
301#[test]
302fn prelude_callable() {
303 check(
304 indoc! {"
305 namespace Microsoft.Quantum.Core {
306 function A() : Unit {}
307 }
308
309 namespace Foo {
310 function B() : Unit {
311 A();
312 }
313 }
314 "},
315 &expect![[r#"
316 namespace item0 {
317 function item1() : Unit {}
318 }
319
320 namespace item2 {
321 function item3() : Unit {
322 item1();
323 }
324 }
325 "#]],
326 );
327}
328
329#[test]
330fn parent_namespace_shadows_prelude() {
331 check(
332 indoc! {"
333 namespace Microsoft.Quantum.Core {
334 function A() : Unit {}
335 }
336
337 namespace Foo {
338 function A() : Unit {}
339
340 function B() : Unit {
341 A();
342 }
343 }
344 "},
345 &expect![[r#"
346 namespace item0 {
347 function item1() : Unit {}
348 }
349
350 namespace item2 {
351 function item3() : Unit {}
352
353 function item4() : Unit {
354 item3();
355 }
356 }
357 "#]],
358 );
359}
360
361#[test]
362fn open_shadows_prelude() {
363 check(
364 indoc! {"
365 namespace Microsoft.Quantum.Core {
366 function A() : Unit {}
367 }
368
369 namespace Foo {
370 function A() : Unit {}
371 }
372
373 namespace Bar {
374 open Foo;
375
376 function B() : Unit {
377 A();
378 }
379 }
380 "},
381 &expect![[r#"
382 namespace item0 {
383 function item1() : Unit {}
384 }
385
386 namespace item2 {
387 function item3() : Unit {}
388 }
389
390 namespace item4 {
391 open Foo;
392
393 function item5() : Unit {
394 item3();
395 }
396 }
397 "#]],
398 );
399}
400
401#[test]
402fn ambiguous_prelude() {
403 check(
404 indoc! {"
405 namespace Microsoft.Quantum.Canon {
406 function A() : Unit {}
407 }
408
409 namespace Microsoft.Quantum.Core {
410 function A() : Unit {}
411 }
412
413 namespace Foo {
414 function B() : Unit {
415 A();
416 }
417 }
418 "},
419 &expect![[r#"
420 namespace item0 {
421 function item1() : Unit {}
422 }
423
424 namespace item2 {
425 function item3() : Unit {}
426 }
427
428 namespace item4 {
429 function item5() : Unit {
430 A();
431 }
432 }
433
434 // AmbiguousPrelude { name: "A", candidate_a: "Microsoft.Quantum.Canon", candidate_b: "Microsoft.Quantum.Core", span: Span { lo: 181, hi: 182 } }
435 "#]],
436 );
437}
438
439#[test]
440fn local_var() {
441 check(
442 indoc! {"
443 namespace Foo {
444 function A() : Int {
445 let x = 0;
446 x
447 }
448 }
449 "},
450 &expect![[r#"
451 namespace item0 {
452 function item1() : Int {
453 let local13 = 0;
454 local13
455 }
456 }
457 "#]],
458 );
459}
460
461#[test]
462fn shadow_local() {
463 check(
464 indoc! {"
465 namespace Foo {
466 function A() : Int {
467 let x = 0;
468 let y = {
469 let x = 1;
470 x
471 };
472 x + y
473 }
474 }
475 "},
476 &expect![[r#"
477 namespace item0 {
478 function item1() : Int {
479 let local13 = 0;
480 let local17 = {
481 let local22 = 1;
482 local22
483 };
484 local13 + local17
485 }
486 }
487 "#]],
488 );
489}
490
491#[test]
492fn callable_param() {
493 check(
494 indoc! {"
495 namespace Foo {
496 function A(x : Int) : Int {
497 x
498 }
499 }
500 "},
501 &expect![[r#"
502 namespace item0 {
503 function item1(local8 : Int) : Int {
504 local8
505 }
506 }
507 "#]],
508 );
509}
510
511#[test]
512fn spec_param() {
513 check(
514 indoc! {"
515 namespace Foo {
516 operation A(q : Qubit) : (Qubit[], Qubit) {
517 controlled (cs, ...) {
518 (cs, q)
519 }
520 }
521 }
522 "},
523 &expect![[r#"
524 namespace item0 {
525 operation item1(local8 : Qubit) : (Qubit[], Qubit) {
526 controlled (local23, ...) {
527 (local23, local8)
528 }
529 }
530 }
531 "#]],
532 );
533}
534
535#[test]
536fn spec_param_shadow_disallowed() {
537 check(
538 indoc! {"
539 namespace Foo {
540 operation A(qs : Qubit[]) : Qubit[] {
541 controlled (qs, ...) {
542 qs
543 }
544 body ... {
545 qs
546 }
547 }
548 }
549 "},
550 &expect![[r#"
551 namespace item0 {
552 operation item1(local8 : Qubit[]) : Qubit[] {
553 controlled (local20, ...) {
554 local20
555 }
556 body ... {
557 local8
558 }
559 }
560 }
561
562 // DuplicateBinding("qs", Span { lo: 78, hi: 80 })
563 "#]],
564 );
565}
566
567#[test]
568fn local_shadows_global() {
569 check(
570 indoc! {"
571 namespace Foo {
572 function x() : Unit {}
573
574 function y() : Int {
575 x();
576 let x = 1;
577 x
578 }
579 }
580 "},
581 &expect![[r#"
582 namespace item0 {
583 function item1() : Unit {}
584
585 function item2() : Int {
586 item1();
587 let local27 = 1;
588 local27
589 }
590 }
591 "#]],
592 );
593}
594
595#[test]
596fn shadow_same_block() {
597 check(
598 indoc! {"
599 namespace Foo {
600 function A() : Int {
601 let x = 0;
602 let x = x + 1;
603 x
604 }
605 }
606 "},
607 &expect![[r#"
608 namespace item0 {
609 function item1() : Int {
610 let local13 = 0;
611 let local17 = local13 + 1;
612 local17
613 }
614 }
615 "#]],
616 );
617}
618
619#[test]
620fn parent_namespace_shadows_open() {
621 check(
622 indoc! {"
623 namespace Foo {
624 function A() : Unit {}
625 }
626
627 namespace Bar {
628 open Foo;
629
630 function A() : Unit {}
631
632 function B() : Unit {
633 A();
634 }
635 }
636 "},
637 &expect![[r#"
638 namespace item0 {
639 function item1() : Unit {}
640 }
641
642 namespace item2 {
643 open Foo;
644
645 function item3() : Unit {}
646
647 function item4() : Unit {
648 item3();
649 }
650 }
651 "#]],
652 );
653}
654
655#[test]
656fn open_alias_shadows_global() {
657 check(
658 indoc! {"
659 namespace Foo {
660 function A() : Unit {}
661 }
662
663 namespace Bar {
664 function A() : Unit {}
665 }
666
667 namespace Baz {
668 open Foo as Bar;
669
670 function B() : Unit {
671 Bar.A();
672 }
673 }
674 "},
675 &expect![[r#"
676 namespace item0 {
677 function item1() : Unit {}
678 }
679
680 namespace item2 {
681 function item3() : Unit {}
682 }
683
684 namespace item4 {
685 open Foo as Bar;
686
687 function item5() : Unit {
688 item1();
689 }
690 }
691 "#]],
692 );
693}
694
695#[test]
696fn shadowing_disallowed_within_parameters() {
697 check(
698 indoc! {"
699 namespace Test {
700 operation Foo(x: Int, y: Double, x: Bool) : Unit {}
701 }
702 "},
703 &expect![[r#"
704 namespace item0 {
705 operation item1(local8: Int, local13: Double, local18: Bool) : Unit {}
706 }
707
708 // DuplicateBinding("x", Span { lo: 54, hi: 55 })
709 "#]],
710 );
711}
712
713#[test]
714fn shadowing_disallowed_within_local_binding() {
715 check(
716 indoc! {"
717 namespace Test {
718 operation Foo() : Unit {
719 let (first, second, first) = (1, 2, 3);
720 }
721 }
722 "},
723 &expect![[r#"
724 namespace item0 {
725 operation item1() : Unit {
726 let (local14, local16, local18) = (1, 2, 3);
727 }
728 }
729
730 // DuplicateBinding("first", Span { lo: 74, hi: 79 })
731 "#]],
732 );
733}
734
735#[test]
736fn shadowing_disallowed_within_for_loop() {
737 check(
738 indoc! {"
739 namespace Test {
740 operation Foo() : Unit {
741 for (key, val, key) in [(1, 1, 1)] {}
742 }
743 }
744 "},
745 &expect![[r#"
746 namespace item0 {
747 operation item1() : Unit {
748 for (local15, local17, local19) in [(1, 1, 1)] {}
749 }
750 }
751
752 // DuplicateBinding("key", Span { lo: 69, hi: 72 })
753 "#]],
754 );
755}
756
757#[test]
758fn shadowing_disallowed_within_lambda_param() {
759 check(
760 indoc! {"
761 namespace Test {
762 operation Foo() : Unit {
763 let f = (x, y, x) -> x + y + 1;
764 }
765 }
766 "},
767 &expect![[r#"
768 namespace item0 {
769 operation item1() : Unit {
770 let local13 = (local17, local19, local21) -> local21 + local19 + 1;
771 }
772 }
773
774 // DuplicateBinding("x", Span { lo: 69, hi: 70 })
775 "#]],
776 );
777}
778
779#[test]
780fn merged_aliases() {
781 check(
782 indoc! {"
783 namespace Foo {
784 function A() : Unit {}
785 }
786
787 namespace Bar {
788 function B() : Unit {}
789 }
790
791 namespace Baz {
792 open Foo as Alias;
793 open Bar as Alias;
794
795 function C() : Unit {
796 Alias.A();
797 Alias.B();
798 }
799 }
800 "},
801 &expect![[r#"
802 namespace item0 {
803 function item1() : Unit {}
804 }
805
806 namespace item2 {
807 function item3() : Unit {}
808 }
809
810 namespace item4 {
811 open Foo as Alias;
812 open Bar as Alias;
813
814 function item5() : Unit {
815 item1();
816 item3();
817 }
818 }
819 "#]],
820 );
821}
822
823#[test]
824fn ty_decl() {
825 check(
826 indoc! {"
827 namespace Foo {
828 newtype A = Unit;
829 function B(a : A) : Unit {}
830 }
831 "},
832 &expect![[r#"
833 namespace item0 {
834 newtype item1 = Unit;
835 function item2(local14 : item1) : Unit {}
836 }
837 "#]],
838 );
839}
840
841#[test]
842fn ty_decl_duplicate_error() {
843 check(
844 indoc! {"
845 namespace Foo {
846 newtype A = Unit;
847 newtype A = Bool;
848 }
849 "},
850 &expect![[r#"
851 namespace item0 {
852 newtype item1 = Unit;
853 newtype item2 = Bool;
854 }
855
856 // Duplicate("A", "Foo", Span { lo: 50, hi: 51 })
857 "#]],
858 );
859}
860
861#[test]
862fn ty_decl_duplicate_error_on_built_in_ty() {
863 check(
864 indoc! {"
865 namespace Microsoft.Quantum.Core {
866 newtype Pauli = Unit;
867 }
868 "},
869 &expect![[r#"
870 namespace item0 {
871 newtype item1 = Unit;
872 }
873
874 // Duplicate("Pauli", "Microsoft.Quantum.Core", Span { lo: 47, hi: 52 })
875 "#]],
876 );
877}
878
879#[test]
880fn ty_decl_in_ty_decl() {
881 check(
882 indoc! {"
883 namespace Foo {
884 newtype A = Unit;
885 newtype B = A;
886 }
887 "},
888 &expect![[r#"
889 namespace item0 {
890 newtype item1 = Unit;
891 newtype item2 = item1;
892 }
893 "#]],
894 );
895}
896
897#[test]
898fn ty_decl_recursive() {
899 check(
900 indoc! {"
901 namespace Foo {
902 newtype A = A;
903 }
904 "},
905 &expect![[r#"
906 namespace item0 {
907 newtype item1 = item1;
908 }
909 "#]],
910 );
911}
912
913#[test]
914fn ty_decl_cons() {
915 check(
916 indoc! {"
917 namespace Foo {
918 newtype A = Unit;
919
920 function B() : A {
921 A()
922 }
923 }
924 "},
925 &expect![[r#"
926 namespace item0 {
927 newtype item1 = Unit;
928
929 function item2() : item1 {
930 item1()
931 }
932 }
933 "#]],
934 );
935}
936
937#[test]
938fn unknown_term() {
939 check(
940 indoc! {"
941 namespace Foo {
942 function A() : Unit {
943 B();
944 }
945 }
946 "},
947 &expect![[r#"
948 namespace item0 {
949 function item1() : Unit {
950 B();
951 }
952 }
953
954 // NotFound("B", Span { lo: 50, hi: 51 })
955 "#]],
956 );
957}
958
959#[test]
960fn unknown_ty() {
961 check(
962 indoc! {"
963 namespace Foo {
964 function A(b : B) : Unit {}
965 }
966 "},
967 &expect![[r#"
968 namespace item0 {
969 function item1(local8 : B) : Unit {}
970 }
971
972 // NotFound("B", Span { lo: 35, hi: 36 })
973 "#]],
974 );
975}
976
977#[test]
978fn open_ambiguous_terms() {
979 check(
980 indoc! {"
981 namespace Foo {
982 function A() : Unit {}
983 }
984
985 namespace Bar {
986 function A() : Unit {}
987 }
988
989 namespace Baz {
990 open Foo;
991 open Bar;
992
993 function C() : Unit {
994 A();
995 }
996 }
997 "},
998 &expect![[r#"
999 namespace item0 {
1000 function item1() : Unit {}
1001 }
1002
1003 namespace item2 {
1004 function item3() : Unit {}
1005 }
1006
1007 namespace item4 {
1008 open Foo;
1009 open Bar;
1010
1011 function item5() : Unit {
1012 A();
1013 }
1014 }
1015
1016 // Ambiguous { name: "A", first_open: "Foo", second_open: "Bar", name_span: Span { lo: 171, hi: 172 }, first_open_span: Span { lo: 117, hi: 120 }, second_open_span: Span { lo: 131, hi: 134 } }
1017 "#]],
1018 );
1019}
1020
1021#[test]
1022fn open_ambiguous_tys() {
1023 check(
1024 indoc! {"
1025 namespace Foo {
1026 newtype A = Unit;
1027 }
1028
1029 namespace Bar {
1030 newtype A = Unit;
1031 }
1032
1033 namespace Baz {
1034 open Foo;
1035 open Bar;
1036
1037 function C(a : A) : Unit {}
1038 }
1039 "},
1040 &expect![[r#"
1041 namespace item0 {
1042 newtype item1 = Unit;
1043 }
1044
1045 namespace item2 {
1046 newtype item3 = Unit;
1047 }
1048
1049 namespace item4 {
1050 open Foo;
1051 open Bar;
1052
1053 function item5(local28 : A) : Unit {}
1054 }
1055
1056 // Ambiguous { name: "A", first_open: "Foo", second_open: "Bar", name_span: Span { lo: 146, hi: 147 }, first_open_span: Span { lo: 107, hi: 110 }, second_open_span: Span { lo: 121, hi: 124 } }
1057 "#]],
1058 );
1059}
1060
1061#[test]
1062fn merged_aliases_ambiguous_terms() {
1063 check(
1064 indoc! {"
1065 namespace Foo {
1066 function A() : Unit {}
1067 }
1068
1069 namespace Bar {
1070 function A() : Unit {}
1071 }
1072
1073 namespace Baz {
1074 open Foo as Alias;
1075 open Bar as Alias;
1076
1077 function C() : Unit {
1078 Alias.A();
1079 }
1080 }
1081 "},
1082 &expect![[r#"
1083 namespace item0 {
1084 function item1() : Unit {}
1085 }
1086
1087 namespace item2 {
1088 function item3() : Unit {}
1089 }
1090
1091 namespace item4 {
1092 open Foo as Alias;
1093 open Bar as Alias;
1094
1095 function item5() : Unit {
1096 Alias.A();
1097 }
1098 }
1099
1100 // Ambiguous { name: "A", first_open: "Foo", second_open: "Bar", name_span: Span { lo: 195, hi: 196 }, first_open_span: Span { lo: 117, hi: 120 }, second_open_span: Span { lo: 140, hi: 143 } }
1101 "#]],
1102 );
1103}
1104
1105#[test]
1106fn merged_aliases_ambiguous_tys() {
1107 check(
1108 indoc! {"
1109 namespace Foo {
1110 newtype A = Unit;
1111 }
1112
1113 namespace Bar {
1114 newtype A = Unit;
1115 }
1116
1117 namespace Baz {
1118 open Foo as Alias;
1119 open Bar as Alias;
1120
1121 function C(a : Alias.A) : Unit {}
1122 }
1123 "},
1124 &expect![[r#"
1125 namespace item0 {
1126 newtype item1 = Unit;
1127 }
1128
1129 namespace item2 {
1130 newtype item3 = Unit;
1131 }
1132
1133 namespace item4 {
1134 open Foo as Alias;
1135 open Bar as Alias;
1136
1137 function item5(local30 : Alias.A) : Unit {}
1138 }
1139
1140 // Ambiguous { name: "A", first_open: "Foo", second_open: "Bar", name_span: Span { lo: 170, hi: 171 }, first_open_span: Span { lo: 107, hi: 110 }, second_open_span: Span { lo: 130, hi: 133 } }
1141 "#]],
1142 );
1143}
1144
1145#[test]
1146fn lambda_param() {
1147 check(
1148 indoc! {"
1149 namespace Foo {
1150 function A() : Unit {
1151 let f = x -> x + 1;
1152 }
1153 }
1154 "},
1155 &expect![[r#"
1156 namespace item0 {
1157 function item1() : Unit {
1158 let local13 = local16 -> local16 + 1;
1159 }
1160 }
1161 "#]],
1162 );
1163}
1164
1165#[test]
1166fn lambda_shadows_local() {
1167 check(
1168 indoc! {"
1169 namespace Foo {
1170 function A() : Int {
1171 let x = 1;
1172 let f = x -> x + 1;
1173 x
1174 }
1175 }
1176 "},
1177 &expect![[r#"
1178 namespace item0 {
1179 function item1() : Int {
1180 let local13 = 1;
1181 let local17 = local20 -> local20 + 1;
1182 local13
1183 }
1184 }
1185 "#]],
1186 );
1187}
1188
1189#[test]
1190fn for_loop_range() {
1191 check(
1192 indoc! {"
1193 namespace Foo {
1194 function A() : Unit {
1195 for i in 0..9 {
1196 let _ = i;
1197 }
1198 }
1199 }
1200 "},
1201 &expect![[r#"
1202 namespace item0 {
1203 function item1() : Unit {
1204 for local14 in 0..9 {
1205 let _ = local14;
1206 }
1207 }
1208 }
1209 "#]],
1210 );
1211}
1212
1213#[test]
1214fn for_loop_var() {
1215 check(
1216 indoc! {"
1217 namespace Foo {
1218 function A(xs : Int[]) : Unit {
1219 for x in xs {
1220 let _ = x;
1221 }
1222 }
1223 }
1224 "},
1225 &expect![[r#"
1226 namespace item0 {
1227 function item1(local8 : Int[]) : Unit {
1228 for local20 in local8 {
1229 let _ = local20;
1230 }
1231 }
1232 }
1233 "#]],
1234 );
1235}
1236
1237#[test]
1238fn repeat_until() {
1239 check(
1240 indoc! {"
1241 namespace Foo {
1242 operation A() : Unit {
1243 mutable cond = false;
1244 repeat {
1245 set cond = true;
1246 } until cond;
1247 }
1248 }
1249 "},
1250 &expect![[r#"
1251 namespace item0 {
1252 operation item1() : Unit {
1253 mutable local13 = false;
1254 repeat {
1255 set local13 = true;
1256 } until local13;
1257 }
1258 }
1259 "#]],
1260 );
1261}
1262
1263#[test]
1264fn repeat_until_fixup() {
1265 check(
1266 indoc! {"
1267 namespace Foo {
1268 operation A() : Unit {
1269 mutable cond = false;
1270 repeat {
1271 set cond = false;
1272 } until cond
1273 fixup {
1274 set cond = true;
1275 }
1276 }
1277 }
1278 "},
1279 &expect![[r#"
1280 namespace item0 {
1281 operation item1() : Unit {
1282 mutable local13 = false;
1283 repeat {
1284 set local13 = false;
1285 } until local13
1286 fixup {
1287 set local13 = true;
1288 }
1289 }
1290 }
1291 "#]],
1292 );
1293}
1294
1295#[test]
1296fn repeat_until_fixup_scoping() {
1297 check(
1298 indoc! {"
1299 namespace Foo {
1300 operation A() : Unit {
1301 repeat {
1302 mutable cond = false;
1303 }
1304 until cond
1305 fixup {
1306 set cond = true;
1307 }
1308 }
1309 }"},
1310 &expect![[r#"
1311 namespace item0 {
1312 operation item1() : Unit {
1313 repeat {
1314 mutable local16 = false;
1315 }
1316 until cond
1317 fixup {
1318 set cond = true;
1319 }
1320 }
1321 }
1322 // NotFound("cond", Span { lo: 118, hi: 122 })
1323 // NotFound("cond", Span { lo: 155, hi: 159 })
1324 "#]],
1325 );
1326}
1327
1328#[test]
1329fn use_qubit() {
1330 check(
1331 indoc! {"
1332 namespace Foo {
1333 operation X(q : Qubit) : Unit {
1334 body intrinsic;
1335 }
1336 operation A() : Unit {
1337 use q = Qubit();
1338 X(q);
1339 }
1340 }
1341 "},
1342 &expect![[r#"
1343 namespace item0 {
1344 operation item1(local8 : Qubit) : Unit {
1345 body intrinsic;
1346 }
1347 operation item2() : Unit {
1348 use local26 = Qubit();
1349 item1(local26);
1350 }
1351 }
1352 "#]],
1353 );
1354}
1355
1356#[test]
1357fn use_qubit_block() {
1358 check(
1359 indoc! {"
1360 namespace Foo {
1361 operation X(q : Qubit) : Unit {
1362 body intrinsic;
1363 }
1364 operation A() : Unit {
1365 use q = Qubit() {
1366 X(q);
1367 }
1368 }
1369 }
1370 "},
1371 &expect![[r#"
1372 namespace item0 {
1373 operation item1(local8 : Qubit) : Unit {
1374 body intrinsic;
1375 }
1376 operation item2() : Unit {
1377 use local26 = Qubit() {
1378 item1(local26);
1379 }
1380 }
1381 }
1382 "#]],
1383 );
1384}
1385
1386#[test]
1387fn use_qubit_block_qubit_restricted_to_block_scope() {
1388 check(
1389 indoc! {"
1390 namespace Foo {
1391 operation X(q : Qubit) : Unit {
1392 body intrinsic;
1393 }
1394 operation A() : Unit {
1395 use q = Qubit() {
1396 X(q);
1397 }
1398 X(q);
1399 }
1400 }
1401 "},
1402 &expect![[r#"
1403 namespace item0 {
1404 operation item1(local8 : Qubit) : Unit {
1405 body intrinsic;
1406 }
1407 operation item2() : Unit {
1408 use local26 = Qubit() {
1409 item1(local26);
1410 }
1411 item1(q);
1412 }
1413 }
1414
1415 // NotFound("q", Span { lo: 173, hi: 174 })
1416 "#]],
1417 );
1418}
1419
1420#[test]
1421fn local_function() {
1422 check(
1423 indoc! {"
1424 namespace A {
1425 function Foo() : Int {
1426 function Bar() : Int { 2 }
1427 Bar() + 1
1428 }
1429 }
1430 "},
1431 &expect![[r#"
1432 namespace item0 {
1433 function item1() : Int {
1434 function item2() : Int { 2 }
1435 item2() + 1
1436 }
1437 }
1438 "#]],
1439 );
1440}
1441
1442#[test]
1443fn local_function_use_before_declare() {
1444 check(
1445 indoc! {"
1446 namespace A {
1447 function Foo() : () {
1448 Bar();
1449 function Bar() : () {}
1450 }
1451 }
1452 "},
1453 &expect![[r#"
1454 namespace item0 {
1455 function item1() : () {
1456 item2();
1457 function item2() : () {}
1458 }
1459 }
1460 "#]],
1461 );
1462}
1463
1464#[test]
1465fn local_function_is_really_local() {
1466 check(
1467 indoc! {"
1468 namespace A {
1469 function Foo() : () {
1470 function Bar() : () {}
1471 Bar();
1472 }
1473
1474 function Baz() : () { Bar(); }
1475 }
1476 "},
1477 &expect![[r#"
1478 namespace item0 {
1479 function item1() : () {
1480 function item3() : () {}
1481 item3();
1482 }
1483
1484 function item2() : () { Bar(); }
1485 }
1486
1487 // NotFound("Bar", Span { lo: 119, hi: 122 })
1488 "#]],
1489 );
1490}
1491
1492#[test]
1493fn local_function_is_not_closure() {
1494 check(
1495 indoc! {"
1496 namespace A {
1497 function Foo() : () {
1498 let x = 2;
1499 function Bar() : Int { x }
1500 }
1501 }
1502 "},
1503 &expect![[r#"
1504 namespace item0 {
1505 function item1() : () {
1506 let local11 = 2;
1507 function item2() : Int { x }
1508 }
1509 }
1510
1511 // NotFound("x", Span { lo: 90, hi: 91 })
1512 "#]],
1513 );
1514}
1515
1516#[test]
1517fn local_type() {
1518 check(
1519 indoc! {"
1520 namespace A {
1521 function Foo() : () {
1522 newtype Bar = Int;
1523 let x = Bar(5);
1524 }
1525 }
1526 "},
1527 &expect![[r#"
1528 namespace item0 {
1529 function item1() : () {
1530 newtype item2 = Int;
1531 let local18 = item2(5);
1532 }
1533 }
1534 "#]],
1535 );
1536}
1537
1538#[test]
1539fn local_open() {
1540 check(
1541 indoc! {"
1542 namespace A { function Foo() : () { open B; Bar(); } }
1543 namespace B { function Bar() : () {} }
1544 "},
1545 &expect![[r#"
1546 namespace item0 { function item1() : () { open B; item3(); } }
1547 namespace item2 { function item3() : () {} }
1548 "#]],
1549 );
1550}
1551
1552#[test]
1553fn local_open_shadows_parent_item() {
1554 check(
1555 indoc! {"
1556 namespace A {
1557 function Bar() : () {}
1558 function Foo() : () { open B; Bar(); }
1559 }
1560
1561 namespace B { function Bar() : () {} }
1562 "},
1563 &expect![[r#"
1564 namespace item0 {
1565 function item1() : () {}
1566 function item2() : () { open B; item4(); }
1567 }
1568
1569 namespace item3 { function item4() : () {} }
1570 "#]],
1571 );
1572}
1573
1574#[test]
1575fn local_open_shadows_parent_open() {
1576 check(
1577 indoc! {"
1578 namespace A {
1579 open B;
1580 function Foo() : () { open C; Bar(); }
1581 }
1582
1583 namespace B { function Bar() : () {} }
1584 namespace C { function Bar() : () {} }
1585 "},
1586 &expect![[r#"
1587 namespace item0 {
1588 open B;
1589 function item1() : () { open C; item5(); }
1590 }
1591
1592 namespace item2 { function item3() : () {} }
1593 namespace item4 { function item5() : () {} }
1594 "#]],
1595 );
1596}
1597
1598#[test]
1599fn update_array_index_var() {
1600 check(
1601 indoc! {"
1602 namespace A {
1603 function Foo() : () {
1604 let xs = [2];
1605 let i = 0;
1606 let ys = xs w/ i <- 3;
1607 }
1608 }
1609 "},
1610 &expect![[r#"
1611 namespace item0 {
1612 function item1() : () {
1613 let local11 = [2];
1614 let local16 = 0;
1615 let local20 = local11 w/ local16 <- 3;
1616 }
1617 }
1618 "#]],
1619 );
1620}
1621
1622#[test]
1623fn update_array_index_expr() {
1624 check(
1625 indoc! {"
1626 namespace A {
1627 function Foo() : () {
1628 let xs = [2];
1629 let i = 0;
1630 let ys = xs w/ i + 1 <- 3;
1631 }
1632 }
1633 "},
1634 &expect![[r#"
1635 namespace item0 {
1636 function item1() : () {
1637 let local11 = [2];
1638 let local16 = 0;
1639 let local20 = local11 w/ local16 + 1 <- 3;
1640 }
1641 }
1642 "#]],
1643 );
1644}
1645
1646#[test]
1647fn update_udt_known_field_name() {
1648 check(
1649 indoc! {"
1650 namespace A {
1651 newtype Pair = (First : Int, Second : Int);
1652
1653 function Foo() : () {
1654 let p = Pair(1, 2);
1655 let q = p w/ First <- 3;
1656 }
1657 }
1658 "},
1659 &expect![[r#"
1660 namespace item0 {
1661 newtype item1 = (First : Int, Second : Int);
1662
1663 function item2() : () {
1664 let local24 = item1(1, 2);
1665 let local34 = local24 w/ First <- 3;
1666 }
1667 }
1668 "#]],
1669 );
1670}
1671
1672#[test]
1673fn update_udt_known_field_name_expr() {
1674 check(
1675 indoc! {"
1676 namespace A {
1677 newtype Pair = (First : Int, Second : Int);
1678
1679 function Foo() : () {
1680 let p = Pair(1, 2);
1681 let q = p w/ First + 1 <- 3;
1682 }
1683 }
1684 "},
1685 &expect![[r#"
1686 namespace item0 {
1687 newtype item1 = (First : Int, Second : Int);
1688
1689 function item2() : () {
1690 let local24 = item1(1, 2);
1691 let local34 = local24 w/ First + 1 <- 3;
1692 }
1693 }
1694
1695 // NotFound("First", Span { lo: 138, hi: 143 })
1696 "#]],
1697 );
1698}
1699
1700#[test]
1701fn update_udt_unknown_field_name() {
1702 check(
1703 indoc! {"
1704 namespace A {
1705 newtype Pair = (First : Int, Second : Int);
1706
1707 function Foo() : () {
1708 let p = Pair(1, 2);
1709 let q = p w/ Third <- 3;
1710 }
1711 }
1712 "},
1713 &expect![[r#"
1714 namespace item0 {
1715 newtype item1 = (First : Int, Second : Int);
1716
1717 function item2() : () {
1718 let local24 = item1(1, 2);
1719 let local34 = local24 w/ Third <- 3;
1720 }
1721 }
1722 "#]],
1723 );
1724}
1725
1726#[test]
1727fn update_udt_unknown_field_name_known_global() {
1728 check(
1729 indoc! {"
1730 namespace A {
1731 newtype Pair = (First : Int, Second : Int);
1732
1733 function Third() : () {}
1734
1735 function Foo() : () {
1736 let p = Pair(1, 2);
1737 let q = p w/ Third <- 3;
1738 }
1739 }
1740 "},
1741 &expect![[r#"
1742 namespace item0 {
1743 newtype item1 = (First : Int, Second : Int);
1744
1745 function item2() : () {}
1746
1747 function item3() : () {
1748 let local30 = item1(1, 2);
1749 let local40 = local30 w/ Third <- 3;
1750 }
1751 }
1752 "#]],
1753 );
1754}
1755
1756#[test]
1757fn unknown_namespace() {
1758 check(
1759 indoc! {"
1760 namespace A {
1761 open Microsoft.Quantum.Fake;
1762 }
1763 "},
1764 &expect![[r#"
1765 namespace item0 {
1766 open Microsoft.Quantum.Fake;
1767 }
1768
1769 // NotFound("Microsoft.Quantum.Fake", Span { lo: 23, hi: 45 })
1770 "#]],
1771 );
1772}
1773
1774#[test]
1775fn empty_namespace_works() {
1776 check(
1777 indoc! {"
1778 namespace A {
1779 open B;
1780 function foo(): Unit{}
1781 }
1782 namespace B {}
1783 "},
1784 &expect![[r#"
1785 namespace item0 {
1786 open B;
1787 function item1(): Unit{}
1788 }
1789 namespace item2 {}
1790 "#]],
1791 );
1792}
1793
1794#[test]
1795fn cyclic_namespace_dependency_supported() {
1796 check(
1797 indoc! {"
1798 namespace A {
1799 open B;
1800 operation Foo() : Unit {
1801 Bar();
1802 }
1803 }
1804 namespace B {
1805 open A;
1806 operation Bar() : Unit {
1807 Foo();
1808 }
1809 }
1810 "},
1811 &expect![[r#"
1812 namespace item0 {
1813 open B;
1814 operation item1() : Unit {
1815 item3();
1816 }
1817 }
1818 namespace item2 {
1819 open A;
1820 operation item3() : Unit {
1821 item1();
1822 }
1823 }
1824 "#]],
1825 );
1826}
1827
1828#[test]
1829fn bind_items_in_repeat() {
1830 check(
1831 indoc! {"
1832 namespace A {
1833 operation B() : Unit {
1834 repeat {
1835 function C() : Unit {}
1836 } until false
1837 fixup {
1838 function D() : Unit {}
1839 }
1840 }
1841 }
1842 "},
1843 &expect![[r#"
1844 namespace item0 {
1845 operation item1() : Unit {
1846 repeat {
1847 function item2() : Unit {}
1848 } until false
1849 fixup {
1850 function item3() : Unit {}
1851 }
1852 }
1853 }
1854 "#]],
1855 );
1856}
1857
1858#[test]
1859fn bind_items_in_qubit_use_block() {
1860 check(
1861 indoc! {"
1862 namespace A {
1863 operation B() : Unit {
1864 use q = Qubit() {
1865 function C() : Unit {}
1866 }
1867 }
1868 }
1869 "},
1870 &expect![[r#"
1871 namespace item0 {
1872 operation item1() : Unit {
1873 use local13 = Qubit() {
1874 function item2() : Unit {}
1875 }
1876 }
1877 }
1878 "#]],
1879 );
1880}
1881
1882#[test]
1883fn use_bound_item_in_another_bound_item() {
1884 check(
1885 indoc! {"
1886 namespace A {
1887 function B() : Unit {
1888 function C() : Unit {
1889 D();
1890 }
1891 function D() : Unit {}
1892 }
1893 }
1894 "},
1895 &expect![[r#"
1896 namespace item0 {
1897 function item1() : Unit {
1898 function item2() : Unit {
1899 item3();
1900 }
1901 function item3() : Unit {}
1902 }
1903 }
1904 "#]],
1905 );
1906}
1907
1908#[test]
1909fn use_unbound_generic() {
1910 check(
1911 indoc! {"
1912 namespace A {
1913 function B<'T>(x: 'U) : 'U {
1914 x
1915 }
1916 }
1917 "},
1918 &expect![[r#"
1919 namespace item0 {
1920 function item1<param0>(local9: 'U) : 'U {
1921 local9
1922 }
1923 }
1924
1925 // NotFound("'U", Span { lo: 36, hi: 38 })
1926 // NotFound("'U", Span { lo: 42, hi: 44 })
1927 "#]],
1928 );
1929}
1930#[test]
1931fn resolve_local_generic() {
1932 check(
1933 indoc! {"
1934 namespace A {
1935 function B<'T>(x: 'T) : 'T {
1936 x
1937 }
1938 }
1939 "},
1940 &expect![[r#"
1941 namespace item0 {
1942 function item1<param0>(local9: param0) : param0 {
1943 local9
1944 }
1945 }
1946 "#]],
1947 );
1948}
1949
1950#[test]
1951fn dropped_callable() {
1952 check(
1953 indoc! {"
1954 namespace A {
1955 @Config(Base)
1956 function Dropped() : Unit {}
1957
1958 function B() : Unit {
1959 Dropped();
1960 }
1961 }
1962 "},
1963 &expect![[r#"
1964 namespace item0 {
1965 @Config(Base)
1966 function Dropped() : Unit {}
1967
1968 function item1() : Unit {
1969 Dropped();
1970 }
1971 }
1972
1973 // NotAvailable("Dropped", "A.Dropped", Span { lo: 100, hi: 107 })
1974 "#]],
1975 );
1976}
1977
1978#[test]
1979fn multiple_definition_dropped_is_not_found() {
1980 check(
1981 indoc! {"
1982 namespace A {
1983 @Config(Unrestricted)
1984 operation B() : Unit {}
1985 @Config(Base)
1986 operation B() : Unit {}
1987 @Config(Base)
1988 operation C() : Unit {}
1989 @Config(Unrestricted)
1990 operation C() : Unit {}
1991 }
1992 namespace D {
1993 operation E() : Unit {
1994 B();
1995 C();
1996 }
1997 operation F() : Unit {
1998 open A;
1999 B();
2000 C();
2001 }
2002 }
2003 "},
2004 &expect![[r#"
2005 namespace item0 {
2006 @Config(Unrestricted)
2007 operation item1() : Unit {}
2008 @Config(Base)
2009 operation B() : Unit {}
2010 @Config(Base)
2011 operation C() : Unit {}
2012 @Config(Unrestricted)
2013 operation item2() : Unit {}
2014 }
2015 namespace item3 {
2016 operation item4() : Unit {
2017 B();
2018 C();
2019 }
2020 operation item5() : Unit {
2021 open A;
2022 item1();
2023 item2();
2024 }
2025 }
2026
2027 // NotFound("B", Span { lo: 265, hi: 266 })
2028 // NotFound("C", Span { lo: 278, hi: 279 })
2029 "#]],
2030 );
2031}
2032
2033#[test]
2034fn disallow_duplicate_intrinsic() {
2035 check(
2036 indoc! {"
2037 namespace A {
2038 operation B() : Unit {
2039 body intrinsic;
2040 }
2041 }
2042 namespace B {
2043 operation B() : Unit {
2044 body intrinsic;
2045 }
2046 }
2047 "},
2048 &expect![[r#"
2049 namespace item0 {
2050 operation item1() : Unit {
2051 body intrinsic;
2052 }
2053 }
2054 namespace item2 {
2055 operation item3() : Unit {
2056 body intrinsic;
2057 }
2058 }
2059
2060 // DuplicateIntrinsic("B", Span { lo: 101, hi: 102 })
2061 "#]],
2062 );
2063}
2064
2065#[test]
2066fn disallow_duplicate_intrinsic_and_non_intrinsic_collision() {
2067 check(
2068 indoc! {"
2069 namespace A {
2070 internal operation C() : Unit {
2071 body intrinsic;
2072 }
2073 }
2074 namespace B {
2075 operation C() : Unit {}
2076 }
2077 namespace B {
2078 operation C() : Unit {
2079 body intrinsic;
2080 }
2081 }
2082 "},
2083 &expect![[r#"
2084 namespace item0 {
2085 internal operation item1() : Unit {
2086 body intrinsic;
2087 }
2088 }
2089 namespace item2 {
2090 operation item3() : Unit {}
2091 }
2092 namespace item4 {
2093 operation item5() : Unit {
2094 body intrinsic;
2095 }
2096 }
2097
2098 // Duplicate("C", "B", Span { lo: 154, hi: 155 })
2099 // DuplicateIntrinsic("C", Span { lo: 154, hi: 155 })
2100 "#]],
2101 );
2102}
2103
2104#[allow(clippy::cast_possible_truncation)]
2105fn check_locals(input: &str, expect: &Expect) {
2106 let parts = input.split('↘').collect::<Vec<_>>();
2107 assert_eq!(
2108 parts.len(),
2109 2,
2110 "input must contain exactly one cursor marker"
2111 );
2112 let cursor_offset = parts[0].len() as u32;
2113 let source = parts.join("");
2114
2115 let (_, _, locals, _) = compile(&source, LanguageFeatures::default());
2116
2117 let locals = locals.get_all_at_offset(cursor_offset);
2118 let actual = locals.iter().fold(String::new(), |mut output, l| {
2119 let _ = writeln!(
2120 output,
2121 "{} ({})",
2122 l.name,
2123 match l.kind {
2124 LocalKind::Item(item_id) => item_id.to_string(),
2125 LocalKind::TyParam(param_id) => format!("ty_param {param_id}"),
2126 LocalKind::Var(node_id) => format!("var {node_id}"),
2127 }
2128 );
2129 output
2130 });
2131
2132 expect.assert_eq(&actual);
2133}
2134
2135#[test]
2136fn get_locals_vars() {
2137 check_locals(
2138 indoc! {"
2139 namespace Foo {
2140 function A() : Int {
2141 let x = 0;
2142
2143 let y = 0;
2144 }
2145 }
2146 "},
2147 &expect![[r#"
2148 x (var 13)
2149 "#]],
2150 );
2151}
2152
2153#[test]
2154fn get_locals_vars_shadowing_same_scope() {
2155 check_locals(
2156 indoc! {r#"
2157 namespace Foo {
2158 function A() : Int {
2159 let x = 0;
2160 let x = "foo";
2161
2162 }
2163 }
2164 "#},
2165 &expect![[r#"
2166 x (var 17)
2167 "#]],
2168 );
2169}
2170
2171#[test]
2172fn get_locals_vars_parent_scope() {
2173 check_locals(
2174 indoc! {r#"
2175 namespace Foo {
2176 function A() : Int {
2177 let x = 0;
2178 {
2179 let y = 0;
2180
2181 }
2182 }
2183 }
2184 "#},
2185 &expect![[r#"
2186 y (var 20)
2187 x (var 13)
2188 "#]],
2189 );
2190}
2191
2192#[test]
2193fn get_locals_params() {
2194 check_locals(
2195 indoc! {r#"
2196 namespace Foo {
2197 function A(x : Int) : Int {
2198
2199 }
2200 }
2201 "#},
2202 &expect![[r#"
2203 x (var 8)
2204 "#]],
2205 );
2206}
2207
2208#[test]
2209fn get_locals_spec_params() {
2210 check_locals(
2211 indoc! {"
2212 namespace Foo {
2213 operation A(q : Qubit) : (Qubit[], Qubit) {
2214 controlled (cs, ...) {
2215
2216 }
2217 }
2218 }
2219 "},
2220 &expect![[r#"
2221 cs (var 23)
2222 q (var 8)
2223 "#]],
2224 );
2225}
2226
2227#[test]
2228fn get_locals_before_binding() {
2229 check_locals(
2230 indoc! {"
2231 namespace Foo {
2232 function A() : Unit {
2233 let y = 0;
2234 let x = { ↘ };
2235 }
2236 }
2237 "},
2238 &expect![[r#"
2239 y (var 13)
2240 "#]],
2241 );
2242}
2243
2244#[test]
2245fn get_locals_lambda_params() {
2246 check_locals(
2247 indoc! {"
2248 namespace Foo {
2249 function A() : Unit {
2250 let y = 0;
2251 let f = x -> { ↘ };
2252 }
2253 }
2254 "},
2255 &expect![[r#"
2256 x (var 20)
2257 y (var 13)
2258 "#]],
2259 );
2260}
2261
2262#[test]
2263fn get_locals_for_loop() {
2264 check_locals(
2265 indoc! {"
2266 namespace Foo {
2267 function A() : Unit {
2268 for x in 0..1 {
2269
2270 }
2271 }
2272 }
2273 "},
2274 &expect![[r#"
2275 x (var 14)
2276 "#]],
2277 );
2278}
2279
2280#[test]
2281fn get_locals_for_loop_before_binding() {
2282 check_locals(
2283 indoc! {"
2284 namespace Foo {
2285 function A() : Unit {
2286 for x in 0..{ ↘ } {
2287 }
2288 }
2289 }
2290 "},
2291 &expect![""],
2292 );
2293}
2294
2295#[test]
2296fn get_locals_items() {
2297 check_locals(
2298 indoc! {"
2299 namespace Foo {
2300 function A() : Unit {
2301
2302 function B() : Unit {}
2303 newtype Bar = String;
2304 }
2305 }
2306 "},
2307 &expect![[r#"
2308 Bar (Item 3)
2309 B (Item 2)
2310 "#]],
2311 );
2312}
2313
2314#[test]
2315fn get_locals_local_item_hide_parent_scope_variables() {
2316 check_locals(
2317 indoc! {"
2318 namespace Foo {
2319 function A() : Unit {
2320 let x = 3;
2321 function B() : Unit {
2322 let y = 3;
2323
2324 }
2325 }
2326 }
2327 "},
2328 &expect![[r#"
2329 y (var 26)
2330 B (Item 2)
2331 "#]],
2332 );
2333}
2334
2335#[test]
2336fn get_locals_shadow_parent_scope() {
2337 check_locals(
2338 indoc! {r#"
2339 namespace Foo {
2340 function A() : Unit {
2341 let x = "foo";
2342 {
2343 let x = 0;
2344
2345 }
2346 }
2347 }
2348 "#},
2349 &expect![[r#"
2350 x (var 20)
2351 "#]],
2352 );
2353}
2354
2355#[test]
2356fn get_locals_type_params() {
2357 check_locals(
2358 indoc! {"
2359 namespace Foo {
2360 function A<'T>(t: 'T) : Unit {
2361 {
2362
2363 }
2364 }
2365 }
2366 "},
2367 &expect![[r#"
2368 t (var 9)
2369 'T (ty_param 0)
2370 "#]],
2371 );
2372}
2373
2374#[test]
2375fn get_locals_block_scope_boundary() {
2376 check_locals(
2377 indoc! {"
2378 namespace Foo {
2379 function A() : Int {
2380 {
2381 let x = 0;
2382 }↘
2383 }
2384 }
2385 "},
2386 &expect![""],
2387 );
2388}
2389
2390#[test]
2391fn get_locals_block_scope_boundary_begin() {
2392 check_locals(
2393 indoc! {"
2394 namespace Foo {
2395 function A() : Int {
2396 ↘{
2397 function Bar(): Unit {}
2398 }
2399 }
2400 }
2401 "},
2402 &expect![""],
2403 );
2404}
2405
2406#[test]
2407fn use_after_scope() {
2408 check(
2409 indoc! {"
2410 namespace Foo {
2411 function A() : Unit {
2412 {
2413 let x = 42;
2414 }
2415 x; // x should not be accessible here
2416 }
2417 }
2418 "},
2419 &expect![[r#"
2420 namespace item0 {
2421 function item1() : Unit {
2422 {
2423 let local16 = 42;
2424 }
2425 x; // x should not be accessible here
2426 }
2427 }
2428
2429 // NotFound("x", Span { lo: 94, hi: 95 })
2430 "#]],
2431 );
2432}
2433
2434#[test]
2435fn nested_function_definition() {
2436 check(
2437 indoc! {"
2438 namespace Foo {
2439 function A() : Unit {
2440 function B() : Unit {
2441 function C() : Unit {}
2442 C();
2443 }
2444 B();
2445 }
2446 }
2447 "},
2448 &expect![[r#"
2449 namespace item0 {
2450 function item1() : Unit {
2451 function item2() : Unit {
2452 function item3() : Unit {}
2453 item3();
2454 }
2455 item2();
2456 }
2457 }
2458 "#]],
2459 );
2460}
2461
2462#[test]
2463fn variable_in_nested_blocks() {
2464 check(
2465 indoc! {"
2466 namespace Foo {
2467 function A() : Unit {
2468 {
2469 let x = 10;
2470 {
2471 let y = x + 5;
2472 y; // Should be accessible
2473 }
2474 y; // Should not be accessible
2475 }
2476 }
2477 }
2478 "},
2479 &expect![[r#"
2480 namespace item0 {
2481 function item1() : Unit {
2482 {
2483 let local16 = 10;
2484 {
2485 let local23 = local16 + 5;
2486 local23; // Should be accessible
2487 }
2488 y; // Should not be accessible
2489 }
2490 }
2491 }
2492
2493 // NotFound("y", Span { lo: 190, hi: 191 })
2494 "#]],
2495 );
2496}
2497
2498#[test]
2499fn function_call_with_namespace_alias() {
2500 check(
2501 indoc! {"
2502 namespace Foo {
2503 function A() : Unit {}
2504 }
2505 namespace Bar {
2506 open Foo as F;
2507 function B() : Unit {
2508 F.A();
2509 }
2510 }
2511 "},
2512 &expect![[r#"
2513 namespace item0 {
2514 function item1() : Unit {}
2515 }
2516 namespace item2 {
2517 open Foo as F;
2518 function item3() : Unit {
2519 item1();
2520 }
2521 }
2522 "#]],
2523 );
2524}
2525
2526#[test]
2527fn type_alias_in_function_scope() {
2528 check(
2529 indoc! {"
2530 namespace Foo {
2531 function A() : Unit {
2532 newtype MyInt = Int;
2533 let x : MyInt = MyInt(5);
2534 }
2535 function B() : Unit {
2536 let z: MyInt = MyInt(5); // this should be a different type (and unresolved)
2537 }
2538 }
2539 "},
2540 &expect![[r#"
2541 namespace item0 {
2542 function item1() : Unit {
2543 newtype item3 = Int;
2544 let local20 : item3 = item3(5);
2545 }
2546 function item2() : Unit {
2547 let local40: MyInt = MyInt(5); // this should be a different type (and unresolved)
2548 }
2549 }
2550
2551 // NotFound("MyInt", Span { lo: 152, hi: 157 })
2552 // NotFound("MyInt", Span { lo: 160, hi: 165 })
2553 "#]],
2554 );
2555}
2556
2557#[test]
2558fn lambda_inside_lambda() {
2559 check(
2560 indoc! {"
2561 namespace Foo {
2562 function A() : Unit {
2563 let f = () -> {
2564 let g = (x) -> x + 1;
2565 g(10);
2566 };
2567 f();
2568 }
2569 }
2570 "},
2571 &expect![[r#"
2572 namespace item0 {
2573 function item1() : Unit {
2574 let local13 = () -> {
2575 let local20 = (local24) -> local24 + 1;
2576 local20(10);
2577 };
2578 local13();
2579 }
2580 }
2581 "#]],
2582 );
2583}
2584
2585#[test]
2586fn nested_namespaces_with_same_function_name() {
2587 check(
2588 indoc! {"
2589 namespace Foo {
2590 function A() : Unit {}
2591 }
2592 namespace Bar {
2593 function A() : Unit {}
2594 function B() : Unit {
2595 Foo.A();
2596 A(); // Should call Bar.A without needing to qualify
2597 }
2598 }
2599 "},
2600 &expect![[r#"
2601 namespace item0 {
2602 function item1() : Unit {}
2603 }
2604 namespace item2 {
2605 function item3() : Unit {}
2606 function item4() : Unit {
2607 item1();
2608 item3(); // Should call Bar.A without needing to qualify
2609 }
2610 }
2611 "#]],
2612 );
2613}
2614
2615#[test]
2616fn newtype_with_invalid_field_type() {
2617 check(
2618 indoc! {"
2619 namespace Foo {
2620 newtype Complex = (Re: Real, Im: Imaginary); // Imaginary is not a valid type
2621 }
2622 "},
2623 &expect![[r#"
2624 namespace item0 {
2625 newtype item1 = (Re: Real, Im: Imaginary); // Imaginary is not a valid type
2626 }
2627
2628 // NotFound("Real", Span { lo: 43, hi: 47 })
2629 // NotFound("Imaginary", Span { lo: 53, hi: 62 })
2630 "#]],
2631 );
2632}
2633
2634#[test]
2635fn newtype_with_tuple_destructuring() {
2636 check(
2637 indoc! {"
2638 namespace Foo {
2639 newtype Pair = (First: Int, Second: Int);
2640 function Destructure(pair: Pair) : Int {
2641 let (first, second) = pair;
2642 first + second
2643 }
2644 }
2645 "},
2646 &expect![[r#"
2647 namespace item0 {
2648 newtype item1 = (First: Int, Second: Int);
2649 function item2(local21: item1) : Int {
2650 let (local32, local34) = local21;
2651 local32 + local34
2652 }
2653 }
2654 "#]],
2655 );
2656}
2657