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

Side by Side Diff: test/checker/inferred_type_test.dart

Issue 1011933002: Handle type-inference on fields, consts, and inferable overrides (Closed) Base URL: git@github.com:dart-lang/dev_compiler.git@master
Patch Set: Created 5 years, 9 months 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
« no previous file with comments | « lib/src/testing.dart ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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:unittest/unittest.dart'; 8 import 'package:unittest/unittest.dart';
9 9
10 import 'package:dev_compiler/src/testing.dart'; 10 import 'package:dev_compiler/src/testing.dart';
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after
130 c = /*severe:StaticTypeError*/"hi"; 130 c = /*severe:StaticTypeError*/"hi";
131 c = 4; 131 c = 4;
132 } 132 }
133 133
134 int y = 0; // field def after use 134 int y = 0; // field def after use
135 final z = 42; // should infer `int` 135 final z = 42; // should infer `int`
136 ''' 136 '''
137 }); 137 });
138 }); 138 });
139 139
140 test('do not infer field type when initializer is null', () {
141 testChecker({
142 '/main.dart': '''
143 var x = null;
144 var y = 3;
145 class A {
146 static var x = null;
147 static var y = 3;
148
149 var x2 = null;
150 var y2 = 3;
151 }
152
153 test() {
154 x = "hi";
155 y = /*severe:StaticTypeError*/"hi";
156 A.x = "hi";
157 A.y = /*severe:StaticTypeError*/"hi";
158 new A().x2 = "hi";
159 new A().y2 = /*severe:StaticTypeError*/"hi";
160 }
161 '''
162 });
163 });
164
140 test('do not infer from variables in same lib (order independence)', () { 165 test('do not infer from variables in same lib (order independence)', () {
141 testChecker({ 166 testChecker({
142 '/main.dart': ''' 167 '/main.dart': '''
143 var x = 2; 168 var x = 2;
144 var y = x;
145
146 test1() {
147 x = /*severe:StaticTypeError*/"hi";
148 y = "hi";
149 }
150 '''
151 });
152
153 testChecker({
154 '/main.dart': '''
155 class A {
156 static var x = 2;
157 static var y = A.x;
158 }
159
160 test1() {
161 A.x = /*severe:StaticTypeError*/"hi";
162 A.y = "hi";
163 }
164 '''
165 });
166
167 // Allowed with special flag. Note, while the flag is generally not stable,
168 // we can use it in this test because it is stable within a library (order
169 // matches program order).
170 testChecker({
171 '/main.dart': '''
172 var x = 2;
173 var y = x; 169 var y = x;
174 170
175 test1() { 171 test1() {
176 x = /*severe:StaticTypeError*/"hi"; 172 x = /*severe:StaticTypeError*/"hi";
177 y = /*severe:StaticTypeError*/"hi"; 173 y = "hi";
178 } 174 }
179 ''' 175 '''
180 }, inferInNonStableOrder: true); 176 });
181 177
182 testChecker({ 178 testChecker({
183 '/main.dart': ''' 179 '/main.dart': '''
184 class A { 180 class A {
185 static var x = 2; 181 static var x = 2;
186 static var y = A.x; 182 static var y = A.x;
187 } 183 }
188 184
189 test1() { 185 test1() {
190 A.x = /*severe:StaticTypeError*/"hi"; 186 A.x = /*severe:StaticTypeError*/"hi";
191 A.y = /*severe:StaticTypeError*/"hi"; 187 A.y = "hi";
192 } 188 }
193 ''' 189 '''
194 }, inferInNonStableOrder: true); 190 });
195 }); 191 });
196 192
197 test('not ok to infer from variables in non-cycle libs', () { 193 test('not ok to infer from variables in non-cycle libs', () {
198 testChecker({ 194 testChecker({
199 '/a.dart': ''' 195 '/a.dart': '''
200 var x = 2; 196 var x = 2;
201 ''', 197 ''',
202 '/main.dart': ''' 198 '/main.dart': '''
203 import 'a.dart'; 199 import 'a.dart';
204 var y = x; 200 var y = x;
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
255 B.y = /*severe:StaticTypeError*/"hi"; 251 B.y = /*severe:StaticTypeError*/"hi";
256 } 252 }
257 ''' 253 '''
258 }, inferStaticsFromIdentifiers: true); 254 }, inferStaticsFromIdentifiers: true);
259 }); 255 });
260 256
261 test('do not infer from variables in cycle libs', () { 257 test('do not infer from variables in cycle libs', () {
262 testChecker({ 258 testChecker({
263 '/a.dart': ''' 259 '/a.dart': '''
264 import 'main.dart'; 260 import 'main.dart';
265 var x = 2; 261 var x = 2; // ok to infer
266 ''', 262 ''',
267 '/main.dart': ''' 263 '/main.dart': '''
268 import 'a.dart'; 264 import 'a.dart';
269 var y = x; 265 var y = x; // not ok to infer yet
270 266
271 test1() { 267 test1() {
272 int t = 3; 268 int t = 3;
273 t = /*info:DownCast*/x; 269 t = x;
274 t = /*info:DownCast*/y; 270 t = /*info:DownCast*/y;
275 } 271 }
276 ''' 272 '''
277 }, inferStaticsFromIdentifiers: true); 273 }, inferStaticsFromIdentifiers: true);
278 274
279 testChecker({ 275 testChecker({
280 '/a.dart': ''' 276 '/a.dart': '''
281 import 'main.dart'; 277 import 'main.dart';
282 class A { static var x = 2; } 278 class A { static var x = 2; }
283 ''', 279 ''',
284 '/main.dart': ''' 280 '/main.dart': '''
285 import 'a.dart'; 281 import 'a.dart';
286 class B { static var y = A.x; } 282 class B { static var y = A.x; }
287 283
288 test1() { 284 test1() {
289 int t = 3; 285 int t = 3;
290 t = /*info:DownCast*/A.x; 286 t = A.x;
291 t = /*info:DownCast*/A.y; 287 t = /*info:DownCast*/A.y;
292 } 288 }
293 ''' 289 '''
294 }, inferStaticsFromIdentifiers: true); 290 }, inferStaticsFromIdentifiers: true);
295 }); 291 });
296 292
297 test('do not infer from static and instance fields', () { 293 test('do not infer from static and instance fields', () {
298 testChecker({ 294 testChecker({
299 '/a.dart': ''' 295 '/a.dart': '''
300 import 'b.dart'; 296 import 'b.dart';
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
343 test1() { 339 test1() {
344 int x = 0; 340 int x = 0;
345 // inference in A now works. 341 // inference in A now works.
346 x = A.a1; 342 x = A.a1;
347 x = new A().a2; 343 x = new A().a2;
348 } 344 }
349 ''' 345 '''
350 }, inferStaticsFromIdentifiers: true); 346 }, inferStaticsFromIdentifiers: true);
351 }); 347 });
352 348
353 test('don\'t infer on cycles', () { 349 test('inference uses declared types', () {
350 testChecker({
351 '/main.dart': '''
352 int w = 0;
353 var x = 0;
354
355 var y = w; // y can be inferred because w is typed int.
356 var z = x; // z cannot, because x would be inferred.
357
358 test1() {
359 int a;
360 a = w;
361 a = x;
362 a = y;
363 a = /*info:DownCast*/z;
364 }
365 '''
366 }, inferStaticsFromIdentifiers: true);
367 });
368
369 test('inference in cycles is deterministic', () {
354 testChecker({ 370 testChecker({
355 '/a.dart': ''' 371 '/a.dart': '''
356 import 'b.dart'; 372 import 'b.dart';
357 class A { 373 class A {
358 static final a1 = B.b1; 374 static final a1 = B.b1;
359 final a2 = new B().b2; 375 final a2 = new B().b2;
360 } 376 }
361 ''', 377 ''',
362 '/b.dart': ''' 378 '/b.dart': '''
363 class B { 379 class B {
364 static final b1 = 1; 380 static final b1 = 1;
365 final b2 = 1; 381 final b2 = 1;
366 } 382 }
367 ''', 383 ''',
368 '/c.dart': ''' 384 '/c.dart': '''
369 import "main.dart"; // creates a cycle 385 import "main.dart"; // creates a cycle
370 386
371 class C { 387 class C {
372 static final c1 = 1; 388 static final c1 = 1;
373 final c2 = 1; 389 final c2 = 1;
374 } 390 }
375 ''', 391 ''',
376 '/e.dart': ''' 392 '/e.dart': '''
377 part "e2.dart"; 393 import 'a.dart';
394 part 'e2.dart';
378 395
379 class E { 396 class E {
380 static final e1 = 1; 397 static final e1 = 1;
381 final e2 = 1; 398 static final e2 = F.f1;
399 static final e3 = A.a1;
400 final e4 = 1;
401 final e5 = new F().f2;
402 final e6 = new A().a2;
382 } 403 }
383 ''', 404 ''',
384 '/f.dart': ''' 405 '/f.dart': '''
385 part "f2.dart"; 406 part 'f2.dart';
386 ''', 407 ''',
387 '/e2.dart': ''' 408 '/e2.dart': '''
388 class F { 409 class F {
389 static final f1 = 1; 410 static final f1 = 1;
390 final f2 = 1; 411 final f2 = 1;
391 } 412 }
392 ''', 413 ''',
393 '/main.dart': ''' 414 '/main.dart': '''
394 import "a.dart"; 415 import "a.dart";
395 import "c.dart"; 416 import "c.dart";
396 import "e.dart"; 417 import "e.dart";
397 418
398 class D { 419 class D {
399 static final d1 = A.a1 + 1; 420 static final d1 = A.a1 + 1;
400 static final d2 = C.c1 + 1; 421 static final d2 = C.c1 + 1;
401 final d3 = new A().a2; 422 final d3 = new A().a2;
402 final d4 = new C().c2; 423 final d4 = new C().c2;
403 } 424 }
404 425
405 test1() { 426 test1() {
406 int x = 0; 427 int x = 0;
407 // inference in A works, it's not in a cycle 428 // inference in A works, it's not in a cycle
408 x = A.a1; 429 x = A.a1;
409 x = new A().a2; 430 x = new A().a2;
410 431
411 // inference here or in c.dart is disabled because of the cycle 432 // Within a cycle we allow inference when the RHS is well known, but
412 x = /*info:DownCast*/C.c1; 433 // not when it depends on other fields within the cycle
413 x = /*info:DownCast*/D.d1; 434 x = C.c1;
435 x = D.d1;
414 x = /*info:DownCast*/D.d2; 436 x = /*info:DownCast*/D.d2;
415 x = /*info:DownCast*/new C().c2; 437 x = new C().c2;
416 x = /*info:DownCast*/new D().d3; 438 x = new D().d3;
417 x = /*info:DownCast*/new D().d4; 439 x = /*info:DownCast*/new D().d4;
418 440
419 441
420 // inference in e.dart and f.dart is disabled because they contains 442 // Similarly if the library contains parts.
421 // parts 443 x = E.e1;
422 x = /*info:DownCast*/E.e1; 444 x = /*info:DownCast*/E.e2;
423 x = /*info:DownCast*/new E().e2; 445 x = E.e3;
424 x = /*info:DownCast*/F.f1; 446 x = new E().e4;
425 x = /*info:DownCast*/new F().f2; 447 x = /*info:DownCast*/new E().e5;
448 x = new E().e6;
449 x = F.f1;
450 x = new F().f2;
426 } 451 }
427 ''' 452 '''
428 }, inferStaticsFromIdentifiers: true); 453 }, inferStaticsFromIdentifiers: true);
429 }); 454 });
430 455
431 test('infer from complex expressions if the outer-most value is precise', () { 456 test('infer from complex expressions if the outer-most value is precise', () {
432 testChecker({ 457 testChecker({
433 '/main.dart': ''' 458 '/main.dart': '''
434 class A { int x; B operator+(other) {} } 459 class A { int x; B operator+(other) {} }
435 class B extends A { B(ignore); } 460 class B extends A { B(ignore); }
436 var a = new A(); 461 var a = new A();
437 // Note: it doesn't matter that some of these refer to 'x'. 462 // Note: it doesn't matter that some of these refer to 'x'.
438 var b = new B(x); // allocations 463 var b = new B(x); // allocations
439 var c1 = [x]; // list literals 464 var c1 = [x]; // list literals
440 var c2 = const []; 465 var c2 = const [];
441 var d = {'a': 'b'}; // map literals 466 var d = {'a': 'b'}; // map literals
442 var e = new A()..x = 3; // cascades 467 var e = new A()..x = 3; // cascades
443 var f = 2 + 3; // binary expressions are OK if the left operand 468 var f = 2 + 3; // binary expressions are OK if the left operand
444 // is from a library in a different strongest 469 // is from a library in a different strongest
445 // conected component. 470 // conected component.
446 var g = -3; 471 var g = -3;
447 var h = new A() + 3; 472 var h = new A() + 3;
448 var i = - new A(); 473 var i = - new A();
474 var j = null as B;
449 475
450 test1() { 476 test1() {
451 a = /*severe:StaticTypeError*/"hi"; 477 a = /*severe:StaticTypeError*/"hi";
452 a = new B(3); 478 a = new B(3);
453 b = /*severe:StaticTypeError*/"hi"; 479 b = /*severe:StaticTypeError*/"hi";
454 b = new B(3); 480 b = new B(3);
455 c1 = []; 481 c1 = [];
456 c1 = /*severe:StaticTypeError*/{}; 482 c1 = /*severe:StaticTypeError*/{};
457 c2 = []; 483 c2 = [];
458 c2 = /*severe:StaticTypeError*/{}; 484 c2 = /*severe:StaticTypeError*/{};
459 d = {}; 485 d = {};
460 d = /*severe:StaticTypeError*/3; 486 d = /*severe:StaticTypeError*/3;
461 e = new A(); 487 e = new A();
462 e = /*severe:StaticTypeError*/{}; 488 e = /*severe:StaticTypeError*/{};
463 f = 3; 489 f = 3;
464 f = /*severe:StaticTypeError*/false; 490 f = /*severe:StaticTypeError*/false;
465 g = 1; 491 g = 1;
466 g = /*severe:StaticTypeError*/false; 492 g = /*severe:StaticTypeError*/false;
467 h = /*severe:StaticTypeError*/false; 493 h = /*severe:StaticTypeError*/false;
468 h = new B(); 494 h = new B();
469 i = false; 495 i = false;
496 j = new B();
497 j = /*severe:StaticTypeError*/false;
498 j = /*severe:StaticTypeError*/[];
470 } 499 }
471 ''' 500 '''
472 }); 501 });
473 }); 502 });
474 503
475 test('do not infer if complex expressions read possibly inferred field', () { 504 test('do not infer if complex expressions read possibly inferred field', () {
476 testChecker({ 505 testChecker({
477 '/a.dart': ''' 506 '/a.dart': '''
478 class A { 507 class A {
479 var x = 3; 508 var x = 3;
(...skipping 327 matching lines...) Expand 10 before | Expand all | Expand 10 after
807 } 836 }
808 837
809 foo () { 838 foo () {
810 int y = /*severe:StaticTypeError*/new B().m(null, null); 839 int y = /*severe:StaticTypeError*/new B().m(null, null);
811 String z = new B().m(null, null); 840 String z = new B().m(null, null);
812 } 841 }
813 ''' 842 '''
814 }, inferFromOverrides: true); 843 }, inferFromOverrides: true);
815 }); 844 });
816 845
817 // TODO(sigmund): enable this test, it's currently flaky (see issue #48). 846 test('infer type regardless of declaration order or cycles', () {
818 skip_test('infer types on generic instantiations in library cycle', () { 847 testChecker({
848 '/b.dart': '''
849 import 'main.dart';
850
851 class B extends A { }
852 ''',
853 '/main.dart': '''
854 import 'b.dart';
855 class C extends B {
856 get x;
857 }
858 class A {
859 int get x;
860 }
861 foo () {
862 int y = new C().x;
863 String y = /*severe:StaticTypeError*/new C().x;
864 }
865 '''
866 }, inferFromOverrides: true);
867 });
868
869 // Note: this is a regression test for a non-deterministic behavior we used to
870 // have with inference in library cycles. If you see this test flake out,
871 // change `test` to `skip_test` and reopen bug #48.
872 test('infer types on generic instantiations in library cycle', () {
819 testChecker({ 873 testChecker({
820 '/a.dart': ''' 874 '/a.dart': '''
821 import 'main.dart'; 875 import 'main.dart';
822 abstract class I<E> { 876 abstract class I<E> {
823 A<E> m(a, String f(v, T e)); 877 A<E> m(a, String f(v, T e));
824 } 878 }
825 ''', 879 ''',
826 '/main.dart': ''' 880 '/main.dart': '''
827 import 'a.dart'; 881 import 'a.dart';
828 882
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
926 class C1 extends A implements B { 980 class C1 extends A implements B {
927 I3 get a => null; 981 I3 get a => null;
928 } 982 }
929 983
930 class C2 extends A implements B { 984 class C2 extends A implements B {
931 /*severe:InvalidMethodOverride*/get a => null; 985 /*severe:InvalidMethodOverride*/get a => null;
932 } 986 }
933 ''' 987 '''
934 }, inferFromOverrides: true); 988 }, inferFromOverrides: true);
935 }); 989 });
990
991 test('infer from RHS only if it wont conflict with overridden fields', () {
992 testChecker({
993 '/main.dart': '''
994 class A {
995 var x;
996 }
997
998 class B extends A {
999 var x = 2;
1000 }
1001
1002 foo() {
1003 String y = /*info:DownCast*/new B().x;
1004 int z = /*info:DownCast*/new B().x;
1005 }
1006 '''
1007 }, inferFromOverrides: true);
1008
1009 testChecker({
1010 '/main.dart': '''
1011 class A {
1012 final x;
1013 }
1014
1015 class B extends A {
1016 final x = 2;
1017 }
1018
1019 foo() {
1020 String y = /*severe:StaticTypeError*/new B().x;
1021 int z = new B().x;
1022 }
1023 '''
1024 }, inferFromOverrides: true);
1025 });
1026
1027 test('infer correctly on multiple variables declared together', () {
1028 testChecker({
1029 '/main.dart': '''
1030 class A {
1031 var x, y = 2, z = "hi";
1032 }
1033
1034 class B extends A {
1035 var x = 2, y = 3, z, w = 2;
1036 }
1037
1038 foo() {
1039 String s;
1040 int i;
1041
1042 s = /*info:DownCast*/new B().x;
1043 s = /*severe:StaticTypeError*/new B().y;
1044 s = new B().z;
1045 s = /*severe:StaticTypeError*/new B().w;
1046
1047 i = /*info:DownCast*/new B().x;
1048 i = new B().y;
1049 i = /*severe:StaticTypeError*/new B().z;
1050 i = new B().w;
1051 }
1052 '''
1053 }, inferFromOverrides: true);
1054 });
936 } 1055 }
OLDNEW
« no previous file with comments | « lib/src/testing.dart ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698