OLD | NEW |
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 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 | 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. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 /// Tests for type inference. | 5 /// Tests for type inference. |
6 library dev_compiler.test.inferred_type_test; | 6 library dev_compiler.test.inferred_type_test; |
7 | 7 |
8 import 'package:test/test.dart'; | 8 import 'package:test/test.dart'; |
9 | 9 |
10 import '../testing.dart'; | 10 import '../testing.dart'; |
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
143 y = /*severe:StaticTypeError*/"hi"; | 143 y = /*severe:StaticTypeError*/"hi"; |
144 A.x = "hi"; | 144 A.x = "hi"; |
145 A.y = /*severe:StaticTypeError*/"hi"; | 145 A.y = /*severe:StaticTypeError*/"hi"; |
146 new A().x2 = "hi"; | 146 new A().x2 = "hi"; |
147 new A().y2 = /*severe:StaticTypeError*/"hi"; | 147 new A().y2 = /*severe:StaticTypeError*/"hi"; |
148 } | 148 } |
149 ''' | 149 ''' |
150 }); | 150 }); |
151 | 151 |
152 testChecker( | 152 testChecker( |
153 'do not infer from variables if flag is off', | |
154 { | |
155 '/main.dart': ''' | |
156 var x = 2; | |
157 var y = x; | |
158 | |
159 test1() { | |
160 x = /*severe:StaticTypeError*/"hi"; | |
161 y = "hi"; | |
162 } | |
163 ''' | |
164 }, | |
165 inferTransitively: false); | |
166 | |
167 testChecker( | |
168 'do not infer from variables if flag is off 2', | |
169 { | |
170 '/main.dart': ''' | |
171 class A { | |
172 static var x = 2; | |
173 static var y = A.x; | |
174 } | |
175 | |
176 test1() { | |
177 A.x = /*severe:StaticTypeError*/"hi"; | |
178 A.y = "hi"; | |
179 } | |
180 ''' | |
181 }, | |
182 inferTransitively: false); | |
183 | |
184 testChecker( | |
185 'do not infer from variables in non-cycle imports if flag is off', | |
186 { | |
187 '/a.dart': ''' | |
188 var x = 2; | |
189 ''', | |
190 '/main.dart': ''' | |
191 import 'a.dart'; | |
192 var y = x; | |
193 | |
194 test1() { | |
195 x = /*severe:StaticTypeError*/"hi"; | |
196 y = "hi"; | |
197 } | |
198 ''' | |
199 }, | |
200 inferTransitively: false); | |
201 | |
202 testChecker( | |
203 'do not infer from variables in non-cycle imports if flag is off 2', | |
204 { | |
205 '/a.dart': ''' | |
206 class A { static var x = 2; } | |
207 ''', | |
208 '/main.dart': ''' | |
209 import 'a.dart'; | |
210 class B { static var y = A.x; } | |
211 | |
212 test1() { | |
213 A.x = /*severe:StaticTypeError*/"hi"; | |
214 B.y = "hi"; | |
215 } | |
216 ''' | |
217 }, | |
218 inferTransitively: false); | |
219 | |
220 testChecker( | |
221 'infer from variables in non-cycle imports with flag', | 153 'infer from variables in non-cycle imports with flag', |
222 { | 154 { |
223 '/a.dart': ''' | 155 '/a.dart': ''' |
224 var x = 2; | 156 var x = 2; |
225 ''', | 157 ''', |
226 '/main.dart': ''' | 158 '/main.dart': ''' |
227 import 'a.dart'; | 159 import 'a.dart'; |
228 var y = x; | 160 var y = x; |
229 | 161 |
230 test1() { | 162 test1() { |
(...skipping 16 matching lines...) Expand all Loading... |
247 | 179 |
248 test1() { | 180 test1() { |
249 A.x = /*severe:StaticTypeError*/"hi"; | 181 A.x = /*severe:StaticTypeError*/"hi"; |
250 B.y = /*severe:StaticTypeError*/"hi"; | 182 B.y = /*severe:StaticTypeError*/"hi"; |
251 } | 183 } |
252 ''' | 184 ''' |
253 }, | 185 }, |
254 inferTransitively: true); | 186 inferTransitively: true); |
255 | 187 |
256 testChecker( | 188 testChecker( |
257 'do not infer from variables in cycle libs when flag is off', | |
258 { | |
259 '/a.dart': ''' | |
260 import 'main.dart'; | |
261 var x = 2; // ok to infer | |
262 ''', | |
263 '/main.dart': ''' | |
264 import 'a.dart'; | |
265 var y = x; // not ok to infer yet | |
266 | |
267 test1() { | |
268 int t = 3; | |
269 t = x; | |
270 t = /*info:DynamicCast*/y; | |
271 } | |
272 ''' | |
273 }, | |
274 inferTransitively: false); | |
275 | |
276 testChecker( | |
277 'do not infer from variables in cycle libs when flag is off 2', | |
278 { | |
279 '/a.dart': ''' | |
280 import 'main.dart'; | |
281 class A { static var x = 2; } | |
282 ''', | |
283 '/main.dart': ''' | |
284 import 'a.dart'; | |
285 class B { static var y = A.x; } | |
286 | |
287 test1() { | |
288 int t = 3; | |
289 t = A.x; | |
290 t = /*info:DynamicCast*/B.y; | |
291 } | |
292 ''' | |
293 }, | |
294 inferTransitively: false); | |
295 | |
296 testChecker( | |
297 'infer from variables in cycle libs when flag is on', | 189 'infer from variables in cycle libs when flag is on', |
298 { | 190 { |
299 '/a.dart': ''' | 191 '/a.dart': ''' |
300 import 'main.dart'; | 192 import 'main.dart'; |
301 var x = 2; // ok to infer | 193 var x = 2; // ok to infer |
302 ''', | 194 ''', |
303 '/main.dart': ''' | 195 '/main.dart': ''' |
304 import 'a.dart'; | 196 import 'a.dart'; |
305 var y = x; // now ok :) | 197 var y = x; // now ok :) |
306 | 198 |
(...skipping 20 matching lines...) Expand all Loading... |
327 test1() { | 219 test1() { |
328 int t = 3; | 220 int t = 3; |
329 t = A.x; | 221 t = A.x; |
330 t = B.y; | 222 t = B.y; |
331 } | 223 } |
332 ''' | 224 ''' |
333 }, | 225 }, |
334 inferTransitively: true); | 226 inferTransitively: true); |
335 | 227 |
336 testChecker( | 228 testChecker( |
337 'do not infer from static and instance fields when flag is off', | |
338 { | |
339 '/a.dart': ''' | |
340 import 'b.dart'; | |
341 class A { | |
342 static final a1 = B.b1; | |
343 final a2 = new B().b2; | |
344 } | |
345 ''', | |
346 '/b.dart': ''' | |
347 class B { | |
348 static final b1 = 1; | |
349 final b2 = 1; | |
350 } | |
351 ''', | |
352 '/main.dart': ''' | |
353 import "a.dart"; | |
354 | |
355 test1() { | |
356 int x = 0; | |
357 // inference in A disabled (flag is off) | |
358 x = /*info:DynamicCast*/A.a1; | |
359 x = /*info:DynamicCast*/new A().a2; | |
360 } | |
361 ''' | |
362 }, | |
363 inferTransitively: false); | |
364 | |
365 testChecker( | |
366 'can infer also from static and instance fields (flag on)', | 229 'can infer also from static and instance fields (flag on)', |
367 { | 230 { |
368 '/a.dart': ''' | 231 '/a.dart': ''' |
369 import 'b.dart'; | 232 import 'b.dart'; |
370 class A { | 233 class A { |
371 static final a1 = B.b1; | 234 static final a1 = B.b1; |
372 final a2 = new B().b2; | 235 final a2 = new B().b2; |
373 } | 236 } |
374 ''', | 237 ''', |
375 '/b.dart': ''' | 238 '/b.dart': ''' |
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
519 h = /*severe:StaticTypeError*/false; | 382 h = /*severe:StaticTypeError*/false; |
520 h = new B(); | 383 h = new B(); |
521 i = false; | 384 i = false; |
522 j = new B(); | 385 j = new B(); |
523 j = /*severe:StaticTypeError*/false; | 386 j = /*severe:StaticTypeError*/false; |
524 j = /*severe:StaticTypeError*/[]; | 387 j = /*severe:StaticTypeError*/[]; |
525 } | 388 } |
526 ''' | 389 ''' |
527 }); | 390 }); |
528 | 391 |
529 testChecker( | |
530 'do not infer if complex expressions read possibly inferred field', | |
531 { | |
532 '/a.dart': ''' | |
533 class A { | |
534 var x = 3; | |
535 } | |
536 ''', | |
537 '/main.dart': ''' | |
538 import 'a.dart'; | |
539 class B { | |
540 var y = 3; | |
541 } | |
542 final t1 = new A(); | |
543 final t2 = new A().x; | |
544 final t3 = new B(); | |
545 final t4 = new B().y; | |
546 | |
547 test1() { | |
548 int i = 0; | |
549 A a; | |
550 B b; | |
551 a = t1; | |
552 i = /*info:DynamicCast*/t2; | |
553 b = t3; | |
554 i = /*info:DynamicCast*/t4; | |
555 i = new B().y; // B.y was inferred though | |
556 } | |
557 ''' | |
558 }, | |
559 inferTransitively: false); | |
560 | |
561 // but flags can enable this behavior. | 392 // but flags can enable this behavior. |
562 testChecker( | 393 testChecker( |
563 'infer if complex expressions read possibly inferred field', | 394 'infer if complex expressions read possibly inferred field', |
564 { | 395 { |
565 '/a.dart': ''' | 396 '/a.dart': ''' |
566 class A { | 397 class A { |
567 var x = 3; | 398 var x = 3; |
568 } | 399 } |
569 ''', | 400 ''', |
570 '/main.dart': ''' | 401 '/main.dart': ''' |
(...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
722 print(d1.c.b.a.x); | 553 print(d1.c.b.a.x); |
723 | 554 |
724 D d2 = new D(); | 555 D d2 = new D(); |
725 print(d2.c.b.a.x); | 556 print(d2.c.b.a.x); |
726 } | 557 } |
727 ''' | 558 ''' |
728 }); | 559 }); |
729 | 560 |
730 group('infer type on overridden fields', () { | 561 group('infer type on overridden fields', () { |
731 testChecker( | 562 testChecker( |
732 '1', | |
733 { | |
734 '/main.dart': ''' | |
735 class A { | |
736 int x = 2; | |
737 } | |
738 | |
739 class B extends A { | |
740 /*severe:InvalidMethodOverride*/get x => 3; | |
741 } | |
742 | |
743 foo() { | |
744 String y = /*info:DynamicCast*/new B().x; | |
745 int z = /*info:DynamicCast*/new B().x; | |
746 } | |
747 ''' | |
748 }, | |
749 inferFromOverrides: false); | |
750 | |
751 testChecker( | |
752 '2', | 563 '2', |
753 { | 564 { |
754 '/main.dart': ''' | 565 '/main.dart': ''' |
755 class A { | 566 class A { |
756 int x = 2; | 567 int x = 2; |
757 } | 568 } |
758 | 569 |
759 class B extends A { | 570 class B extends A { |
760 get x => 3; | 571 get x => 3; |
761 } | 572 } |
762 | 573 |
763 foo() { | 574 foo() { |
764 String y = /*severe:StaticTypeError*/new B().x; | 575 String y = /*severe:StaticTypeError*/new B().x; |
765 int z = new B().x; | 576 int z = new B().x; |
766 } | 577 } |
767 ''' | 578 ''' |
768 }, | 579 }, |
769 inferFromOverrides: true); | 580 inferFromOverrides: true); |
770 | 581 |
771 testChecker( | 582 testChecker( |
772 '3', | |
773 { | |
774 '/main.dart': ''' | |
775 class A { | |
776 int x = 2; | |
777 } | |
778 | |
779 class B implements A { | |
780 /*severe:InvalidMethodOverride*/get x => 3; | |
781 } | |
782 | |
783 foo() { | |
784 String y = /*info:DynamicCast*/new B().x; | |
785 int z = /*info:DynamicCast*/new B().x; | |
786 } | |
787 ''' | |
788 }, | |
789 inferFromOverrides: false); | |
790 | |
791 testChecker( | |
792 '4', | 583 '4', |
793 { | 584 { |
794 '/main.dart': ''' | 585 '/main.dart': ''' |
795 class A { | 586 class A { |
796 int x = 2; | 587 int x = 2; |
797 } | 588 } |
798 | 589 |
799 class B implements A { | 590 class B implements A { |
800 get x => 3; | 591 get x => 3; |
801 } | 592 } |
(...skipping 24 matching lines...) Expand all Loading... |
826 foo() { | 617 foo() { |
827 String y = /*info:DynamicCast*/new B().x; | 618 String y = /*info:DynamicCast*/new B().x; |
828 int z = /*info:DynamicCast*/new B().x; | 619 int z = /*info:DynamicCast*/new B().x; |
829 } | 620 } |
830 ''' | 621 ''' |
831 }, | 622 }, |
832 inferFromOverrides: infer); | 623 inferFromOverrides: infer); |
833 } | 624 } |
834 | 625 |
835 testChecker( | 626 testChecker( |
836 '2', | |
837 { | |
838 '/main.dart': ''' | |
839 class A<T> { | |
840 T x; | |
841 } | |
842 | |
843 class B implements A<int> { | |
844 /*severe:InvalidMethodOverride*/get x => 3; | |
845 } | |
846 | |
847 foo() { | |
848 String y = /*info:DynamicCast*/new B().x; | |
849 int z = /*info:DynamicCast*/new B().x; | |
850 } | |
851 ''' | |
852 }, | |
853 inferFromOverrides: false); | |
854 | |
855 testChecker( | |
856 '3', | 627 '3', |
857 { | 628 { |
858 '/main.dart': ''' | 629 '/main.dart': ''' |
859 class A<T> { | 630 class A<T> { |
860 T x; | 631 T x; |
861 T w; | 632 T w; |
862 } | 633 } |
863 | 634 |
864 class B implements A<int> { | 635 class B implements A<int> { |
865 get x => 3; | 636 get x => 3; |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
954 | 725 |
955 // Note: this is a regression test for a non-deterministic behavior we used to | 726 // Note: this is a regression test for a non-deterministic behavior we used to |
956 // have with inference in library cycles. If you see this test flake out, | 727 // have with inference in library cycles. If you see this test flake out, |
957 // change `test` to `skip_test` and reopen bug #48. | 728 // change `test` to `skip_test` and reopen bug #48. |
958 testChecker( | 729 testChecker( |
959 'infer types on generic instantiations in library cycle', | 730 'infer types on generic instantiations in library cycle', |
960 { | 731 { |
961 '/a.dart': ''' | 732 '/a.dart': ''' |
962 import 'main.dart'; | 733 import 'main.dart'; |
963 abstract class I<E> { | 734 abstract class I<E> { |
964 A<E> m(a, String f(v, T e)); | 735 A<E> m(a, String f(v, int e)); |
965 } | 736 } |
966 ''', | 737 ''', |
967 '/main.dart': ''' | 738 '/main.dart': ''' |
968 import 'a.dart'; | 739 import 'a.dart'; |
969 | 740 |
970 abstract class A<E> implements I<E> { | 741 abstract class A<E> implements I<E> { |
971 const A(); | 742 const A(); |
972 | 743 |
973 E value; | 744 E value; |
974 } | 745 } |
975 | 746 |
976 abstract class M { | 747 abstract class M { |
977 int y; | 748 int y; |
978 } | 749 } |
979 | 750 |
980 class B<E> extends A<E> implements M { | 751 class B<E> extends A<E> implements M { |
981 const B(); | 752 const B(); |
982 int get y => 0; | 753 int get y => 0; |
983 | 754 |
984 m(a, f(v, T e)) {} | 755 m(a, f(v, int e)) {} |
985 } | 756 } |
986 | 757 |
987 foo () { | 758 foo () { |
988 int y = /*severe:StaticTypeError*/new B<String>().m(null, null).value; | 759 int y = /*severe:StaticTypeError*/new B<String>().m(null, null).value; |
989 String z = new B<String>().m(null, null).value; | 760 String z = new B<String>().m(null, null).value; |
990 } | 761 } |
991 ''' | 762 ''' |
992 }, | 763 }, |
993 inferFromOverrides: true); | 764 inferFromOverrides: true); |
994 | 765 |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1029 | 800 |
1030 class A { | 801 class A { |
1031 final I1 a; | 802 final I1 a; |
1032 } | 803 } |
1033 | 804 |
1034 class B { | 805 class B { |
1035 final I2 a; | 806 final I2 a; |
1036 } | 807 } |
1037 | 808 |
1038 class C1 extends A implements B { | 809 class C1 extends A implements B { |
1039 /*severe:InvalidMethodOverride*/get a => null; | 810 /*severe:InvalidMethodOverride,severe:InvalidMethodOverride*/get a =>
null; |
1040 } | 811 } |
1041 | 812 |
1042 // Here we infer from B, which is more precise. | 813 // Still ambiguous |
1043 class C2 extends B implements A { | 814 class C2 extends B implements A { |
1044 get a => null; | 815 /*severe:InvalidMethodOverride,severe:InvalidMethodOverride*/get a =>
null; |
1045 } | 816 } |
1046 ''' | 817 ''' |
1047 }, | 818 }, |
1048 inferFromOverrides: true); | 819 inferFromOverrides: true); |
1049 | 820 |
1050 testChecker( | 821 testChecker( |
1051 'conflicts can happen 2', | 822 'conflicts can happen 2', |
1052 { | 823 { |
1053 '/main.dart': ''' | 824 '/main.dart': ''' |
1054 class I1 { | 825 class I1 { |
(...skipping 14 matching lines...) Expand all Loading... |
1069 | 840 |
1070 class B { | 841 class B { |
1071 final I2 a; | 842 final I2 a; |
1072 } | 843 } |
1073 | 844 |
1074 class C1 extends A implements B { | 845 class C1 extends A implements B { |
1075 I3 get a => null; | 846 I3 get a => null; |
1076 } | 847 } |
1077 | 848 |
1078 class C2 extends A implements B { | 849 class C2 extends A implements B { |
1079 /*severe:InvalidMethodOverride*/get a => null; | 850 /*severe:InvalidMethodOverride,severe:InvalidMethodOverride*/get a =>
null; |
1080 } | 851 } |
1081 ''' | 852 ''' |
1082 }, | 853 }, |
1083 inferFromOverrides: true); | 854 inferFromOverrides: true); |
1084 | 855 |
1085 testChecker( | 856 testChecker( |
1086 'infer from RHS only if it wont conflict with overridden fields', | 857 'infer from RHS only if it wont conflict with overridden fields', |
1087 { | 858 { |
1088 '/main.dart': ''' | 859 '/main.dart': ''' |
1089 class A { | 860 class A { |
(...skipping 552 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1642 main() { | 1413 main() { |
1643 Iterable<Future<int>> list = <int>[1, 2, 3].map(make); | 1414 Iterable<Future<int>> list = <int>[1, 2, 3].map(make); |
1644 Future<List<int>> results = Future.wait(list); | 1415 Future<List<int>> results = Future.wait(list); |
1645 Future<String> results2 = results.then((List<int> list) | 1416 Future<String> results2 = results.then((List<int> list) |
1646 => list.fold('', (String x, int y) => x + y.toString())); | 1417 => list.fold('', (String x, int y) => x + y.toString())); |
1647 } | 1418 } |
1648 ''' | 1419 ''' |
1649 }); | 1420 }); |
1650 }); | 1421 }); |
1651 } | 1422 } |
OLD | NEW |