Chromium Code Reviews| 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 /// General type checking tests | 5 /// General type checking tests |
| 6 library dev_compiler.test.checker_test; | 6 library dev_compiler.test.checker_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'; |
| 11 | 11 |
| 12 import '../test_util.dart'; | 12 import '../test_util.dart'; |
| 13 | 13 |
| 14 void main() { | 14 void main() { |
| 15 configureTest(); | 15 configureTest(); |
| 16 | 16 |
| 17 test('conversion and dynamic invoke', () { | 17 test('conversion and dynamic invoke', () { |
| 18 testChecker({ | 18 testChecker({ |
| 19 '/main.dart': ''' | 19 '/main.dart': ''' |
| 20 class A { | 20 class A { |
| 21 String x = "hello world"; | 21 String x = "hello world"; |
| 22 | |
| 23 void baz1(y) => x + y; | |
| 24 static baz2(y) => y + y; | |
| 22 } | 25 } |
| 23 | 26 |
| 24 void foo(String str) { | 27 void foo(String str) { |
| 25 print(str); | 28 print(str); |
| 26 } | 29 } |
| 27 | 30 |
| 28 void bar(a) { | 31 void bar(a) { |
| 29 foo(/*info:DownCast,warning:DynamicInvoke*/a.x); | 32 foo(/*info:DownCast,warning:DynamicInvoke*/a.x); |
| 30 } | 33 } |
| 31 | 34 |
| 32 void main() => bar(new A()); | 35 typedef DynFun(x); |
| 36 typedef StrFun(String x); | |
| 37 | |
| 38 var bar1 = bar; | |
| 39 | |
| 40 void main() { | |
| 41 var a = new A(); | |
| 42 bar(a); | |
| 43 (/*warning:DynamicInvoke*/bar1(a)); | |
| 44 var b = bar; | |
| 45 (/*warning:DynamicInvoke*/b(a)); | |
| 46 var f1 = foo; | |
| 47 f1("hello"); | |
| 48 dynamic f2 = foo; | |
| 49 (/*warning:DynamicInvoke*/f2("hello")); | |
| 50 DynFun f3 = foo; | |
| 51 (/*warning:DynamicInvoke*/f3("hello")); | |
| 52 (/*warning:DynamicInvoke*/f3(42)); | |
| 53 StrFun f4 = foo; | |
| 54 f4("hello"); | |
| 55 a.baz1("hello"); | |
| 56 var b1 = a.baz1; | |
| 57 (/*warning:DynamicInvoke*/b1("hello")); | |
| 58 A.baz2("hello"); | |
| 59 var b2 = A.baz2; | |
| 60 (/*warning:DynamicInvoke*/b2("hello")); | |
| 33 ''' | 61 ''' |
| 34 }); | 62 }); |
| 35 }); | 63 }); |
| 36 | 64 |
| 37 test('Primitives', () { | 65 test('Primitives', () { |
| 38 testChecker({ | 66 testChecker({ |
| 39 '/main.dart': ''' | 67 '/main.dart': ''' |
| 40 int /*severe:InvalidVariableDeclaration*/a; | 68 int /*severe:InvalidVariableDeclaration*/a; |
| 41 double /*severe:InvalidVariableDeclaration*/b; | 69 double /*severe:InvalidVariableDeclaration*/b; |
| 42 num c; | 70 num c; |
| (...skipping 407 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 450 ''' | 478 ''' |
| 451 }); | 479 }); |
| 452 }); | 480 }); |
| 453 | 481 |
| 454 test('Function typing and subtyping: dynamic', () { | 482 test('Function typing and subtyping: dynamic', () { |
| 455 testChecker({ | 483 testChecker({ |
| 456 '/main.dart': ''' | 484 '/main.dart': ''' |
| 457 | 485 |
| 458 class A {} | 486 class A {} |
| 459 | 487 |
| 460 typedef dynamic Top(A x); // Top of the lattice | 488 // Note: because we allow A->B <: dynamic->B, we have circularity |
|
Leaf
2015/03/18 22:57:26
This comment is no longer true, I think?
vsm
2015/03/18 23:40:32
Removed
| |
| 461 typedef A Left(A x); // Left branch | 489 // in the subtyping here, and it's not a true lattice. In addition |
| 462 typedef dynamic Right(dynamic x); // Right branch | 490 // to the below, we also have Top <: Right. |
| 463 typedef A Bot(dynamic x); // Bottom of the lattice | 491 typedef dynamic Left(A x); // Real left |
|
Leaf
2015/03/18 22:57:26
Nit: Sorting Top -> Left, Right -> Bottom makes th
vsm
2015/03/18 23:40:32
Done.
| |
| 492 typedef A Bottom(A x); // Real bottom | |
| 493 typedef dynamic Top(dynamic x); // Real top | |
| 494 typedef A Right(dynamic x); // Real right | |
| 464 | 495 |
| 465 dynamic top(A x) => x; | 496 dynamic left(A x) => x; |
| 466 A left(A x) => x; | 497 A bot(A x) => x; |
| 467 dynamic right(dynamic x) => x; | 498 dynamic top(dynamic x) => x; |
| 468 A bot(dynamic x) => /*info:DownCast*/x; | 499 A right(dynamic x) => /*info:DownCast*/x; |
| 469 | 500 |
| 470 void main() { | 501 void main() { |
| 471 { | 502 { |
| 472 Top f; | 503 Top f; |
| 473 f = top; | 504 f = top; |
| 474 f = left; | 505 f = left; |
| 475 f = right; | 506 f = right; |
| 476 f = bot; | 507 f = bot; |
| 477 } | 508 } |
| 478 { | 509 { |
| 479 Left f; | 510 Left f; |
| 480 f = /*warning:ClosureWrap*/top; | 511 f = /*warning:ClosureWrap*/top; |
| 481 f = left; | 512 f = left; |
| 482 f = /*warning:ClosureWrap*/right; | 513 f = /*warning:ClosureWrap*/right; |
| 483 f = bot; | 514 f = bot; |
| 484 } | 515 } |
| 485 { | 516 { |
| 486 Right f; | 517 Right f; |
| 487 f = /*warning:ClosureWrap*/top; | 518 f = /*warning:ClosureWrap*/top; |
| 488 f = /*warning:ClosureWrap*/left; | 519 f = /*warning:ClosureWrap*/left; |
| 489 f = right; | 520 f = right; |
| 490 f = bot; | 521 f = bot; |
| 491 } | 522 } |
| 492 { | 523 { |
| 493 Bot f; | 524 Bottom f; |
| 494 f = /*warning:ClosureWrap*/top; | 525 f = /*warning:ClosureWrap*/top; |
| 495 f = /*warning:ClosureWrap*/left; | 526 f = /*warning:ClosureWrap*/left; |
| 496 f = /*warning:ClosureWrap*/right; | 527 f = /*warning:ClosureWrap*/right; |
| 497 f = bot; | 528 f = bot; |
| 498 } | 529 } |
| 499 } | 530 } |
| 500 ''' | 531 ''' |
| 501 }); | 532 }); |
| 502 }); | 533 }); |
| 503 | 534 |
| (...skipping 395 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 899 '/main.dart': ''' | 930 '/main.dart': ''' |
| 900 typedef T F<T>(T t1, T t2); | 931 typedef T F<T>(T t1, T t2); |
| 901 typedef dynamic D(t1, t2); | 932 typedef dynamic D(t1, t2); |
| 902 | 933 |
| 903 void main() { | 934 void main() { |
| 904 F f1 = (x, y) => x + y; | 935 F f1 = (x, y) => x + y; |
| 905 F<int> f2 = /*warning:ClosureWrapLiteral*/(x, y) => x + y; | 936 F<int> f2 = /*warning:ClosureWrapLiteral*/(x, y) => x + y; |
| 906 D f3 = (x, y) => x + y; | 937 D f3 = (x, y) => x + y; |
| 907 Function f4 = (x, y) => x + y; | 938 Function f4 = (x, y) => x + y; |
| 908 f2 = /*warning:ClosureWrap*/f1; | 939 f2 = /*warning:ClosureWrap*/f1; |
| 909 f1 = /*warning:ClosureWrapLiteral*/(int x, int y) => x + y; | 940 f1 = (int x, int y) => x + y; |
| 910 f2 = /*severe:StaticTypeError*/(int x) => -x; | 941 f2 = /*severe:StaticTypeError*/(int x) => -x; |
| 911 } | 942 } |
| 912 ''' | 943 ''' |
| 913 }); | 944 }); |
| 914 }); | 945 }); |
| 915 | 946 |
| 916 test('Generic subtyping: invariance', () { | 947 test('Generic subtyping: invariance', () { |
| 917 testChecker({ | 948 testChecker({ |
| 918 '/main.dart': ''' | 949 '/main.dart': ''' |
| 919 | 950 |
| (...skipping 676 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1596 B f1; | 1627 B f1; |
| 1597 B f2; | 1628 B f2; |
| 1598 B f3; | 1629 B f3; |
| 1599 B f4; | 1630 B f4; |
| 1600 } | 1631 } |
| 1601 | 1632 |
| 1602 class Child extends Base { | 1633 class Child extends Base { |
| 1603 /*severe:InvalidMethodOverride*/A f1; // invalid for getter | 1634 /*severe:InvalidMethodOverride*/A f1; // invalid for getter |
| 1604 /*severe:InvalidMethodOverride*/C f2; // invalid for setter | 1635 /*severe:InvalidMethodOverride*/C f2; // invalid for setter |
| 1605 var f3; | 1636 var f3; |
| 1606 /*severe:InvalidMethodOverride*/dynamic f4; | 1637 /*severe:InvalidMethodOverride,severe:InvalidMethodOverride*/dynamic f4; |
| 1607 } | 1638 } |
| 1608 ''' | 1639 ''' |
| 1609 }, inferFromOverrides: true); | 1640 }, inferFromOverrides: true); |
| 1610 | 1641 |
| 1611 testChecker({ | 1642 testChecker({ |
| 1612 '/main.dart': ''' | 1643 '/main.dart': ''' |
| 1613 class A {} | 1644 class A {} |
| 1614 class B extends A {} | 1645 class B extends A {} |
| 1615 class C extends B {} | 1646 class C extends B {} |
| 1616 | 1647 |
| 1617 class Base { | 1648 class Base { |
| 1618 B f1; | 1649 B f1; |
| 1619 B f2; | 1650 B f2; |
| 1620 B f3; | 1651 B f3; |
| 1621 B f4; | 1652 B f4; |
| 1622 } | 1653 } |
| 1623 | 1654 |
| 1624 class Child extends Base { | 1655 class Child extends Base { |
| 1625 /*severe:InvalidMethodOverride*/A f1; // invalid for getter | 1656 /*severe:InvalidMethodOverride*/A f1; // invalid for getter |
| 1626 /*severe:InvalidMethodOverride*/C f2; // invalid for setter | 1657 /*severe:InvalidMethodOverride*/C f2; // invalid for setter |
| 1627 /*severe:InferableOverride*/var f3; | 1658 /*severe:InferableOverride,severe:InvalidMethodOverride*/var f3; |
| 1628 /*severe:InvalidMethodOverride*/dynamic f4; | 1659 /*severe:InvalidMethodOverride,severe:InvalidMethodOverride*/dynamic f4; |
| 1629 } | 1660 } |
| 1630 ''' | 1661 ''' |
| 1631 }, inferFromOverrides: false); | 1662 }, inferFromOverrides: false); |
| 1632 }); | 1663 }); |
| 1633 | 1664 |
| 1634 test('getter/getter override', () { | 1665 test('getter/getter override', () { |
| 1635 testChecker({ | 1666 testChecker({ |
| 1636 '/main.dart': ''' | 1667 '/main.dart': ''' |
| 1637 class A {} | 1668 class A {} |
| 1638 class B extends A {} | 1669 class B extends A {} |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1712 void set f1(B value); | 1743 void set f1(B value); |
| 1713 void set f2(B value); | 1744 void set f2(B value); |
| 1714 void set f3(B value); | 1745 void set f3(B value); |
| 1715 void set f4(B value); | 1746 void set f4(B value); |
| 1716 void set f5(B value); | 1747 void set f5(B value); |
| 1717 } | 1748 } |
| 1718 | 1749 |
| 1719 class Child extends Base { | 1750 class Child extends Base { |
| 1720 void set f1(A value) {} | 1751 void set f1(A value) {} |
| 1721 /*severe:InvalidMethodOverride*/void set f2(C value) {} | 1752 /*severe:InvalidMethodOverride*/void set f2(C value) {} |
| 1722 void set f3(value) {} | 1753 /*severe:InvalidMethodOverride*/void set f3(value) {} |
| 1723 void set f4(dynamic value) {} | 1754 /*severe:InvalidMethodOverride*/void set f4(dynamic value) {} |
| 1724 set f5(B value) {} | 1755 set f5(B value) {} |
| 1725 } | 1756 } |
| 1726 ''' | 1757 ''' |
| 1727 }); | 1758 }); |
| 1728 }); | 1759 }); |
| 1729 | 1760 |
| 1730 test('field/setter override', () { | 1761 test('field/setter override', () { |
| 1731 testChecker({ | 1762 testChecker({ |
| 1732 '/main.dart': ''' | 1763 '/main.dart': ''' |
| 1733 class A {} | 1764 class A {} |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 1744 | 1775 |
| 1745 class Child extends Base { | 1776 class Child extends Base { |
| 1746 B get f1 => null; | 1777 B get f1 => null; |
| 1747 B get f2 => null; | 1778 B get f2 => null; |
| 1748 B get f3 => null; | 1779 B get f3 => null; |
| 1749 B get f4 => null; | 1780 B get f4 => null; |
| 1750 B get f5 => null; | 1781 B get f5 => null; |
| 1751 | 1782 |
| 1752 void set f1(A value) {} | 1783 void set f1(A value) {} |
| 1753 /*severe:InvalidMethodOverride*/void set f2(C value) {} | 1784 /*severe:InvalidMethodOverride*/void set f2(C value) {} |
| 1754 void set f3(value) {} | 1785 /*severe:InvalidMethodOverride*/void set f3(value) {} |
| 1755 void set f4(dynamic value) {} | 1786 /*severe:InvalidMethodOverride*/void set f4(dynamic value) {} |
| 1756 set f5(B value) {} | 1787 set f5(B value) {} |
| 1757 } | 1788 } |
| 1758 ''' | 1789 ''' |
| 1759 }); | 1790 }); |
| 1760 }); | 1791 }); |
| 1761 | 1792 |
| 1762 test('method override', () { | 1793 test('method override', () { |
| 1763 testChecker({ | 1794 testChecker({ |
| 1764 '/main.dart': ''' | 1795 '/main.dart': ''' |
| 1765 class A {} | 1796 class A {} |
| 1766 class B extends A {} | 1797 class B extends A {} |
| 1767 class C extends B {} | 1798 class C extends B {} |
| 1768 | 1799 |
| 1769 class Base { | 1800 class Base { |
| 1770 B m1(B a); | 1801 B m1(B a); |
| 1771 B m2(B a); | 1802 B m2(B a); |
| 1772 B m3(B a); | 1803 B m3(B a); |
| 1773 B m4(B a); | 1804 B m4(B a); |
| 1774 B m5(B a); | 1805 B m5(B a); |
| 1775 B m6(B a); | 1806 B m6(B a); |
| 1776 } | 1807 } |
| 1777 | 1808 |
| 1778 class Child extends Base { | 1809 class Child extends Base { |
| 1779 /*severe:InvalidMethodOverride*/A m1(A value) {} | 1810 /*severe:InvalidMethodOverride*/A m1(A value) {} |
| 1780 /*severe:InvalidMethodOverride*/C m2(C value) {} | 1811 /*severe:InvalidMethodOverride*/C m2(C value) {} |
| 1781 /*severe:InvalidMethodOverride*/A m3(C value) {} | 1812 /*severe:InvalidMethodOverride*/A m3(C value) {} |
| 1782 C m4(A value) {} | 1813 C m4(A value) {} |
| 1783 m5(value) {} | 1814 /*severe:InvalidMethodOverride*/m5(value) {} |
| 1784 /*severe:InvalidMethodOverride*/dynamic m6(dynamic value) {} | 1815 /*severe:InvalidMethodOverride*/dynamic m6(dynamic value) {} |
| 1785 } | 1816 } |
| 1786 ''' | 1817 ''' |
| 1787 }, inferFromOverrides: true); | 1818 }, inferFromOverrides: true); |
| 1788 }); | 1819 }); |
| 1789 | 1820 |
| 1790 test('binary operators', () { | 1821 test('binary operators', () { |
| 1791 testChecker({ | 1822 testChecker({ |
| 1792 '/main.dart': ''' | 1823 '/main.dart': ''' |
| 1793 class A { | 1824 class A { |
| (...skipping 413 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2207 } | 2238 } |
| 2208 | 2239 |
| 2209 class I1 { | 2240 class I1 { |
| 2210 m(B a) {} | 2241 m(B a) {} |
| 2211 } | 2242 } |
| 2212 | 2243 |
| 2213 class T1 /*severe:InvalidMethodOverride*/extends Base | 2244 class T1 /*severe:InvalidMethodOverride*/extends Base |
| 2214 implements I1 {} | 2245 implements I1 {} |
| 2215 | 2246 |
| 2216 class T2 extends Base implements I1 { | 2247 class T2 extends Base implements I1 { |
| 2217 m(a) {} | 2248 /*severe:InvalidMethodOverride,severe:InvalidMethodOverride*/m(a ) {} |
|
Leaf
2015/03/18 22:57:26
We may want to treat this differently long term.
vsm
2015/03/18 23:40:32
Agree. It seems as though we want the static type
| |
| 2218 } | 2249 } |
| 2219 | 2250 |
| 2220 class T3 extends Object with /*severe:InvalidMethodOverride*/Base | 2251 class T3 extends Object with /*severe:InvalidMethodOverride*/Base |
| 2221 implements I1 {} | 2252 implements I1 {} |
| 2222 | 2253 |
| 2223 class T4 extends Object with Base implements I1 { | 2254 class T4 extends Object with Base implements I1 { |
| 2224 m(a) {} | 2255 /*severe:InvalidMethodOverride,severe:InvalidMethodOverride*/m(a ) {} |
| 2225 } | 2256 } |
| 2226 ''' | 2257 ''' |
| 2227 }); | 2258 }); |
| 2228 }); | 2259 }); |
| 2229 | 2260 |
| 2230 group('class override of grand interface', () { | 2261 group('class override of grand interface', () { |
| 2231 test('interface of interface of child', () { | 2262 test('interface of interface of child', () { |
| 2232 testChecker({ | 2263 testChecker({ |
| 2233 '/main.dart': ''' | 2264 '/main.dart': ''' |
| 2234 class A {} | 2265 class A {} |
| (...skipping 484 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2719 '/main.dart': ''' | 2750 '/main.dart': ''' |
| 2720 class A {} | 2751 class A {} |
| 2721 class T1 implements A { | 2752 class T1 implements A { |
| 2722 /*severe:InferableOverride*/toString() {} | 2753 /*severe:InferableOverride*/toString() {} |
| 2723 } | 2754 } |
| 2724 ''' | 2755 ''' |
| 2725 }, inferFromOverrides: false); | 2756 }, inferFromOverrides: false); |
| 2726 }); | 2757 }); |
| 2727 }); | 2758 }); |
| 2728 } | 2759 } |
| OLD | NEW |