| 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 // TODO(jmesserly): this file needs to be refactored, it's a port from | 5 // TODO(jmesserly): this file needs to be refactored, it's a port from |
| 6 // package:dev_compiler's tests | 6 // package:dev_compiler's tests |
| 7 /// Tests for type inference. | 7 /// Tests for type inference. |
| 8 library analyzer.test.src.task.strong.inferred_type_test; | 8 library analyzer.test.src.task.strong.inferred_type_test; |
| 9 | 9 |
| 10 import 'package:analyzer/dart/element/element.dart'; | 10 import 'package:analyzer/dart/element/element.dart'; |
| (...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 242 String s = /*info:DYNAMIC_CAST*/await f(); | 242 String s = /*info:DYNAMIC_CAST*/await f(); |
| 243 } | 243 } |
| 244 '''); | 244 '''); |
| 245 var f = mainUnit.functions[0].localVariables[0]; | 245 var f = mainUnit.functions[0].localVariables[0]; |
| 246 expect(f.type.toString(), '() → Future<dynamic>'); | 246 expect(f.type.toString(), '() → Future<dynamic>'); |
| 247 } | 247 } |
| 248 | 248 |
| 249 void test_blockBodiedLambdas_doesNotInferBottom_async_topLevel() { | 249 void test_blockBodiedLambdas_doesNotInferBottom_async_topLevel() { |
| 250 var mainUnit = checkFile(r''' | 250 var mainUnit = checkFile(r''' |
| 251 import 'dart:async'; | 251 import 'dart:async'; |
| 252 var f = /*warning:UNSAFE_BLOCK_CLOSURE_INFERENCE*/() async { return null; }; | 252 var f = /*warning:UNSAFE_BLOCK_CLOSURE_INFERENCE,info:INFERRED_TYPE_CLOSURE*/()
async { return null; }; |
| 253 '''); | 253 '''); |
| 254 var f = mainUnit.topLevelVariables[0]; | 254 var f = mainUnit.topLevelVariables[0]; |
| 255 expect(f.type.toString(), '() → Future<dynamic>'); | 255 expect(f.type.toString(), '() → Future<dynamic>'); |
| 256 } | 256 } |
| 257 | 257 |
| 258 void test_blockBodiedLambdas_doesNotInferBottom_asyncStar() { | 258 void test_blockBodiedLambdas_doesNotInferBottom_asyncStar() { |
| 259 if (!mayCheckTypesOfLocals) { | 259 if (!mayCheckTypesOfLocals) { |
| 260 return; | 260 return; |
| 261 } | 261 } |
| 262 var mainUnit = checkFile(r''' | 262 var mainUnit = checkFile(r''' |
| (...skipping 1402 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1665 expect(x.type.toString(), 'int'); | 1665 expect(x.type.toString(), 'int'); |
| 1666 } | 1666 } |
| 1667 | 1667 |
| 1668 void test_futureThen() { | 1668 void test_futureThen() { |
| 1669 String build({String declared, String downwards, String upwards}) => ''' | 1669 String build({String declared, String downwards, String upwards}) => ''' |
| 1670 import 'dart:async'; | 1670 import 'dart:async'; |
| 1671 class MyFuture<T> implements Future<T> { | 1671 class MyFuture<T> implements Future<T> { |
| 1672 MyFuture() {} | 1672 MyFuture() {} |
| 1673 MyFuture.value(T x) {} | 1673 MyFuture.value(T x) {} |
| 1674 dynamic noSuchMethod(invocation); | 1674 dynamic noSuchMethod(invocation); |
| 1675 MyFuture<S> then<S>(dynamic f(T x), {Function onError}) => null; | 1675 MyFuture<S> then<S>(FutureOr<S> f(T x), {Function onError}) => null; |
| 1676 } | 1676 } |
| 1677 | 1677 |
| 1678 void main() { | 1678 void main() { |
| 1679 $declared f; | 1679 $declared f; |
| 1680 $downwards<int> t1 = f.then((_) async => await new $upwards<int>.value(3)); | 1680 $downwards<int> t1 = f.then((_) async => await new $upwards<int>.value(3)); |
| 1681 $downwards<int> t2 = f.then(/*info:INFERRED_TYPE_CLOSURE*/(_) async { | 1681 $downwards<int> t2 = f.then(/*info:INFERRED_TYPE_CLOSURE*/(_) async { |
| 1682 return await new $upwards<int>.value(3);}); | 1682 return await new $upwards<int>.value(3);}); |
| 1683 $downwards<int> t3 = f.then((_) async => 3); | 1683 $downwards<int> t3 = f.then((_) async => 3); |
| 1684 $downwards<int> t4 = f.then(/*info:INFERRED_TYPE_CLOSURE*/(_) async { | 1684 $downwards<int> t4 = f.then(/*info:INFERRED_TYPE_CLOSURE*/(_) async { |
| 1685 return 3;}); | 1685 return 3;}); |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1745 build(declared: "Future", downwards: "Future", upwards: "Future")); | 1745 build(declared: "Future", downwards: "Future", upwards: "Future")); |
| 1746 } | 1746 } |
| 1747 | 1747 |
| 1748 void test_futureThen_conditional() { | 1748 void test_futureThen_conditional() { |
| 1749 String build({String declared, String downwards, String upwards}) => ''' | 1749 String build({String declared, String downwards, String upwards}) => ''' |
| 1750 import 'dart:async'; | 1750 import 'dart:async'; |
| 1751 class MyFuture<T> implements Future<T> { | 1751 class MyFuture<T> implements Future<T> { |
| 1752 MyFuture() {} | 1752 MyFuture() {} |
| 1753 MyFuture.value(T x) {} | 1753 MyFuture.value(T x) {} |
| 1754 dynamic noSuchMethod(invocation); | 1754 dynamic noSuchMethod(invocation); |
| 1755 MyFuture<S> then<S>(dynamic f(T x), {Function onError}) => null; | 1755 MyFuture<S> then<S>(FutureOr<S> f(T x), {Function onError}) => null; |
| 1756 } | 1756 } |
| 1757 | 1757 |
| 1758 void main() { | 1758 void main() { |
| 1759 $declared<bool> f; | 1759 $declared<bool> f; |
| 1760 $downwards<int> t1 = f.then(/*info:INFERRED_TYPE_CLOSURE*/ | 1760 $downwards<int> t1 = f.then(/*info:INFERRED_TYPE_CLOSURE*/ |
| 1761 (x) async => x ? 2 : await new $upwards<int>.value(3)); | 1761 (x) async => x ? 2 : await new $upwards<int>.value(3)); |
| 1762 $downwards<int> t2 = f.then(/*info:INFERRED_TYPE_CLOSURE,info:INFERRED_TYPE_CL
OSURE*/(x) async { // TODO(leafp): Why the duplicate here? | 1762 $downwards<int> t2 = f.then(/*info:INFERRED_TYPE_CLOSURE,info:INFERRED_TYPE_CL
OSURE*/(x) async { // TODO(leafp): Why the duplicate here? |
| 1763 return await x ? 2 : new $upwards<int>.value(3);}); | 1763 return await x ? 2 : new $upwards<int>.value(3);}); |
| 1764 $downwards<int> t5 = f.then(/*info:INFERRED_TYPE_CLOSURE*/ | 1764 $downwards<int> t5 = f.then(/*info:INFERRED_TYPE_CLOSURE,error:INVALID_CAST_FU
NCTION_EXPR*/ |
| 1765 (x) => x ? 2 : new $upwards<int>.value(3)); | 1765 (x) => x ? 2 : new $upwards<int>.value(3)); |
| 1766 $downwards<int> t6 = f.then(/*info:INFERRED_TYPE_CLOSURE*/ | 1766 $downwards<int> t6 = f.then(/*info:INFERRED_TYPE_CLOSURE*/ |
| 1767 (x) {return x ? 2 : new $upwards<int>.value(3);}); | 1767 (x) {return /*warning:DOWN_CAST_COMPOSITE*/x ? 2 : new $upwards<int>.value
(3);}); |
| 1768 } | 1768 } |
| 1769 '''; | 1769 '''; |
| 1770 checkFile( | 1770 checkFile( |
| 1771 build(declared: "MyFuture", downwards: "Future", upwards: "Future")); | |
| 1772 checkFile( | |
| 1773 build(declared: "MyFuture", downwards: "Future", upwards: "MyFuture")); | |
| 1774 checkFile( | |
| 1775 build(declared: "MyFuture", downwards: "MyFuture", upwards: "Future")); | |
| 1776 checkFile(build( | |
| 1777 declared: "MyFuture", downwards: "MyFuture", upwards: "MyFuture")); | |
| 1778 checkFile( | |
| 1779 build(declared: "Future", downwards: "Future", upwards: "MyFuture")); | |
| 1780 checkFile( | |
| 1781 build(declared: "Future", downwards: "Future", upwards: "Future")); | |
| 1782 } | |
| 1783 | |
| 1784 void test_futureThen_conditional_comment() { | |
| 1785 String build({String declared, String downwards, String upwards}) => ''' | |
| 1786 import 'dart:async'; | |
| 1787 class MyFuture<T> implements Future<T> { | |
| 1788 MyFuture() {} | |
| 1789 MyFuture.value(T x) {} | |
| 1790 dynamic noSuchMethod(invocation); | |
| 1791 MyFuture/*<S>*/ then/*<S>*/(dynamic f(T x), {Function onError}) => null; | |
| 1792 } | |
| 1793 | |
| 1794 void main() { | |
| 1795 $declared<bool> f; | |
| 1796 $downwards<int> t1 = f.then(/*info:INFERRED_TYPE_CLOSURE*/ | |
| 1797 (x) async => x ? 2 : await new $upwards<int>.value(3)); | |
| 1798 $downwards<int> t2 = f.then(/*info:INFERRED_TYPE_CLOSURE,info:INFERRED_TYPE_CL
OSURE*/(x) async { // TODO(leafp): Why the duplicate here? | |
| 1799 return await x ? 2 : new $upwards<int>.value(3);}); | |
| 1800 $downwards<int> t5 = f.then(/*info:INFERRED_TYPE_CLOSURE*/ | |
| 1801 (x) => x ? 2 : new $upwards<int>.value(3)); | |
| 1802 $downwards<int> t6 = f.then(/*info:INFERRED_TYPE_CLOSURE*/ | |
| 1803 (x) {return x ? 2 : new $upwards<int>.value(3);}); | |
| 1804 } | |
| 1805 '''; | |
| 1806 checkFile( | |
| 1807 build(declared: "MyFuture", downwards: "Future", upwards: "Future")); | 1771 build(declared: "MyFuture", downwards: "Future", upwards: "Future")); |
| 1808 checkFile( | 1772 checkFile( |
| 1809 build(declared: "MyFuture", downwards: "Future", upwards: "MyFuture")); | 1773 build(declared: "MyFuture", downwards: "Future", upwards: "MyFuture")); |
| 1810 checkFile( | 1774 checkFile( |
| 1811 build(declared: "MyFuture", downwards: "MyFuture", upwards: "Future")); | 1775 build(declared: "MyFuture", downwards: "MyFuture", upwards: "Future")); |
| 1812 checkFile(build( | 1776 checkFile(build( |
| 1813 declared: "MyFuture", downwards: "MyFuture", upwards: "MyFuture")); | 1777 declared: "MyFuture", downwards: "MyFuture", upwards: "MyFuture")); |
| 1814 checkFile( | 1778 checkFile( |
| 1815 build(declared: "Future", downwards: "Future", upwards: "MyFuture")); | 1779 build(declared: "Future", downwards: "Future", upwards: "MyFuture")); |
| 1816 checkFile( | 1780 checkFile( |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1827 .then(/*info:INFERRED_TYPE_CLOSURE*/(x) => []) | 1791 .then(/*info:INFERRED_TYPE_CLOSURE*/(x) => []) |
| 1828 .whenComplete(/*pass should be info:INFERRED_TYPE_LITERAL*/() {}); | 1792 .whenComplete(/*pass should be info:INFERRED_TYPE_LITERAL*/() {}); |
| 1829 b = f.then(/*info:INFERRED_TYPE_CLOSURE*/(x) => /*info:INFERRED_TYPE_LITERAL*/
[]); | 1793 b = f.then(/*info:INFERRED_TYPE_CLOSURE*/(x) => /*info:INFERRED_TYPE_LITERAL*/
[]); |
| 1830 } | 1794 } |
| 1831 '''); | 1795 '''); |
| 1832 } | 1796 } |
| 1833 | 1797 |
| 1834 void test_futureThen_explicitFuture() { | 1798 void test_futureThen_explicitFuture() { |
| 1835 checkFile(r''' | 1799 checkFile(r''' |
| 1836 import "dart:async"; | 1800 import "dart:async"; |
| 1837 main() { | 1801 m1() { |
| 1838 Future<int> f; | 1802 Future<int> f; |
| 1839 var x = f.then<Future<List<int>>>(/*info:INFERRED_TYPE_CLOSURE*/(x) => /*info:
INFERRED_TYPE_LITERAL*/[]); | 1803 var x = f.then<Future<List<int>>>(/*info:INFERRED_TYPE_CLOSURE,error:ARGUMENT_
TYPE_NOT_ASSIGNABLE*/(x) => []); |
| 1804 Future<List<int>> y = x; |
| 1805 } |
| 1806 m2() { |
| 1807 Future<int> f; |
| 1808 var x = f.then<List<int>>(/*info:INFERRED_TYPE_CLOSURE*/(x) => /*info:INFERRED
_TYPE_LITERAL*/[]); |
| 1840 Future<List<int>> y = x; | 1809 Future<List<int>> y = x; |
| 1841 } | 1810 } |
| 1842 '''); | 1811 '''); |
| 1843 } | |
| 1844 | |
| 1845 void test_futureThen_explicitFuture_comment() { | |
| 1846 checkFile(r''' | |
| 1847 import "dart:async"; | |
| 1848 main() { | |
| 1849 Future<int> f; | |
| 1850 var x = f.then/*<Future<List<int>>>*/(/*info:INFERRED_TYPE_CLOSURE*/(x) => /*i
nfo:INFERRED_TYPE_LITERAL*/[]); | |
| 1851 Future<List<int>> y = x; | |
| 1852 } | |
| 1853 '''); | |
| 1854 } | 1812 } |
| 1855 | 1813 |
| 1856 void test_futureThen_upwards() { | 1814 void test_futureThen_upwards() { |
| 1857 // Regression test for https://github.com/dart-lang/sdk/issues/27088. | 1815 // Regression test for https://github.com/dart-lang/sdk/issues/27088. |
| 1858 String build({String declared, String downwards, String upwards}) => ''' | 1816 String build({String declared, String downwards, String upwards}) => ''' |
| 1859 import 'dart:async'; | 1817 import 'dart:async'; |
| 1860 class MyFuture<T> implements Future<T> { | 1818 class MyFuture<T> implements Future<T> { |
| 1861 MyFuture() {} | 1819 MyFuture() {} |
| 1862 MyFuture.value(T x) {} | 1820 MyFuture.value(T x) {} |
| 1863 dynamic noSuchMethod(invocation); | 1821 dynamic noSuchMethod(invocation); |
| 1864 MyFuture<S> then<S>(dynamic f(T x), {Function onError}) => null; | 1822 MyFuture<S> then<S>(FutureOr<S> f(T x), {Function onError}) => null; |
| 1865 } | 1823 } |
| 1866 | 1824 |
| 1867 void main() { | 1825 void main() { |
| 1868 var f = foo().then((_) => 2.3); | |
| 1869 $downwards<int> f2 = /*error:INVALID_ASSIGNMENT*/f; | |
| 1870 | |
| 1871 // The unnecessary cast is to illustrate that we inferred <double> for | |
| 1872 // the generic type args, even though we had a return type context. | |
| 1873 $downwards<num> f3 = /*info:UNNECESSARY_CAST*/foo().then( | |
| 1874 (_) => 2.3) as $upwards<double>; | |
| 1875 } | |
| 1876 $declared foo() => new $declared<int>.value(1); | |
| 1877 '''; | |
| 1878 checkFile( | |
| 1879 build(declared: "MyFuture", downwards: "Future", upwards: "Future")); | |
| 1880 checkFile(build( | |
| 1881 declared: "MyFuture", downwards: "MyFuture", upwards: "MyFuture")); | |
| 1882 checkFile( | |
| 1883 build(declared: "Future", downwards: "Future", upwards: "Future")); | |
| 1884 } | |
| 1885 | |
| 1886 void test_futureThen_upwards_comment() { | |
| 1887 // Regression test for https://github.com/dart-lang/sdk/issues/27088. | |
| 1888 String build({String declared, String downwards, String upwards}) => ''' | |
| 1889 import 'dart:async'; | |
| 1890 class MyFuture<T> implements Future<T> { | |
| 1891 MyFuture() {} | |
| 1892 MyFuture.value(T x) {} | |
| 1893 dynamic noSuchMethod(invocation); | |
| 1894 MyFuture/*<S>*/ then/*<S>*/(dynamic f(T x), {Function onError}) => null; | |
| 1895 } | |
| 1896 | |
| 1897 void main() { | |
| 1898 var f = foo().then((_) => 2.3); | 1826 var f = foo().then((_) => 2.3); |
| 1899 $downwards<int> f2 = /*error:INVALID_ASSIGNMENT*/f; | 1827 $downwards<int> f2 = /*error:INVALID_ASSIGNMENT*/f; |
| 1900 | 1828 |
| 1901 // The unnecessary cast is to illustrate that we inferred <double> for | 1829 // The unnecessary cast is to illustrate that we inferred <double> for |
| 1902 // the generic type args, even though we had a return type context. | 1830 // the generic type args, even though we had a return type context. |
| 1903 $downwards<num> f3 = /*info:UNNECESSARY_CAST*/foo().then( | 1831 $downwards<num> f3 = /*info:UNNECESSARY_CAST*/foo().then( |
| 1904 (_) => 2.3) as $upwards<double>; | 1832 (_) => 2.3) as $upwards<double>; |
| 1905 } | 1833 } |
| 1906 $declared foo() => new $declared<int>.value(1); | 1834 $declared foo() => new $declared<int>.value(1); |
| 1907 '''; | 1835 '''; |
| (...skipping 12 matching lines...) Expand all Loading... |
| 1920 main() { | 1848 main() { |
| 1921 Future<int> base; | 1849 Future<int> base; |
| 1922 var f = base.then(/*info:INFERRED_TYPE_CLOSURE,info:INFERRED_TYPE_CLOSURE*/(x)
{ return x == 0; }); | 1850 var f = base.then(/*info:INFERRED_TYPE_CLOSURE,info:INFERRED_TYPE_CLOSURE*/(x)
{ return x == 0; }); |
| 1923 var g = base.then(/*info:INFERRED_TYPE_CLOSURE*/(x) => x == 0); | 1851 var g = base.then(/*info:INFERRED_TYPE_CLOSURE*/(x) => x == 0); |
| 1924 Future<bool> b = f; | 1852 Future<bool> b = f; |
| 1925 b = g; | 1853 b = g; |
| 1926 } | 1854 } |
| 1927 '''); | 1855 '''); |
| 1928 } | 1856 } |
| 1929 | 1857 |
| 1858 void test_futureOr_subtyping() { |
| 1859 checkFile(r''' |
| 1860 import 'dart:async'; |
| 1861 void add(int x) {} |
| 1862 add2(int y) {} |
| 1863 main() { |
| 1864 Future<int> f; |
| 1865 var a = f.then(add); |
| 1866 var b = f.then(add2); |
| 1867 } |
| 1868 '''); |
| 1869 } |
| 1870 |
| 1930 void test_futureUnion_asyncConditional() { | 1871 void test_futureUnion_asyncConditional() { |
| 1931 String build({String declared, String downwards, String upwards}) => ''' | 1872 String build({String declared, String downwards, String upwards}) => ''' |
| 1932 import 'dart:async'; | 1873 import 'dart:async'; |
| 1933 class MyFuture<T> implements Future<T> { | 1874 class MyFuture<T> implements Future<T> { |
| 1934 MyFuture() {} | 1875 MyFuture() {} |
| 1935 MyFuture.value(x) {} | 1876 MyFuture.value(x) {} |
| 1936 dynamic noSuchMethod(invocation); | 1877 dynamic noSuchMethod(invocation); |
| 1937 MyFuture<S> then<S>(dynamic f(T x), {Function onError}) => null; | 1878 MyFuture<S> then<S>(FutureOr<S> f(T x), {Function onError}) => null; |
| 1938 } | 1879 } |
| 1939 | 1880 |
| 1940 $downwards<int> g1(bool x) async { | 1881 $downwards<int> g1(bool x) async { |
| 1941 return x ? 42 : /*info:INFERRED_TYPE_ALLOCATION*/new $upwards.value(42); } | 1882 return x ? 42 : /*info:INFERRED_TYPE_ALLOCATION*/new $upwards.value(42); } |
| 1942 $downwards<int> g2(bool x) async => | 1883 $downwards<int> g2(bool x) async => |
| 1943 x ? 42 : /*info:INFERRED_TYPE_ALLOCATION*/new $upwards.value(42); | 1884 x ? 42 : /*info:INFERRED_TYPE_ALLOCATION*/new $upwards.value(42); |
| 1944 $downwards<int> g3(bool x) async { | 1885 $downwards<int> g3(bool x) async { |
| 1945 var y = x ? 42 : new $upwards.value(42); | 1886 var y = x ? 42 : new $upwards.value(42); |
| 1946 return y; | 1887 return y; |
| 1947 } | 1888 } |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1979 // in the resolver visitor isn't powerful enough to catch this for the | 1920 // in the resolver visitor isn't powerful enough to catch this for the |
| 1980 // subclass. See the TODO there. | 1921 // subclass. See the TODO there. |
| 1981 var allocInfo = | 1922 var allocInfo = |
| 1982 (upwards == "Future") ? "/*info:INFERRED_TYPE_ALLOCATION*/" : ""; | 1923 (upwards == "Future") ? "/*info:INFERRED_TYPE_ALLOCATION*/" : ""; |
| 1983 return ''' | 1924 return ''' |
| 1984 import 'dart:async'; | 1925 import 'dart:async'; |
| 1985 class MyFuture<T> implements Future<T> { | 1926 class MyFuture<T> implements Future<T> { |
| 1986 MyFuture() {} | 1927 MyFuture() {} |
| 1987 MyFuture.value([x]) {} | 1928 MyFuture.value([x]) {} |
| 1988 dynamic noSuchMethod(invocation); | 1929 dynamic noSuchMethod(invocation); |
| 1989 MyFuture<S> then<S>(dynamic f(T x), {Function onError}) => null; | 1930 MyFuture<S> then<S>(FutureOr<S> f(T x), {Function onError}) => null; |
| 1990 } | 1931 } |
| 1991 | 1932 |
| 1992 $declared f; | 1933 $declared f; |
| 1993 // Instantiates Future<int> | |
| 1994 $downwards<int> t1 = f.then((_) => | |
| 1995 ${allocInfo}new $upwards.value('hi')); | |
| 1996 | |
| 1997 // Instantiates List<int> | |
| 1998 $downwards<List<int>> t2 = f.then((_) => /*info:INFERRED_TYPE_LITERAL*/[3]); | |
| 1999 $downwards<List<int>> g2() async { return /*info:INFERRED_TYPE_LITERAL*/[3]; } | |
| 2000 $downwards<List<int>> g3() async { | |
| 2001 return /*info:INFERRED_TYPE_ALLOCATION*/new $upwards.value( | |
| 2002 /*info:INFERRED_TYPE_LITERAL*/[3]); } | |
| 2003 '''; | |
| 2004 } | |
| 2005 | |
| 2006 ; | |
| 2007 checkFile( | |
| 2008 build(declared: "MyFuture", downwards: "Future", upwards: "Future")); | |
| 2009 checkFile( | |
| 2010 build(declared: "MyFuture", downwards: "Future", upwards: "MyFuture")); | |
| 2011 checkFile( | |
| 2012 build(declared: "Future", downwards: "Future", upwards: "Future")); | |
| 2013 checkFile( | |
| 2014 build(declared: "Future", downwards: "Future", upwards: "MyFuture")); | |
| 2015 } | |
| 2016 | |
| 2017 void test_futureUnion_downwards_comment() { | |
| 2018 String build({String declared, String downwards, String upwards}) { | |
| 2019 // TODO(leafp): The use of matchTypes in visitInstanceCreationExpression | |
| 2020 // in the resolver visitor isn't powerful enough to catch this for the | |
| 2021 // subclass. See the TODO there. | |
| 2022 var allocInfo = | |
| 2023 (upwards == "Future") ? "/*info:INFERRED_TYPE_ALLOCATION*/" : ""; | |
| 2024 return ''' | |
| 2025 import 'dart:async'; | |
| 2026 class MyFuture<T> implements Future<T> { | |
| 2027 MyFuture() {} | |
| 2028 MyFuture.value([x]) {} | |
| 2029 dynamic noSuchMethod(invocation); | |
| 2030 MyFuture/*<S>*/ then/*<S>*/(dynamic f(T x), {Function onError}) => null; | |
| 2031 } | |
| 2032 | |
| 2033 $declared f; | |
| 2034 // Instantiates Future<int> | 1934 // Instantiates Future<int> |
| 2035 $downwards<int> t1 = f.then((_) => | 1935 $downwards<int> t1 = f.then((_) => |
| 2036 ${allocInfo}new $upwards.value('hi')); | 1936 ${allocInfo}new $upwards.value('hi')); |
| 2037 | 1937 |
| 2038 // Instantiates List<int> | 1938 // Instantiates List<int> |
| 2039 $downwards<List<int>> t2 = f.then((_) => /*info:INFERRED_TYPE_LITERAL*/[3]); | 1939 $downwards<List<int>> t2 = f.then((_) => /*info:INFERRED_TYPE_LITERAL*/[3]); |
| 2040 $downwards<List<int>> g2() async { return /*info:INFERRED_TYPE_LITERAL*/[3]; } | 1940 $downwards<List<int>> g2() async { return /*info:INFERRED_TYPE_LITERAL*/[3]; } |
| 2041 $downwards<List<int>> g3() async { | 1941 $downwards<List<int>> g3() async { |
| 2042 return /*info:INFERRED_TYPE_ALLOCATION*/new $upwards.value( | 1942 return /*info:INFERRED_TYPE_ALLOCATION*/new $upwards.value( |
| 2043 /*info:INFERRED_TYPE_LITERAL*/[3]); } | 1943 /*info:INFERRED_TYPE_LITERAL*/[3]); } |
| 2044 '''; | 1944 '''; |
| 2045 } | 1945 } |
| 2046 | 1946 |
| 2047 ; | |
| 2048 checkFile( | 1947 checkFile( |
| 2049 build(declared: "MyFuture", downwards: "Future", upwards: "Future")); | 1948 build(declared: "MyFuture", downwards: "Future", upwards: "Future")); |
| 2050 checkFile( | 1949 checkFile( |
| 2051 build(declared: "MyFuture", downwards: "Future", upwards: "MyFuture")); | 1950 build(declared: "MyFuture", downwards: "Future", upwards: "MyFuture")); |
| 2052 checkFile( | 1951 checkFile( |
| 2053 build(declared: "Future", downwards: "Future", upwards: "Future")); | 1952 build(declared: "Future", downwards: "Future", upwards: "Future")); |
| 2054 checkFile( | 1953 checkFile( |
| 2055 build(declared: "Future", downwards: "Future", upwards: "MyFuture")); | 1954 build(declared: "Future", downwards: "Future", upwards: "MyFuture")); |
| 2056 } | 1955 } |
| 2057 | 1956 |
| (...skipping 601 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2659 void test_genericMethods_IterableAndFuture() { | 2558 void test_genericMethods_IterableAndFuture() { |
| 2660 checkFile(''' | 2559 checkFile(''' |
| 2661 import 'dart:async'; | 2560 import 'dart:async'; |
| 2662 | 2561 |
| 2663 Future<int> make(int x) => (/*info:INFERRED_TYPE_ALLOCATION*/new Future(() => x)
); | 2562 Future<int> make(int x) => (/*info:INFERRED_TYPE_ALLOCATION*/new Future(() => x)
); |
| 2664 | 2563 |
| 2665 main() { | 2564 main() { |
| 2666 Iterable<Future<int>> list = <int>[1, 2, 3].map(make); | 2565 Iterable<Future<int>> list = <int>[1, 2, 3].map(make); |
| 2667 Future<List<int>> results = Future.wait(list); | 2566 Future<List<int>> results = Future.wait(list); |
| 2668 Future<String> results2 = results.then((List<int> list) | 2567 Future<String> results2 = results.then((List<int> list) |
| 2669 => list.fold('', /*info:INFERRED_TYPE_CLOSURE*/(x, y) => x + y.toString())); | 2568 => list.fold('', /*info:INFERRED_TYPE_CLOSURE*/(x, y) => /*info:DYNAMIC_CAST
,info:DYNAMIC_INVOKE*/x /*error:UNDEFINED_OPERATOR*/+ y.toString())); |
| 2569 |
| 2570 Future<String> results3 = results.then((List<int> list) |
| 2571 => list.fold('', /*info:INFERRED_TYPE_CLOSURE*/(String x, y) => x + y.toStri
ng())); |
| 2670 } | 2572 } |
| 2671 '''); | 2573 '''); |
| 2672 } | 2574 } |
| 2673 | 2575 |
| 2674 void test_genericMethods_usesGreatestLowerBound() { | 2576 void test_genericMethods_usesGreatestLowerBound() { |
| 2675 var mainUnit = checkFile(r''' | 2577 var mainUnit = checkFile(r''' |
| 2676 typedef Iterable<num> F(int x); | 2578 typedef Iterable<num> F(int x); |
| 2677 typedef List<int> G(double x); | 2579 typedef List<int> G(double x); |
| 2678 | 2580 |
| 2679 T generic<T>(a(T _), b(T _)) => null; | 2581 T generic<T>(a(T _), b(T _)) => null; |
| (...skipping 2734 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5414 T run<T>(T f()) { | 5316 T run<T>(T f()) { |
| 5415 print("running"); | 5317 print("running"); |
| 5416 var t = f(); | 5318 var t = f(); |
| 5417 print("done running"); | 5319 print("done running"); |
| 5418 return t; | 5320 return t; |
| 5419 } | 5321 } |
| 5420 | 5322 |
| 5421 | 5323 |
| 5422 void printRunning() { print("running"); } | 5324 void printRunning() { print("running"); } |
| 5423 var x = run<dynamic>(printRunning); | 5325 var x = run<dynamic>(printRunning); |
| 5424 var y = run(printRunning); | 5326 var y = /*info:USE_OF_VOID_RESULT*/run(printRunning); |
| 5425 | 5327 |
| 5426 main() { | 5328 main() { |
| 5427 void printRunning() { print("running"); } | 5329 void printRunning() { print("running"); } |
| 5428 var x = run<dynamic>(printRunning); | 5330 var x = run<dynamic>(printRunning); |
| 5429 var y = run(printRunning); | 5331 var y = /*info:USE_OF_VOID_RESULT*/run(printRunning); |
| 5430 x = 123; | 5332 x = 123; |
| 5431 x = 'hi'; | 5333 x = 'hi'; |
| 5432 y = 123; | 5334 y = /*error:INVALID_ASSIGNMENT*/123; |
| 5433 y = 'hi'; | 5335 y = /*error:INVALID_ASSIGNMENT*/'hi'; |
| 5434 } | 5336 } |
| 5435 '''); | 5337 '''); |
| 5436 | 5338 |
| 5437 var x = unit.topLevelVariables[0]; | 5339 var x = unit.topLevelVariables[0]; |
| 5438 var y = unit.topLevelVariables[1]; | 5340 var y = unit.topLevelVariables[1]; |
| 5439 expect(x.type.toString(), 'dynamic'); | 5341 expect(x.type.toString(), 'dynamic'); |
| 5440 expect(y.type.toString(), 'dynamic'); | 5342 expect(y.type.toString(), 'void'); |
| 5441 } | |
| 5442 | |
| 5443 void test_voidReturnTypeSubtypesDynamic_comment() { | |
| 5444 var unit = checkFile(r''' | |
| 5445 /*=T*/ run/*<T>*/(/*=T*/ f()) { | |
| 5446 print("running"); | |
| 5447 var t = f(); | |
| 5448 print("done running"); | |
| 5449 return t; | |
| 5450 } | |
| 5451 | |
| 5452 | |
| 5453 void printRunning() { print("running"); } | |
| 5454 var x = run/*<dynamic>*/(printRunning); | |
| 5455 var y = run(printRunning); | |
| 5456 | |
| 5457 main() { | |
| 5458 void printRunning() { print("running"); } | |
| 5459 var x = run/*<dynamic>*/(printRunning); | |
| 5460 var y = run(printRunning); | |
| 5461 x = 123; | |
| 5462 x = 'hi'; | |
| 5463 y = 123; | |
| 5464 y = 'hi'; | |
| 5465 } | |
| 5466 '''); | |
| 5467 | |
| 5468 var x = unit.topLevelVariables[0]; | |
| 5469 var y = unit.topLevelVariables[1]; | |
| 5470 expect(x.type.toString(), 'dynamic'); | |
| 5471 expect(y.type.toString(), 'dynamic'); | |
| 5472 } | 5343 } |
| 5473 } | 5344 } |
| 5474 | 5345 |
| 5475 @reflectiveTest | 5346 @reflectiveTest |
| 5476 class InferredTypeTest extends InferredTypeMixin { | 5347 class InferredTypeTest extends InferredTypeMixin { |
| 5477 @override | 5348 @override |
| 5478 bool get mayCheckTypesOfLocals => true; | 5349 bool get mayCheckTypesOfLocals => true; |
| 5479 | 5350 |
| 5480 /// Adds a file to check. The file should contain: | 5351 /// Adds a file to check. The file should contain: |
| 5481 /// | 5352 /// |
| (...skipping 27 matching lines...) Expand all Loading... |
| 5509 } | 5380 } |
| 5510 | 5381 |
| 5511 void setUp() { | 5382 void setUp() { |
| 5512 helper.doSetUp(); | 5383 helper.doSetUp(); |
| 5513 } | 5384 } |
| 5514 | 5385 |
| 5515 void tearDown() { | 5386 void tearDown() { |
| 5516 helper.doTearDown(); | 5387 helper.doTearDown(); |
| 5517 } | 5388 } |
| 5518 } | 5389 } |
| OLD | NEW |