| 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 |