Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(295)

Side by Side Diff: packages/analyzer/test/src/task/strong/inferred_type_test.dart

Issue 1521693002: Roll Observatory deps (charted -> ^0.3.0) (Closed) Base URL: https://chromium.googlesource.com/external/github.com/dart-lang/observatory_pub_packages.git@master
Patch Set: Created 5 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file.
4
5 // TODO(jmesserly): this file needs to be refactored, it's a port from
6 // package:dev_compiler's tests
7 /// Tests for type inference.
8 library test.src.task.strong.inferred_type_test;
9
10 import 'package:unittest/unittest.dart';
11
12 import 'strong_test_helper.dart';
13
14 void main() {
15 // Error also expected when declared type is `int`.
16 testChecker('infer type on var', {
17 '/main.dart': '''
18 test1() {
19 int x = 3;
20 x = /*severe:StaticTypeError*/"hi";
21 }
22 '''
23 });
24
25 // If inferred type is `int`, error is also reported
26 testChecker('infer type on var 2', {
27 '/main.dart': '''
28 test2() {
29 var x = 3;
30 x = /*severe:StaticTypeError*/"hi";
31 }
32 '''
33 });
34
35 testChecker('No error when declared type is `num` and assigned null.', {
36 '/main.dart': '''
37 test1() {
38 num x = 3;
39 x = null;
40 }
41 '''
42 });
43
44 testChecker('do not infer type on dynamic', {
45 '/main.dart': '''
46 test() {
47 dynamic x = 3;
48 x = "hi";
49 }
50 '''
51 });
52
53 testChecker('do not infer type when initializer is null', {
54 '/main.dart': '''
55 test() {
56 var x = null;
57 x = "hi";
58 x = 3;
59 }
60 '''
61 });
62
63 testChecker('infer type on var from field', {
64 '/main.dart': '''
65 class A {
66 int x = 0;
67
68 test1() {
69 var a = x;
70 a = /*severe:StaticTypeError*/"hi";
71 a = 3;
72 var b = y;
73 b = /*severe:StaticTypeError*/"hi";
74 b = 4;
75 var c = z;
76 c = /*severe:StaticTypeError*/"hi";
77 c = 4;
78 }
79
80 int y; // field def after use
81 final z = 42; // should infer `int`
82 }
83 '''
84 });
85
86 testChecker('infer type on var from top-level', {
87 '/main.dart': '''
88 int x = 0;
89
90 test1() {
91 var a = x;
92 a = /*severe:StaticTypeError*/"hi";
93 a = 3;
94 var b = y;
95 b = /*severe:StaticTypeError*/"hi";
96 b = 4;
97 var c = z;
98 c = /*severe:StaticTypeError*/"hi";
99 c = 4;
100 }
101
102 int y = 0; // field def after use
103 final z = 42; // should infer `int`
104 '''
105 });
106
107 testChecker('do not infer field type when initializer is null', {
108 '/main.dart': '''
109 var x = null;
110 var y = 3;
111 class A {
112 static var x = null;
113 static var y = 3;
114
115 var x2 = null;
116 var y2 = 3;
117 }
118
119 test() {
120 x = "hi";
121 y = /*severe:StaticTypeError*/"hi";
122 A.x = "hi";
123 A.y = /*severe:StaticTypeError*/"hi";
124 new A().x2 = "hi";
125 new A().y2 = /*severe:StaticTypeError*/"hi";
126 }
127 '''
128 });
129
130 testChecker('infer from variables in non-cycle imports with flag', {
131 '/a.dart': '''
132 var x = 2;
133 ''',
134 '/main.dart': '''
135 import 'a.dart';
136 var y = x;
137
138 test1() {
139 x = /*severe:StaticTypeError*/"hi";
140 y = /*severe:StaticTypeError*/"hi";
141 }
142 '''
143 });
144
145 testChecker('infer from variables in non-cycle imports with flag 2', {
146 '/a.dart': '''
147 class A { static var x = 2; }
148 ''',
149 '/main.dart': '''
150 import 'a.dart';
151 class B { static var y = A.x; }
152
153 test1() {
154 A.x = /*severe:StaticTypeError*/"hi";
155 B.y = /*severe:StaticTypeError*/"hi";
156 }
157 '''
158 });
159
160 testChecker('infer from variables in cycle libs when flag is on', {
161 '/a.dart': '''
162 import 'main.dart';
163 var x = 2; // ok to infer
164 ''',
165 '/main.dart': '''
166 import 'a.dart';
167 var y = x; // now ok :)
168
169 test1() {
170 int t = 3;
171 t = x;
172 t = y;
173 }
174 '''
175 });
176
177 testChecker('infer from variables in cycle libs when flag is on 2', {
178 '/a.dart': '''
179 import 'main.dart';
180 class A { static var x = 2; }
181 ''',
182 '/main.dart': '''
183 import 'a.dart';
184 class B { static var y = A.x; }
185
186 test1() {
187 int t = 3;
188 t = A.x;
189 t = B.y;
190 }
191 '''
192 });
193
194 testChecker('can infer also from static and instance fields (flag on)', {
195 '/a.dart': '''
196 import 'b.dart';
197 class A {
198 static final a1 = B.b1;
199 final a2 = new B().b2;
200 }
201 ''',
202 '/b.dart': '''
203 class B {
204 static final b1 = 1;
205 final b2 = 1;
206 }
207 ''',
208 '/main.dart': '''
209 import "a.dart";
210
211 test1() {
212 int x = 0;
213 // inference in A now works.
214 x = A.a1;
215 x = new A().a2;
216 }
217 '''
218 });
219
220 testChecker('inference in cycles is deterministic', {
221 '/a.dart': '''
222 import 'b.dart';
223 class A {
224 static final a1 = B.b1;
225 final a2 = new B().b2;
226 }
227 ''',
228 '/b.dart': '''
229 class B {
230 static final b1 = 1;
231 final b2 = 1;
232 }
233 ''',
234 '/c.dart': '''
235 import "main.dart"; // creates a cycle
236
237 class C {
238 static final c1 = 1;
239 final c2 = 1;
240 }
241 ''',
242 '/e.dart': '''
243 import 'a.dart';
244 part 'e2.dart';
245
246 class E {
247 static final e1 = 1;
248 static final e2 = F.f1;
249 static final e3 = A.a1;
250 final e4 = 1;
251 final e5 = new F().f2;
252 final e6 = new A().a2;
253 }
254 ''',
255 '/f.dart': '''
256 part 'f2.dart';
257 ''',
258 '/e2.dart': '''
259 class F {
260 static final f1 = 1;
261 final f2 = 1;
262 }
263 ''',
264 '/main.dart': '''
265 import "a.dart";
266 import "c.dart";
267 import "e.dart";
268
269 class D {
270 static final d1 = A.a1 + 1;
271 static final d2 = C.c1 + 1;
272 final d3 = new A().a2;
273 final d4 = new C().c2;
274 }
275
276 test1() {
277 int x = 0;
278 // inference in A works, it's not in a cycle
279 x = A.a1;
280 x = new A().a2;
281
282 // Within a cycle we allow inference when the RHS is well known, but
283 // not when it depends on other fields within the cycle
284 x = C.c1;
285 x = D.d1;
286 x = D.d2;
287 x = new C().c2;
288 x = new D().d3;
289 x = /*info:DynamicCast*/new D().d4;
290
291
292 // Similarly if the library contains parts.
293 x = E.e1;
294 x = E.e2;
295 x = E.e3;
296 x = new E().e4;
297 x = /*info:DynamicCast*/new E().e5;
298 x = new E().e6;
299 x = F.f1;
300 x = new F().f2;
301 }
302 '''
303 });
304
305 testChecker(
306 'infer from complex expressions if the outer-most value is precise', {
307 '/main.dart': '''
308 class A { int x; B operator+(other) {} }
309 class B extends A { B(ignore); }
310 var a = new A();
311 // Note: it doesn't matter that some of these refer to 'x'.
312 var b = new B(x); // allocations
313 var c1 = [x]; // list literals
314 var c2 = const [];
315 var d = {'a': 'b'}; // map literals
316 var e = new A()..x = 3; // cascades
317 var f = 2 + 3; // binary expressions are OK if the left operand
318 // is from a library in a different strongest
319 // conected component.
320 var g = -3;
321 var h = new A() + 3;
322 var i = - new A();
323 var j = null as B;
324
325 test1() {
326 a = /*severe:StaticTypeError*/"hi";
327 a = new B(3);
328 b = /*severe:StaticTypeError*/"hi";
329 b = new B(3);
330 c1 = [];
331 c1 = /*severe:StaticTypeError*/{};
332 c2 = [];
333 c2 = /*severe:StaticTypeError*/{};
334 d = {};
335 d = /*severe:StaticTypeError*/3;
336 e = new A();
337 e = /*severe:StaticTypeError*/{};
338 f = 3;
339 f = /*severe:StaticTypeError*/false;
340 g = 1;
341 g = /*severe:StaticTypeError*/false;
342 h = /*severe:StaticTypeError*/false;
343 h = new B();
344 i = false;
345 j = new B();
346 j = /*severe:StaticTypeError*/false;
347 j = /*severe:StaticTypeError*/[];
348 }
349 '''
350 });
351
352 // but flags can enable this behavior.
353 testChecker('infer if complex expressions read possibly inferred field', {
354 '/a.dart': '''
355 class A {
356 var x = 3;
357 }
358 ''',
359 '/main.dart': '''
360 import 'a.dart';
361 class B {
362 var y = 3;
363 }
364 final t1 = new A();
365 final t2 = new A().x;
366 final t3 = new B();
367 final t4 = new B().y;
368
369 test1() {
370 int i = 0;
371 A a;
372 B b;
373 a = t1;
374 i = t2;
375 b = t3;
376 i = /*info:DynamicCast*/t4;
377 i = new B().y; // B.y was inferred though
378 }
379 '''
380 });
381
382 group('infer types on loop indices', () {
383 testChecker('foreach loop', {
384 '/main.dart': '''
385 class Foo {
386 int bar = 42;
387 }
388
389 class Bar<T extends Iterable<String>> {
390 void foo(T t) {
391 for (var i in t) {
392 int x = /*severe:StaticTypeError*/i;
393 }
394 }
395 }
396
397 class Baz<T, E extends Iterable<T>, S extends E> {
398 void foo(S t) {
399 for (var i in t) {
400 int x = /*severe:StaticTypeError*/i;
401 T y = i;
402 }
403 }
404 }
405
406 test() {
407 var list = <Foo>[];
408 for (var x in list) {
409 String y = /*severe:StaticTypeError*/x;
410 }
411
412 for (dynamic x in list) {
413 String y = /*info:DynamicCast*/x;
414 }
415
416 for (String x in /*severe:StaticTypeError*/list) {
417 String y = x;
418 }
419
420 var z;
421 for(z in list) {
422 String y = /*info:DynamicCast*/z;
423 }
424
425 Iterable iter = list;
426 for (Foo x in /*warning:DownCastComposite*/iter) {
427 var y = x;
428 }
429
430 dynamic iter2 = list;
431 for (Foo x in /*warning:DownCastComposite*/iter2) {
432 var y = x;
433 }
434
435 var map = <String, Foo>{};
436 // Error: map must be an Iterable.
437 for (var x in /*severe:StaticTypeError*/map) {
438 String y = /*info:DynamicCast*/x;
439 }
440
441 // We're not properly inferring that map.keys is an Iterable<String>
442 // and that x is a String.
443 for (var x in map.keys) {
444 String y = x;
445 }
446 }
447 '''
448 });
449
450 testChecker('for loop, with inference', {
451 '/main.dart': '''
452 test() {
453 for (var i = 0; i < 10; i++) {
454 int j = i + 1;
455 }
456 }
457 '''
458 });
459 });
460
461 testChecker('propagate inference to field in class', {
462 '/main.dart': '''
463 class A {
464 int x = 2;
465 }
466
467 test() {
468 var a = new A();
469 A b = a; // doesn't require down cast
470 print(a.x); // doesn't require dynamic invoke
471 print(a.x + 2); // ok to use in bigger expression
472 }
473 '''
474 });
475
476 testChecker('propagate inference to field in class dynamic warnings', {
477 '/main.dart': '''
478 class A {
479 int x = 2;
480 }
481
482 test() {
483 dynamic a = new A();
484 A b = /*info:DynamicCast*/a;
485 print(/*info:DynamicInvoke*/a.x);
486 print(/*info:DynamicInvoke*/(/*info:DynamicInvoke*/a.x) + 2);
487 }
488 '''
489 });
490
491 testChecker('propagate inference transitively', {
492 '/main.dart': '''
493 class A {
494 int x = 2;
495 }
496
497 test5() {
498 var a1 = new A();
499 a1.x = /*severe:StaticTypeError*/"hi";
500
501 A a2 = new A();
502 a2.x = /*severe:StaticTypeError*/"hi";
503 }
504 '''
505 });
506
507 testChecker('propagate inference transitively 2', {
508 '/main.dart': '''
509 class A {
510 int x = 42;
511 }
512
513 class B {
514 A a = new A();
515 }
516
517 class C {
518 B b = new B();
519 }
520
521 class D {
522 C c = new C();
523 }
524
525 void main() {
526 var d1 = new D();
527 print(d1.c.b.a.x);
528
529 D d2 = new D();
530 print(d2.c.b.a.x);
531 }
532 '''
533 });
534
535 group('infer type on overridden fields', () {
536 testChecker('2', {
537 '/main.dart': '''
538 class A {
539 int x = 2;
540 }
541
542 class B extends A {
543 get x => 3;
544 }
545
546 foo() {
547 String y = /*severe:StaticTypeError*/new B().x;
548 int z = new B().x;
549 }
550 '''
551 });
552
553 testChecker('4', {
554 '/main.dart': '''
555 class A {
556 int x = 2;
557 }
558
559 class B implements A {
560 get x => 3;
561 }
562
563 foo() {
564 String y = /*severe:StaticTypeError*/new B().x;
565 int z = new B().x;
566 }
567 '''
568 });
569 });
570
571 group('infer types on generic instantiations', () {
572 testChecker('infer', {
573 '/main.dart': '''
574 class A<T> {
575 T x;
576 }
577
578 class B implements A<int> {
579 /*severe:InvalidMethodOverride*/dynamic get x => 3;
580 }
581
582 foo() {
583 String y = /*info:DynamicCast*/new B().x;
584 int z = /*info:DynamicCast*/new B().x;
585 }
586 '''
587 });
588
589 testChecker('3', {
590 '/main.dart': '''
591 class A<T> {
592 T x;
593 T w;
594 }
595
596 class B implements A<int> {
597 get x => 3;
598 get w => /*severe:StaticTypeError*/"hello";
599 }
600
601 foo() {
602 String y = /*severe:StaticTypeError*/new B().x;
603 int z = new B().x;
604 }
605 '''
606 });
607
608 testChecker('4', {
609 '/main.dart': '''
610 class A<T> {
611 T x;
612 }
613
614 class B<E> extends A<E> {
615 E y;
616 get x => y;
617 }
618
619 foo() {
620 int y = /*severe:StaticTypeError*/new B<String>().x;
621 String z = new B<String>().x;
622 }
623 '''
624 });
625
626 testChecker('5', {
627 '/main.dart': '''
628 abstract class I<E> {
629 String m(a, String f(v, T e));
630 }
631
632 abstract class A<E> implements I<E> {
633 const A();
634 String m(a, String f(v, T e));
635 }
636
637 abstract class M {
638 int y;
639 }
640
641 class B<E> extends A<E> implements M {
642 const B();
643 int get y => 0;
644
645 m(a, f(v, T e)) {}
646 }
647
648 foo () {
649 int y = /*severe:StaticTypeError*/new B().m(null, null);
650 String z = new B().m(null, null);
651 }
652 '''
653 });
654 });
655
656 testChecker('infer type regardless of declaration order or cycles', {
657 '/b.dart': '''
658 import 'main.dart';
659
660 class B extends A { }
661 ''',
662 '/main.dart': '''
663 import 'b.dart';
664 class C extends B {
665 get x;
666 }
667 class A {
668 int get x;
669 }
670 foo () {
671 int y = new C().x;
672 String y = /*severe:StaticTypeError*/new C().x;
673 }
674 '''
675 });
676
677 // Note: this is a regression test for a non-deterministic behavior we used to
678 // have with inference in library cycles. If you see this test flake out,
679 // change `test` to `skip_test` and reopen bug #48.
680 testChecker('infer types on generic instantiations in library cycle', {
681 '/a.dart': '''
682 import 'main.dart';
683 abstract class I<E> {
684 A<E> m(a, String f(v, int e));
685 }
686 ''',
687 '/main.dart': '''
688 import 'a.dart';
689
690 abstract class A<E> implements I<E> {
691 const A();
692
693 E value;
694 }
695
696 abstract class M {
697 int y;
698 }
699
700 class B<E> extends A<E> implements M {
701 const B();
702 int get y => 0;
703
704 m(a, f(v, int e)) {}
705 }
706
707 foo () {
708 int y = /*severe:StaticTypeError*/new B<String>().m(null, null).value;
709 String z = new B<String>().m(null, null).value;
710 }
711 '''
712 });
713
714 group('do not infer overridden fields that explicitly say dynamic', () {
715 testChecker('infer', {
716 '/main.dart': '''
717 class A {
718 int x = 2;
719 }
720
721 class B implements A {
722 /*severe:InvalidMethodOverride*/dynamic get x => 3;
723 }
724
725 foo() {
726 String y = /*info:DynamicCast*/new B().x;
727 int z = /*info:DynamicCast*/new B().x;
728 }
729 '''
730 });
731 });
732
733 testChecker('conflicts can happen', {
734 '/main.dart': '''
735 class I1 {
736 int x;
737 }
738 class I2 extends I1 {
739 int y;
740 }
741
742 class A {
743 final I1 a;
744 }
745
746 class B {
747 final I2 a;
748 }
749
750 class C1 extends A implements B {
751 /*severe:InvalidMethodOverride,severe:InvalidMethodOverride*/get a => null;
752 }
753
754 // Still ambiguous
755 class C2 extends B implements A {
756 /*severe:InvalidMethodOverride,severe:InvalidMethodOverride*/get a => null;
757 }
758 '''
759 });
760
761 testChecker('conflicts can happen 2', {
762 '/main.dart': '''
763 class I1 {
764 int x;
765 }
766 class I2 {
767 int y;
768 }
769
770 class I3 implements I1, I2 {
771 int x;
772 int y;
773 }
774
775 class A {
776 final I1 a;
777 }
778
779 class B {
780 final I2 a;
781 }
782
783 class C1 extends A implements B {
784 I3 get a => null;
785 }
786
787 class C2 extends A implements B {
788 /*severe:InvalidMethodOverride,severe:InvalidMethodOverride*/get a => null;
789 }
790 '''
791 });
792
793 testChecker(
794 'infer from RHS only if it wont conflict with overridden fields', {
795 '/main.dart': '''
796 class A {
797 var x;
798 }
799
800 class B extends A {
801 var x = 2;
802 }
803
804 foo() {
805 String y = /*info:DynamicCast*/new B().x;
806 int z = /*info:DynamicCast*/new B().x;
807 }
808 '''
809 });
810
811 testChecker(
812 'infer from RHS only if it wont conflict with overridden fields 2', {
813 '/main.dart': '''
814 class A {
815 final x;
816 }
817
818 class B extends A {
819 final x = 2;
820 }
821
822 foo() {
823 String y = /*severe:StaticTypeError*/new B().x;
824 int z = new B().x;
825 }
826 '''
827 });
828
829 testChecker('infer correctly on multiple variables declared together', {
830 '/main.dart': '''
831 class A {
832 var x, y = 2, z = "hi";
833 }
834
835 class B extends A {
836 var x = 2, y = 3, z, w = 2;
837 }
838
839 foo() {
840 String s;
841 int i;
842
843 s = /*info:DynamicCast*/new B().x;
844 s = /*severe:StaticTypeError*/new B().y;
845 s = new B().z;
846 s = /*severe:StaticTypeError*/new B().w;
847
848 i = /*info:DynamicCast*/new B().x;
849 i = new B().y;
850 i = /*severe:StaticTypeError*/new B().z;
851 i = new B().w;
852 }
853 '''
854 });
855
856 testChecker('infer consts transitively', {
857 '/b.dart': '''
858 const b1 = 2;
859 ''',
860 '/a.dart': '''
861 import 'main.dart';
862 import 'b.dart';
863 const a1 = m2;
864 const a2 = b1;
865 ''',
866 '/main.dart': '''
867 import 'a.dart';
868 const m1 = a1;
869 const m2 = a2;
870
871 foo() {
872 int i;
873 i = m1;
874 }
875 '''
876 });
877
878 testChecker('infer statics transitively', {
879 '/b.dart': '''
880 final b1 = 2;
881 ''',
882 '/a.dart': '''
883 import 'main.dart';
884 import 'b.dart';
885 final a1 = m2;
886 class A {
887 static final a2 = b1;
888 }
889 ''',
890 '/main.dart': '''
891 import 'a.dart';
892 final m1 = a1;
893 final m2 = A.a2;
894
895 foo() {
896 int i;
897 i = m1;
898 }
899 '''
900 });
901
902 testChecker('infer statics transitively 2', {
903 '/main.dart': '''
904 const x1 = 1;
905 final x2 = 1;
906 final y1 = x1;
907 final y2 = x2;
908
909 foo() {
910 int i;
911 i = y1;
912 i = y2;
913 }
914 '''
915 });
916
917 testChecker('infer statics transitively 3', {
918 '/a.dart': '''
919 const a1 = 3;
920 const a2 = 4;
921 class A {
922 a3;
923 }
924 ''',
925 '/main.dart': '''
926 import 'a.dart' show a1, A;
927 import 'a.dart' as p show a2, A;
928 const t1 = 1;
929 const t2 = t1;
930 const t3 = a1;
931 const t4 = p.a2;
932 const t5 = A.a3;
933 const t6 = p.A.a3;
934
935 foo() {
936 int i;
937 i = t1;
938 i = t2;
939 i = t3;
940 i = t4;
941 }
942 '''
943 });
944
945 testChecker('infer statics with method invocations', {
946 '/a.dart': '''
947 m3(String a, String b, [a1,a2]) {}
948 ''',
949 '/main.dart': '''
950 import 'a.dart';
951 class T {
952 static final T foo = m1(m2(m3('', '')));
953 static T m1(String m) { return null; }
954 static String m2(e) { return ''; }
955 }
956
957
958 '''
959 });
960
961 testChecker('downwards inference: miscellaneous', {
962 '/main.dart': '''
963 typedef (T x);
964 class A<T> {
965 Function2<T> x;
966 A(this.x);
967 }
968 void main() {
969 { // Variables, nested literals
970 var x = "hello";
971 var y = 3;
972 void f(List<Map<int, String>> l) {};
973 f(/*info:InferredTypeLiteral*/[{y: x}]);
974 }
975 {
976 int f(int x) {};
977 A<int> a = /*info:InferredTypeAllocation*/new A(f);
978 }
979 }
980 '''
981 });
982
983 group('downwards inference on instance creations', () {
984 String info = 'info:InferredTypeAllocation';
985 String code = '''
986 class A<S, T> {
987 S x;
988 T y;
989 A(this.x, this.y);
990 A.named(this.x, this.y);
991 }
992
993 class B<S, T> extends A<T, S> {
994 B(S y, T x) : super(x, y);
995 B.named(S y, T x) : super.named(x, y);
996 }
997
998 class C<S> extends B<S, S> {
999 C(S a) : super(a, a);
1000 C.named(S a) : super.named(a, a);
1001 }
1002
1003 class D<S, T> extends B<T, int> {
1004 D(T a) : super(a, 3);
1005 D.named(T a) : super.named(a, 3);
1006 }
1007
1008 class E<S, T> extends A<C<S>, T> {
1009 E(T a) : super(null, a);
1010 }
1011
1012 class F<S, T> extends A<S, T> {
1013 F(S x, T y, {List<S> a, List<T> b}) : super(x, y);
1014 F.named(S x, T y, [S a, T b]) : super(a, b);
1015 }
1016
1017 void main() {
1018 {
1019 A<int, String> a0 = /*$info*/new A(3, "hello");
1020 A<int, String> a1 = /*$info*/new A.named(3, "hello");
1021 A<int, String> a2 = new A<int, String>(3, "hello");
1022 A<int, String> a3 = new A<int, String>.named(3, "hello");
1023 A<int, String> a4 = /*severe:StaticTypeError*/new A<int, dynamic>(3, " hello");
1024 A<int, String> a5 = /*severe:StaticTypeError*/new A<dynamic, dynamic>. named(3, "hello");
1025 }
1026 {
1027 A<int, String> a0 = /*severe:StaticTypeError*/new A("hello", 3);
1028 A<int, String> a1 = /*severe:StaticTypeError*/new A.named("hello", 3);
1029 }
1030 {
1031 A<int, String> a0 = /*$info*/new B("hello", 3);
1032 A<int, String> a1 = /*$info*/new B.named("hello", 3);
1033 A<int, String> a2 = new B<String, int>("hello", 3);
1034 A<int, String> a3 = new B<String, int>.named("hello", 3);
1035 A<int, String> a4 = /*severe:StaticTypeError*/new B<String, dynamic>(" hello", 3);
1036 A<int, String> a5 = /*severe:StaticTypeError*/new B<dynamic, dynamic>. named("hello", 3);
1037 }
1038 {
1039 A<int, String> a0 = /*severe:StaticTypeError*/new B(3, "hello");
1040 A<int, String> a1 = /*severe:StaticTypeError*/new B.named(3, "hello");
1041 }
1042 {
1043 A<int, int> a0 = /*$info*/new C(3);
1044 A<int, int> a1 = /*$info*/new C.named(3);
1045 A<int, int> a2 = new C<int>(3);
1046 A<int, int> a3 = new C<int>.named(3);
1047 A<int, int> a4 = /*severe:StaticTypeError*/new C<dynamic>(3);
1048 A<int, int> a5 = /*severe:StaticTypeError*/new C<dynamic>.named(3);
1049 }
1050 {
1051 A<int, int> a0 = /*severe:StaticTypeError*/new C("hello");
1052 A<int, int> a1 = /*severe:StaticTypeError*/new C.named("hello");
1053 }
1054 {
1055 A<int, String> a0 = /*$info*/new D("hello");
1056 A<int, String> a1 = /*$info*/new D.named("hello");
1057 A<int, String> a2 = new D<int, String>("hello");
1058 A<int, String> a3 = new D<String, String>.named("hello");
1059 A<int, String> a4 = /*severe:StaticTypeError*/new D<num, dynamic>("hel lo");
1060 A<int, String> a5 = /*severe:StaticTypeError*/new D<dynamic, dynamic>. named("hello");
1061 }
1062 {
1063 A<int, String> a0 = /*severe:StaticTypeError*/new D(3);
1064 A<int, String> a1 = /*severe:StaticTypeError*/new D.named(3);
1065 }
1066 { // Currently we only allow variable constraints. Test that we reject.
1067 A<C<int>, String> a0 = /*severe:StaticTypeError*/new E("hello");
1068 }
1069 { // Check named and optional arguments
1070 A<int, String> a0 = /*$info*/new F(3, "hello", a: [3], b: ["hello"]);
1071 A<int, String> a1 = /*severe:StaticTypeError*/new F(3, "hello", a: ["h ello"], b:[3]);
1072 A<int, String> a2 = /*$info*/new F.named(3, "hello", 3, "hello");
1073 A<int, String> a3 = /*$info*/new F.named(3, "hello");
1074 A<int, String> a4 = /*severe:StaticTypeError*/new F.named(3, "hello", "hello", 3);
1075 A<int, String> a5 = /*severe:StaticTypeError*/new F.named(3, "hello", "hello");
1076 }
1077 }
1078 ''';
1079 testChecker('infer downwards', {'/main.dart': code});
1080 });
1081
1082 group('downwards inference on list literals', () {
1083 String info = "info:InferredTypeLiteral";
1084 String code = '''
1085 void foo([List<String> list1 = /*$info*/const [],
1086 List<String> list2 = /*severe:StaticTypeError*/const [42]]) {
1087 }
1088
1089 void main() {
1090 {
1091 List<int> l0 = /*$info*/[];
1092 List<int> l1 = /*$info*/[3];
1093 List<int> l2 = /*severe:StaticTypeError*/["hello"];
1094 List<int> l3 = /*severe:StaticTypeError*/["hello", 3];
1095 }
1096 {
1097 List<dynamic> l0 = [];
1098 List<dynamic> l1 = [3];
1099 List<dynamic> l2 = ["hello"];
1100 List<dynamic> l3 = ["hello", 3];
1101 }
1102 {
1103 List<int> l0 = /*severe:StaticTypeError*/<num>[];
1104 List<int> l1 = /*severe:StaticTypeError*/<num>[3];
1105 List<int> l2 = /*severe:StaticTypeError*/<num>[/*severe:StaticTypeErro r*/"hello"];
1106 List<int> l3 = /*severe:StaticTypeError*/<num>[/*severe:StaticTypeErro r*/"hello", 3];
1107 }
1108 {
1109 Iterable<int> i0 = /*$info*/[];
1110 Iterable<int> i1 = /*$info*/[3];
1111 Iterable<int> i2 = /*severe:StaticTypeError*/["hello"];
1112 Iterable<int> i3 = /*severe:StaticTypeError*/["hello", 3];
1113 }
1114 {
1115 const List<int> c0 = /*$info*/const [];
1116 const List<int> c1 = /*$info*/const [3];
1117 const List<int> c2 = /*severe:StaticTypeError*/const ["hello"];
1118 const List<int> c3 = /*severe:StaticTypeError*/const ["hello", 3];
1119 }
1120 }
1121 ''';
1122 testChecker('infer downwards', {'/main.dart': code});
1123 });
1124
1125 group('downwards inference on function arguments', () {
1126 String info = "info:InferredTypeLiteral";
1127 String code = '''
1128 void f0(List<int> a) {};
1129 void f1({List<int> a}) {};
1130 void f2(Iterable<int> a) {};
1131 void f3(Iterable<Iterable<int>> a) {};
1132 void f4({Iterable<Iterable<int>> a}) {};
1133 void main() {
1134 f0(/*$info*/[]);
1135 f0(/*$info*/[3]);
1136 f0(/*severe:StaticTypeError*/["hello"]);
1137 f0(/*severe:StaticTypeError*/["hello", 3]);
1138
1139 f1(a: /*$info*/[]);
1140 f1(a: /*$info*/[3]);
1141 f1(a: /*severe:StaticTypeError*/["hello"]);
1142 f1(a: /*severe:StaticTypeError*/["hello", 3]);
1143
1144 f2(/*$info*/[]);
1145 f2(/*$info*/[3]);
1146 f2(/*severe:StaticTypeError*/["hello"]);
1147 f2(/*severe:StaticTypeError*/["hello", 3]);
1148
1149 f3(/*$info*/[]);
1150 f3(/*$info*/[[3]]);
1151 f3(/*severe:StaticTypeError*/[["hello"]]);
1152 f3(/*severe:StaticTypeError*/[["hello"], [3]]);
1153
1154 f4(a: /*$info*/[]);
1155 f4(a: /*$info*/[[3]]);
1156 f4(a: /*severe:StaticTypeError*/[["hello"]]);
1157 f4(a: /*severe:StaticTypeError*/[["hello"], [3]]);
1158 }
1159 ''';
1160 testChecker('infer downwards', {'/main.dart': code});
1161 });
1162
1163 group('downwards inference on map literals', () {
1164 String info = "info:InferredTypeLiteral";
1165 String code = '''
1166 void foo([Map<int, String> m1 = /*$info*/const {1: "hello"},
1167 Map<int, String> m1 = /*severe:StaticTypeError*/const {"hello": "world"}]) {
1168 }
1169 void main() {
1170 {
1171 Map<int, String> l0 = /*$info*/{};
1172 Map<int, String> l1 = /*$info*/{3: "hello"};
1173 Map<int, String> l2 = /*severe:StaticTypeError*/{"hello": "hello"};
1174 Map<int, String> l3 = /*severe:StaticTypeError*/{3: 3};
1175 Map<int, String> l4 = /*severe:StaticTypeError*/{3:"hello", "hello": 3 };
1176 }
1177 {
1178 Map<dynamic, dynamic> l0 = {};
1179 Map<dynamic, dynamic> l1 = {3: "hello"};
1180 Map<dynamic, dynamic> l2 = {"hello": "hello"};
1181 Map<dynamic, dynamic> l3 = {3: 3};
1182 Map<dynamic, dynamic> l4 = {3:"hello", "hello": 3};
1183 }
1184 {
1185 Map<dynamic, String> l0 = /*$info*/{};
1186 Map<dynamic, String> l1 = /*$info*/{3: "hello"};
1187 Map<dynamic, String> l2 = /*$info*/{"hello": "hello"};
1188 Map<dynamic, String> l3 = /*severe:StaticTypeError*/{3: 3};
1189 Map<dynamic, String> l4 = /*severe:StaticTypeError*/{3:"hello", "hello ": 3};
1190 }
1191 {
1192 Map<int, dynamic> l0 = /*$info*/{};
1193 Map<int, dynamic> l1 = /*$info*/{3: "hello"};
1194 Map<int, dynamic> l2 = /*severe:StaticTypeError*/{"hello": "hello"};
1195 Map<int, dynamic> l3 = /*$info*/{3: 3};
1196 Map<int, dynamic> l3 = /*severe:StaticTypeError*/{3:"hello", "hello": 3};
1197 }
1198 {
1199 Map<int, String> l0 = /*severe:StaticTypeError*/<num, dynamic>{};
1200 Map<int, String> l1 = /*severe:StaticTypeError*/<num, dynamic>{3: "hel lo"};
1201 Map<int, String> l3 = /*severe:StaticTypeError*/<num, dynamic>{3: 3};
1202 }
1203 {
1204 const Map<int, String> l0 = /*$info*/const {};
1205 const Map<int, String> l1 = /*$info*/const {3: "hello"};
1206 const Map<int, String> l2 = /*severe:StaticTypeError*/const {"hello": "hello"};
1207 const Map<int, String> l3 = /*severe:StaticTypeError*/const {3: 3};
1208 const Map<int, String> l4 = /*severe:StaticTypeError*/const {3:"hello" , "hello": 3};
1209 }
1210 }
1211 ''';
1212 testChecker('infer downwards', {'/main.dart': code});
1213 });
1214
1215 testChecker('downwards inference on function expressions', {
1216 '/main.dart': '''
1217 typedef T Function2<S, T>(S x);
1218
1219 void main () {
1220 {
1221 Function2<int, String> l0 = (int x) => null;
1222 Function2<int, String> l1 = (int x) => "hello";
1223 Function2<int, String> l2 = /*severe:StaticTypeError*/(String x) => "h ello";
1224 Function2<int, String> l3 = /*severe:StaticTypeError*/(int x) => 3;
1225 Function2<int, String> l4 = /*warning:UninferredClosure should be seve re:StaticTypeError*/(int x) {return 3};
1226 }
1227 {
1228 Function2<int, String> l0 = /*info:InferredTypeClosure*/(x) => null;
1229 Function2<int, String> l1 = /*info:InferredTypeClosure*/(x) => "hello" ;
1230 Function2<int, String> l2 = /*severe:StaticTypeError*/(x) => 3;
1231 Function2<int, String> l3 = /*warning:UninferredClosure should be seve re:StaticTypeError*/(x) {return 3};
1232 }
1233 {
1234 Function2<int, List<String>> l0 = (int x) => null;
1235 Function2<int, List<String>> l1 = /*info:InferredTypeClosure*/(int x) => ["hello"];
1236 Function2<int, List<String>> l2 = /*severe:StaticTypeError*/(String x) => ["hello"];
1237 Function2<int, List<String>> l3 = /*warning:UninferredClosure should b e severe:StaticTypeError*/(int x) => [3];
1238 Function2<int, List<String>> l4 = /*warning:UninferredClosure should b e severe:StaticTypeError*/(int x) {return [3]};
1239 }
1240 {
1241 Function2<int, int> l0 = /*info:InferredTypeClosure*/(x) => x;
1242 Function2<int, int> l1 = /*info:InferredTypeClosure*/(x) => /*info:Dyn amicInvoke should be pass*/x+1;
1243 Function2<int, String> l2 = /*info:InferredTypeClosure should be sever e:StaticTypeError*/(x) => x;
1244 Function2<int, String> l3 = /*info:InferredTypeClosure should be sever e:StaticTypeError*/(x) => /*info:DynamicInvoke should be pass*/x.substring(3);
1245 Function2<String, String> l4 = /*info:InferredTypeClosure*/(x) => /*in fo:DynamicInvoke should be pass*/x.substring(3);
1246 }
1247 }
1248 '''
1249 });
1250
1251 testChecker('inferred initializing formal checks default value', {
1252 '/main.dart': '''
1253 class Foo {
1254 var x = 1;
1255 Foo([this.x = /*severe:StaticTypeError*/"1"]);
1256 }'''
1257 });
1258
1259 group('quasi-generics', () {
1260 testChecker('dart:math min/max', {
1261 '/main.dart': '''
1262 import 'dart:math';
1263
1264 void printInt(int x) => print(x);
1265 void printDouble(double x) => print(x);
1266
1267 num myMax(num x, num y) => max(x, y);
1268
1269 main() {
1270 // Okay if static types match.
1271 printInt(max(1, 2));
1272 printInt(min(1, 2));
1273 printDouble(max(1.0, 2.0));
1274 printDouble(min(1.0, 2.0));
1275
1276 // No help for user-defined functions from num->num->num.
1277 printInt(/*info:DownCastImplicit*/myMax(1, 2));
1278 printInt(myMax(1, 2) as int);
1279
1280 // Mixing int and double means return type is num.
1281 printInt(/*info:DownCastImplicit*/max(1, 2.0));
1282 printInt(/*info:DownCastImplicit*/min(1, 2.0));
1283 printDouble(/*info:DownCastImplicit*/max(1, 2.0));
1284 printDouble(/*info:DownCastImplicit*/min(1, 2.0));
1285
1286 // Types other than int and double are not accepted.
1287 printInt(
1288 /*info:DownCastImplicit*/min(
1289 /*severe:StaticTypeError*/"hi",
1290 /*severe:StaticTypeError*/"there"));
1291 }
1292 '''
1293 });
1294
1295 testChecker('Iterable and Future', {
1296 '/main.dart': '''
1297 import 'dart:async';
1298
1299 Future<int> make(int x) => (/*info:InferredTypeAllocation*/new Future(() => x));
1300
1301 main() {
1302 Iterable<Future<int>> list = <int>[1, 2, 3].map(make);
1303 Future<List<int>> results = Future.wait(list);
1304 Future<String> results2 = results.then((List<int> list)
1305 => list.fold('', (String x, int y) => x + y.toString()));
1306 }
1307 '''
1308 });
1309 });
1310 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698