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 /// General type checking tests | 7 /// General type checking tests |
8 library analyzer.test.src.task.strong.checker_test; | 8 library analyzer.test.src.task.strong.checker_test; |
9 | 9 |
10 import 'package:unittest/unittest.dart'; | 10 import '../../../reflective_tests.dart'; |
11 | |
12 import 'strong_test_helper.dart'; | 11 import 'strong_test_helper.dart'; |
13 | 12 |
14 void main() { | 13 void main() { |
15 initStrongModeTests(); | 14 initStrongModeTests(); |
16 | 15 runReflectiveTests(CheckerTest); |
17 test('ternary operator', () { | 16 } |
18 checkFile(''' | 17 |
19 abstract class Comparable<T> { | 18 @reflectiveTest |
20 int compareTo(T other); | 19 class CheckerTest { |
21 static int compare(Comparable a, Comparable b) => a.compareTo(b); | 20 void test_awaitForInCastsStreamElementToVariable() { |
22 } | 21 checkFile(''' |
23 typedef int Comparator<T>(T a, T b); | 22 import 'dart:async'; |
24 | 23 main() async { |
25 typedef bool _Predicate<T>(T value); | 24 // Don't choke if sequence is not stream. |
26 | 25 await for (var i in /*warning:FOR_IN_OF_INVALID_TYPE*/1234) {} |
27 class SplayTreeMap<K, V> { | 26 |
28 Comparator<K> _comparator; | 27 // Dynamic cast. |
29 _Predicate _validKey; | 28 await for (String /*info:DYNAMIC_CAST*/s in new Stream<dynamic>()) {} |
30 | 29 |
31 // The warning on assigning to _comparator is legitimate. Since K has | 30 // Identity cast. |
32 // no bound, all we know is that it's object. _comparator's function | 31 await for (String s in new Stream<String>()) {} |
33 // type is effectively: (Object, Object) -> int | 32 |
34 // We are assigning it a fn of type: (Comparable, Comparable) -> int | 33 // Untyped. |
35 // There's no telling if that will work. For example, consider: | 34 await for (var s in new Stream<String>()) {} |
36 // | 35 |
37 // new SplayTreeMap<Uri>(); | 36 // Downcast. |
38 // | 37 await for (int /*info:DOWN_CAST_IMPLICIT*/i in new Stream<num>()) {} |
39 // This would end up calling .compareTo() on a Uri, which doesn't | 38 } |
40 // define that since it doesn't implement Comparable. | 39 '''); |
41 SplayTreeMap([int compare(K key1, K key2), | 40 } |
42 bool isValidKey(potentialKey)]) | 41 |
43 : _comparator = /*warning:DOWN_CAST_COMPOSITE*/(compare == null) ? C
omparable.compare : compare, | 42 void test_awaitForInCastsSupertypeSequenceToStream() { |
44 _validKey = (isValidKey != null) ? isValidKey : ((v) => true) { | 43 checkFile(''' |
45 _Predicate<Object> v = (isValidKey != null) | 44 main() async { |
46 ? isValidKey : (/*info:INFERRED_TYPE_CLOSURE*/(_) => true); | 45 dynamic d; |
47 | 46 await for (var i in /*info:DYNAMIC_CAST*/d) {} |
48 v = (isValidKey != null) | 47 |
49 ? v : (/*info:INFERRED_TYPE_CLOSURE*/(_) => true); | 48 Object o; |
50 } | 49 await for (var i in /*info:DOWN_CAST_IMPLICIT*/o) {} |
51 } | 50 } |
52 void main() { | 51 '''); |
53 Object obj = 42; | 52 } |
54 dynamic dyn = 42; | 53 |
55 int i = 42; | 54 void test_binaryAndIndexOperators() { |
56 | 55 checkFile(''' |
57 // Check the boolean conversion of the condition. | 56 class A { |
58 print(/*warning:NON_BOOL_CONDITION*/i ? false : true); | 57 A operator *(B b) => null; |
59 print((/*info:DOWN_CAST_IMPLICIT*/obj) ? false : true); | 58 A operator /(B b) => null; |
60 print((/*info:DYNAMIC_CAST*/dyn) ? false : true); | 59 A operator ~/(B b) => null; |
61 } | 60 A operator %(B b) => null; |
62 '''); | 61 A operator +(B b) => null; |
63 }); | 62 A operator -(B b) => null; |
64 | 63 A operator <<(B b) => null; |
65 test('least upper bounds', () { | 64 A operator >>(B b) => null; |
66 checkFile(''' | 65 A operator &(B b) => null; |
67 typedef T Returns<T>(); | 66 A operator ^(B b) => null; |
68 | 67 A operator |(B b) => null; |
69 // regression test for https://github.com/dart-lang/sdk/issues/26094 | 68 A operator[](B b) => null; |
70 class A <S extends Returns<S>, T extends Returns<T>> { | 69 } |
71 int test(bool b) { | 70 |
72 S s; | 71 class B { |
73 T t; | 72 A operator -(B b) => null; |
74 if (b) { | 73 } |
75 return /*warning:RETURN_OF_INVALID_TYPE*/b ? s : t; | 74 |
76 } else { | 75 foo() => new A(); |
77 return /*warning:RETURN_OF_INVALID_TYPE*/s ?? t; | 76 |
78 } | 77 test() { |
79 } | 78 A a = new A(); |
80 } | 79 B b = new B(); |
81 | 80 var c = foo(); |
82 class B<S, T extends S> { | 81 a = a * b; |
83 T t; | 82 a = a * /*info:DYNAMIC_CAST*/c; |
84 S s; | 83 a = a / b; |
85 int test(bool b) { | 84 a = a ~/ b; |
86 return /*warning:RETURN_OF_INVALID_TYPE*/b ? t : s; | 85 a = a % b; |
87 } | 86 a = a + b; |
88 } | 87 a = a + /*warning:ARGUMENT_TYPE_NOT_ASSIGNABLE*/a; |
89 | 88 a = a - b; |
90 class C { | 89 b = /*warning:INVALID_ASSIGNMENT*/b - b; |
91 // Check that the least upper bound of two types with the same | 90 a = a << b; |
92 // class but different type arguments produces the pointwise | 91 a = a >> b; |
93 // least upper bound of the type arguments | 92 a = a & b; |
94 int test1(bool b) { | 93 a = a ^ b; |
95 List<int> li; | 94 a = a | b; |
96 List<double> ld; | 95 c = (/*info:DYNAMIC_INVOKE*/c + b); |
97 return /*warning:RETURN_OF_INVALID_TYPE*/b ? li : ld; | 96 |
98 } | 97 String x = 'hello'; |
99 // TODO(leafp): This case isn't handled yet. This test checks | 98 int y = 42; |
100 // the case where two related classes are instantiated with related | 99 x = x + x; |
101 // but different types. | 100 x = x + /*info:DYNAMIC_CAST*/c; |
102 Iterable<num> test2(bool b) { | 101 x = x + /*warning:ARGUMENT_TYPE_NOT_ASSIGNABLE*/y; |
103 List<int> li; | 102 |
104 Iterable<double> id; | 103 bool p = true; |
105 int x = | 104 p = p && p; |
106 /*info:ASSIGNMENT_CAST should be warning:INVALID_ASSIGNMENT*/ | 105 p = p && /*info:DYNAMIC_CAST*/c; |
107 b ? li : id; | 106 p = (/*info:DYNAMIC_CAST*/c) && p; |
108 return /*warning:DOWN_CAST_COMPOSITE should be pass*/b ? li : id; | 107 p = (/*info:DYNAMIC_CAST*/c) && /*info:DYNAMIC_CAST*/c; |
109 } | 108 p = /*warning:NON_BOOL_OPERAND*/y && p; |
110 } | 109 p = c == y; |
111 '''); | 110 |
112 }); | 111 a = a[b]; |
113 | 112 a = a[/*info:DYNAMIC_CAST*/c]; |
114 test('setter return types', () { | 113 c = (/*info:DYNAMIC_INVOKE*/c[b]); |
115 checkFile(''' | 114 a[/*warning:ARGUMENT_TYPE_NOT_ASSIGNABLE*/y]; |
116 void voidFn() => null; | 115 } |
117 class A { | 116 '''); |
118 set a(y) => 4; | 117 } |
119 set b(y) => voidFn(); | 118 |
120 void set c(y) => /*warning:RETURN_OF_INVALID_TYPE*/4; | 119 void test_castsInConditions() { |
121 void set d(y) => voidFn(); | 120 checkFile(''' |
122 /*warning:NON_VOID_RETURN_FOR_SETTER*/int set e(y) => 4; | 121 main() { |
123 /*warning:NON_VOID_RETURN_FOR_SETTER*/int set f(y) => | 122 bool b = true; |
124 /*warning:RETURN_OF_INVALID_TYPE*/voidFn(); | 123 num x = b ? 1 : 2.3; |
125 set g(y) {return /*warning:RETURN_OF_INVALID_TYPE*/4;} | 124 int y = /*info:ASSIGNMENT_CAST*/b ? 1 : 2.3; |
126 void set h(y) {return /*warning:RETURN_OF_INVALID_TYPE*/4;} | 125 String z = !b ? "hello" : null; |
127 /*warning:NON_VOID_RETURN_FOR_SETTER*/int set i(y) {return 4;} | 126 z = b ? null : "hello"; |
128 } | 127 } |
129 '''); | 128 '''); |
130 }); | 129 } |
131 | 130 |
132 test('if/for/do/while statements use boolean conversion', () { | 131 void test_castsInConstantContexts() { |
133 checkFile(''' | 132 checkFile(''' |
134 main() { | 133 class A { |
135 dynamic dyn = 42; | 134 static const num n = 3.0; |
136 Object obj = 42; | 135 // The severe error is from constant evaluation where we know the |
137 int i = 42; | 136 // concrete type. |
138 bool b = false; | 137 static const int /*severe:VARIABLE_TYPE_MISMATCH*/i = /*info:ASSIGNMENT_CAST*/
n; |
139 | 138 final int fi; |
140 if (b) {} | 139 const A(num a) : this.fi = /*info:DOWN_CAST_IMPLICIT*/a; |
141 if (/*info:DYNAMIC_CAST*/dyn) {} | 140 } |
142 if (/*info:DOWN_CAST_IMPLICIT*/obj) {} | 141 class B extends A { |
143 if (/*warning:NON_BOOL_CONDITION*/i) {} | 142 const B(Object a) : super(/*info:DOWN_CAST_IMPLICIT*/a); |
144 | 143 } |
145 while (b) {} | 144 void foo(Object o) { |
146 while (/*info:DYNAMIC_CAST*/dyn) {} | 145 var a = const A(/*info:DOWN_CAST_IMPLICIT, severe:CONST_WITH_NON_CONSTANT_ARGU
MENT, severe:INVALID_CONSTANT*/o); |
147 while (/*info:DOWN_CAST_IMPLICIT*/obj) {} | 146 } |
148 while (/*warning:NON_BOOL_CONDITION*/i) {} | 147 '''); |
149 | 148 } |
150 do {} while (b); | 149 |
151 do {} while (/*info:DYNAMIC_CAST*/dyn); | 150 void test_classOverrideOfGrandInterface_interfaceOfAbstractSuperclass() { |
152 do {} while (/*info:DOWN_CAST_IMPLICIT*/obj); | 151 checkFile(''' |
153 do {} while (/*warning:NON_BOOL_CONDITION*/i); | 152 class A {} |
154 | 153 class B {} |
155 for (;b;) {} | 154 |
156 for (;/*info:DYNAMIC_CAST*/dyn;) {} | 155 abstract class I1 { |
157 for (;/*info:DOWN_CAST_IMPLICIT*/obj;) {} | 156 m(A a); |
158 for (;/*warning:NON_BOOL_CONDITION*/i;) {} | 157 } |
159 } | 158 abstract class Base implements I1 {} |
160 '''); | 159 |
161 }); | 160 class T1 extends Base { |
162 | 161 /*severe:INVALID_METHOD_OVERRIDE*/m( |
163 test('for-in casts supertype sequence to iterable', () { | 162 /*warning:INVALID_METHOD_OVERRIDE_NORMAL_PARAM_TYPE*/B a) {} |
164 checkFile(''' | 163 } |
165 main() { | 164 '''); |
166 dynamic d; | 165 } |
167 for (var i in /*info:DYNAMIC_CAST*/d) {} | 166 |
168 | 167 void test_classOverrideOfGrandInterface_interfaceOfConcreteSuperclass() { |
169 Object o; | 168 checkFile(''' |
170 for (var i in /*info:DOWN_CAST_IMPLICIT*/o) {} | 169 class A {} |
171 } | 170 class B {} |
172 '''); | 171 |
173 }); | 172 abstract class I1 { |
174 | 173 m(A a); |
175 test('await for-in casts supertype sequence to stream', () { | 174 } |
176 checkFile(''' | 175 |
177 main() async { | 176 class /*warning:NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_ONE*/Base |
178 dynamic d; | 177 implements I1 {} |
179 await for (var i in /*info:DYNAMIC_CAST*/d) {} | 178 |
180 | 179 class T1 extends Base { |
181 Object o; | 180 // not reported technically because if the class is concrete, |
182 await for (var i in /*info:DOWN_CAST_IMPLICIT*/o) {} | 181 // it should implement all its interfaces and hence it is |
183 } | 182 // sufficient to check overrides against it. |
184 '''); | 183 m(/*warning:INVALID_METHOD_OVERRIDE_NORMAL_PARAM_TYPE*/B a) {} |
185 }); | 184 } |
186 | 185 '''); |
187 test('for-in casts iterable element to variable', () { | 186 } |
188 checkFile(''' | 187 |
189 main() { | 188 void test_classOverrideOfGrandInterface_interfaceOfInterfaceOfChild() { |
190 // Don't choke if sequence is not iterable. | 189 checkFile(''' |
191 for (var i in /*warning:FOR_IN_OF_INVALID_TYPE*/1234) {} | 190 class A {} |
192 | 191 class B {} |
193 // Dynamic cast. | 192 |
194 for (String /*info:DYNAMIC_CAST*/s in <dynamic>[]) {} | 193 abstract class I1 { |
195 | 194 m(A a); |
196 // Identity cast. | 195 } |
197 for (String s in <String>[]) {} | 196 abstract class I2 implements I1 {} |
198 | 197 |
199 // Untyped. | 198 class T1 implements I2 { |
200 for (var s in <String>[]) {} | 199 /*severe:INVALID_METHOD_OVERRIDE*/m( |
201 | 200 /*warning:INVALID_METHOD_OVERRIDE_NORMAL_PARAM_TYPE*/B a) {} |
202 // Downcast. | 201 } |
203 for (int /*info:DOWN_CAST_IMPLICIT*/i in <num>[]) {} | 202 '''); |
204 } | 203 } |
205 '''); | 204 |
206 }); | 205 void test_classOverrideOfGrandInterface_mixinOfInterfaceOfChild() { |
207 | 206 checkFile(''' |
208 test('await for-in casts stream element to variable', () { | 207 class A {} |
209 checkFile(''' | 208 class B {} |
210 import 'dart:async'; | 209 |
211 main() async { | 210 abstract class M1 { |
212 // Don't choke if sequence is not stream. | 211 m(A a); |
213 await for (var i in /*warning:FOR_IN_OF_INVALID_TYPE*/1234) {} | 212 } |
214 | 213 abstract class I2 extends Object with M1 {} |
215 // Dynamic cast. | 214 |
216 await for (String /*info:DYNAMIC_CAST*/s in new Stream<dynamic>()) {} | 215 class T1 implements I2 { |
217 | 216 /*severe:INVALID_METHOD_OVERRIDE*/m( |
218 // Identity cast. | 217 /*warning:INVALID_METHOD_OVERRIDE_NORMAL_PARAM_TYPE*/B a) {} |
219 await for (String s in new Stream<String>()) {} | 218 } |
220 | 219 '''); |
221 // Untyped. | 220 } |
222 await for (var s in new Stream<String>()) {} | 221 |
223 | 222 void test_classOverrideOfGrandInterface_superclassOfInterfaceOfChild() { |
224 // Downcast. | 223 checkFile(''' |
225 await for (int /*info:DOWN_CAST_IMPLICIT*/i in new Stream<num>()) {} | 224 class A {} |
226 } | 225 class B {} |
227 '''); | 226 |
228 }); | 227 abstract class I1 { |
229 | 228 m(A a); |
230 test('dynamic invocation', () { | 229 } |
231 checkFile(''' | 230 abstract class I2 extends I1 {} |
232 typedef dynamic A(dynamic x); | 231 |
233 class B { | 232 class T1 implements I2 { |
234 int call(int x) => x; | 233 /*severe:INVALID_METHOD_OVERRIDE*/m( |
235 double col(double x) => x; | 234 /*warning:INVALID_METHOD_OVERRIDE_NORMAL_PARAM_TYPE*/B a) {} |
236 } | 235 } |
237 void main() { | 236 '''); |
238 { | 237 } |
239 B f = new B(); | 238 |
240 int x; | 239 void test_compoundAssignments() { |
241 double y; | 240 checkFile(''' |
242 x = f(3); | 241 class A { |
243 x = /*warning:INVALID_ASSIGNMENT*/f.col(3.0); | 242 A operator *(B b) => null; |
244 y = /*warning:INVALID_ASSIGNMENT*/f(3); | 243 A operator /(B b) => null; |
245 y = f.col(3.0); | 244 A operator ~/(B b) => null; |
246 f(/*warning:ARGUMENT_TYPE_NOT_ASSIGNABLE*/3.0); | 245 A operator %(B b) => null; |
247 f.col(/*warning:ARGUMENT_TYPE_NOT_ASSIGNABLE*/3); | 246 A operator +(B b) => null; |
248 } | 247 A operator -(B b) => null; |
249 { | 248 A operator <<(B b) => null; |
250 Function f = new B(); | 249 A operator >>(B b) => null; |
251 int x; | 250 A operator &(B b) => null; |
252 double y; | 251 A operator ^(B b) => null; |
253 x = /*info:DYNAMIC_CAST, info:DYNAMIC_INVOKE*/f(3); | 252 A operator |(B b) => null; |
254 x = /*info:DYNAMIC_CAST, info:DYNAMIC_INVOKE, info:INVALID_ASSIGNMENT*
/f.col(3.0); | 253 D operator [](B index) => null; |
255 y = /*info:DYNAMIC_CAST, info:DYNAMIC_INVOKE*/f(3); | 254 void operator []=(B index, D value) => null; |
256 y = /*info:DYNAMIC_CAST, info:DYNAMIC_INVOKE*/f.col(3.0); | 255 } |
257 /*info:DYNAMIC_INVOKE*/f(3.0); | 256 |
258 // Through type propagation, we know f is actually a B, hence the | 257 class B { |
259 // hint. | 258 A operator -(B b) => null; |
260 /*info:DYNAMIC_INVOKE*/f.col(/*info:ARGUMENT_TYPE_NOT_ASSIGNABLE*/3); | 259 } |
261 } | 260 |
262 { | 261 class D { |
263 A f = new B(); | 262 D operator +(D d) => null; |
264 int x; | 263 } |
265 double y; | 264 |
266 x = /*info:DYNAMIC_CAST, info:DYNAMIC_INVOKE*/f(3); | 265 foo() => new A(); |
267 y = /*info:DYNAMIC_CAST, info:DYNAMIC_INVOKE*/f(3); | 266 |
268 /*info:DYNAMIC_INVOKE*/f(3.0); | 267 test() { |
269 } | 268 int x = 0; |
270 { | 269 x += 5; |
271 dynamic g = new B(); | 270 /*severe:STATIC_TYPE_ERROR*/x += 3.14; |
272 /*info:DYNAMIC_INVOKE*/g.call(/*info:ARGUMENT_TYPE_NOT_ASSIGNABLE*/32.
0); | 271 |
273 /*info:DYNAMIC_INVOKE*/g.col(42.0); | 272 double y = 0.0; |
274 /*info:DYNAMIC_INVOKE*/g.foo(42.0); | 273 y += 5; |
275 /*info:DYNAMIC_INVOKE*/g./*info:UNDEFINED_GETTER*/x; | 274 y += 3.14; |
276 A f = new B(); | 275 |
277 /*info:DYNAMIC_INVOKE*/f.col(42.0); | 276 num z = 0; |
278 /*info:DYNAMIC_INVOKE*/f.foo(42.0); | 277 z += 5; |
279 /*info:DYNAMIC_INVOKE*/f./*warning:UNDEFINED_GETTER*/x; | 278 z += 3.14; |
280 } | 279 |
281 } | 280 x = /*info:DOWN_CAST_IMPLICIT*/x + z; |
282 '''); | 281 x += /*info:DOWN_CAST_IMPLICIT*/z; |
283 }); | 282 y = y + z; |
284 | 283 y += z; |
285 test('conversion and dynamic invoke', () { | 284 |
| 285 dynamic w = 42; |
| 286 x += /*info:DYNAMIC_CAST*/w; |
| 287 y += /*info:DYNAMIC_CAST*/w; |
| 288 z += /*info:DYNAMIC_CAST*/w; |
| 289 |
| 290 A a = new A(); |
| 291 B b = new B(); |
| 292 var c = foo(); |
| 293 a = a * b; |
| 294 a *= b; |
| 295 a *= /*info:DYNAMIC_CAST*/c; |
| 296 a /= b; |
| 297 a ~/= b; |
| 298 a %= b; |
| 299 a += b; |
| 300 a += /*warning:ARGUMENT_TYPE_NOT_ASSIGNABLE*/a; |
| 301 a -= b; |
| 302 /*severe:STATIC_TYPE_ERROR*/b -= /*warning:INVALID_ASSIGNMENT*/b; |
| 303 a <<= b; |
| 304 a >>= b; |
| 305 a &= b; |
| 306 a ^= b; |
| 307 a |= b; |
| 308 /*info:DYNAMIC_INVOKE*/c += b; |
| 309 |
| 310 var d = new D(); |
| 311 a[b] += d; |
| 312 a[/*info:DYNAMIC_CAST*/c] += d; |
| 313 a[/*warning:ARGUMENT_TYPE_NOT_ASSIGNABLE*/z] += d; |
| 314 a[b] += /*info:DYNAMIC_CAST*/c; |
| 315 a[b] += /*warning:ARGUMENT_TYPE_NOT_ASSIGNABLE*/z; |
| 316 /*info:DYNAMIC_INVOKE,info:DYNAMIC_INVOKE*/c[b] += d; |
| 317 } |
| 318 '''); |
| 319 } |
| 320 |
| 321 void test_constructors() { |
| 322 checkFile(''' |
| 323 const num z = 25; |
| 324 Object obj = "world"; |
| 325 |
| 326 class A { |
| 327 int x; |
| 328 String y; |
| 329 |
| 330 A(this.x) : this.y = /*warning:FIELD_INITIALIZER_NOT_ASSIGNABLE*/42; |
| 331 |
| 332 A.c1(p): this.x = /*info:DOWN_CAST_IMPLICIT*/z, this.y = /*info:DYNAMIC_CAST*/
p; |
| 333 |
| 334 A.c2(this.x, this.y); |
| 335 |
| 336 A.c3(/*severe:INVALID_PARAMETER_DECLARATION*/num this.x, String this.y); |
| 337 } |
| 338 |
| 339 class B extends A { |
| 340 B() : super(/*warning:ARGUMENT_TYPE_NOT_ASSIGNABLE*/"hello"); |
| 341 |
| 342 B.c2(int x, String y) : super.c2(/*warning:ARGUMENT_TYPE_NOT_ASSIGNABLE*/y, |
| 343 /*warning:ARGUMENT_TYPE_NOT_ASSIGNABLE*/x); |
| 344 |
| 345 B.c3(num x, Object y) : super.c3(x, /*info:DOWN_CAST_IMPLICIT*/y); |
| 346 } |
| 347 |
| 348 void main() { |
| 349 A a = new A.c2(/*info:DOWN_CAST_IMPLICIT*/z, /*warning:ARGUMENT_TYPE_NOT_ASSI
GNABLE*/z); |
| 350 var b = new B.c2(/*warning:ARGUMENT_TYPE_NOT_ASSIGNABLE*/"hello", /*info:DOWN
_CAST_IMPLICIT*/obj); |
| 351 } |
| 352 '''); |
| 353 } |
| 354 |
| 355 void test_conversionAndDynamicInvoke() { |
286 addFile( | 356 addFile( |
287 ''' | 357 ''' |
288 dynamic toString = (int x) => x + 42; | 358 dynamic toString = (int x) => x + 42; |
289 dynamic hashCode = "hello"; | 359 dynamic hashCode = "hello"; |
290 ''', | 360 ''', |
291 name: '/helper.dart'); | 361 name: '/helper.dart'); |
292 checkFile(''' | 362 checkFile(''' |
293 import 'helper.dart' as helper; | 363 import 'helper.dart' as helper; |
294 | 364 |
295 class A { | 365 class A { |
296 String x = "hello world"; | 366 String x = "hello world"; |
297 | 367 |
298 void baz1(y) { x + /*info:DYNAMIC_CAST*/y; } | 368 void baz1(y) { x + /*info:DYNAMIC_CAST*/y; } |
299 static baz2(y) => /*info:DYNAMIC_INVOKE*/y + y; | 369 static baz2(y) => /*info:DYNAMIC_INVOKE*/y + y; |
300 } | 370 } |
301 | 371 |
302 void foo(String str) { | 372 void foo(String str) { |
303 print(str); | 373 print(str); |
304 } | 374 } |
305 | 375 |
306 class B { | 376 class B { |
307 String toString([int arg]) => arg.toString(); | 377 String toString([int arg]) => arg.toString(); |
308 } | 378 } |
309 | 379 |
310 void bar(a) { | 380 void bar(a) { |
311 foo(/*info:DYNAMIC_CAST,info:DYNAMIC_INVOKE*/a.x); | 381 foo(/*info:DYNAMIC_CAST,info:DYNAMIC_INVOKE*/a.x); |
312 } | 382 } |
313 | 383 |
314 baz() => new B(); | 384 baz() => new B(); |
315 | 385 |
316 typedef DynFun(x); | 386 typedef DynFun(x); |
317 typedef StrFun(String x); | 387 typedef StrFun(String x); |
318 | 388 |
319 var bar1 = bar; | 389 var bar1 = bar; |
320 | 390 |
321 void main() { | 391 void main() { |
322 var a = new A(); | 392 var a = new A(); |
323 bar(a); | 393 bar(a); |
324 (/*info:DYNAMIC_INVOKE*/bar1(a)); | 394 (/*info:DYNAMIC_INVOKE*/bar1(a)); |
325 var b = bar; | 395 var b = bar; |
326 (/*info:DYNAMIC_INVOKE*/b(a)); | 396 (/*info:DYNAMIC_INVOKE*/b(a)); |
327 var f1 = foo; | 397 var f1 = foo; |
328 f1("hello"); | 398 f1("hello"); |
329 dynamic f2 = foo; | 399 dynamic f2 = foo; |
330 (/*info:DYNAMIC_INVOKE*/f2("hello")); | 400 (/*info:DYNAMIC_INVOKE*/f2("hello")); |
331 DynFun f3 = foo; | 401 DynFun f3 = foo; |
332 (/*info:DYNAMIC_INVOKE*/f3("hello")); | 402 (/*info:DYNAMIC_INVOKE*/f3("hello")); |
333 (/*info:DYNAMIC_INVOKE*/f3(42)); | 403 (/*info:DYNAMIC_INVOKE*/f3(42)); |
334 StrFun f4 = foo; | 404 StrFun f4 = foo; |
335 f4("hello"); | 405 f4("hello"); |
336 a.baz1("hello"); | 406 a.baz1("hello"); |
337 var b1 = a.baz1; | 407 var b1 = a.baz1; |
338 (/*info:DYNAMIC_INVOKE*/b1("hello")); | 408 (/*info:DYNAMIC_INVOKE*/b1("hello")); |
339 A.baz2("hello"); | 409 A.baz2("hello"); |
340 var b2 = A.baz2; | 410 var b2 = A.baz2; |
341 (/*info:DYNAMIC_INVOKE*/b2("hello")); | 411 (/*info:DYNAMIC_INVOKE*/b2("hello")); |
342 | 412 |
343 dynamic a1 = new B(); | 413 dynamic a1 = new B(); |
344 (/*info:DYNAMIC_INVOKE*/a1./*info:UNDEFINED_GETTER*/x); | 414 (/*info:DYNAMIC_INVOKE*/a1./*info:UNDEFINED_GETTER*/x); |
345 a1.toString(); | 415 a1.toString(); |
346 (/*info:DYNAMIC_INVOKE*/a1.toString(42)); | 416 (/*info:DYNAMIC_INVOKE*/a1.toString(42)); |
347 var toStringClosure = a1.toString; | 417 var toStringClosure = a1.toString; |
348 (/*info:DYNAMIC_INVOKE*/a1.toStringClosure()); | 418 (/*info:DYNAMIC_INVOKE*/a1.toStringClosure()); |
349 (/*info:DYNAMIC_INVOKE*/a1.toStringClosure(42)); | 419 (/*info:DYNAMIC_INVOKE*/a1.toStringClosure(42)); |
350 (/*info:DYNAMIC_INVOKE*/a1.toStringClosure("hello")); | 420 (/*info:DYNAMIC_INVOKE*/a1.toStringClosure("hello")); |
351 a1.hashCode; | 421 a1.hashCode; |
352 | 422 |
353 dynamic toString = () => null; | 423 dynamic toString = () => null; |
354 (/*info:DYNAMIC_INVOKE*/toString()); | 424 (/*info:DYNAMIC_INVOKE*/toString()); |
355 | 425 |
356 (/*info:DYNAMIC_INVOKE*/helper.toString()); | 426 (/*info:DYNAMIC_INVOKE*/helper.toString()); |
357 var toStringClosure2 = helper.toString; | 427 var toStringClosure2 = helper.toString; |
358 (/*info:DYNAMIC_INVOKE*/toStringClosure2()); | 428 (/*info:DYNAMIC_INVOKE*/toStringClosure2()); |
359 int hashCode = /*info:DYNAMIC_CAST*/helper.hashCode; | 429 int hashCode = /*info:DYNAMIC_CAST*/helper.hashCode; |
360 | 430 |
361 baz().toString(); | 431 baz().toString(); |
362 baz().hashCode; | 432 baz().hashCode; |
363 } | 433 } |
364 '''); | 434 '''); |
365 }); | 435 } |
366 | 436 |
367 test('Constructors', () { | 437 void test_dynamicInvocation() { |
368 checkFile(''' | 438 checkFile(''' |
369 const num z = 25; | 439 typedef dynamic A(dynamic x); |
370 Object obj = "world"; | 440 class B { |
371 | 441 int call(int x) => x; |
372 class A { | 442 double col(double x) => x; |
373 int x; | 443 } |
374 String y; | 444 void main() { |
375 | 445 { |
376 A(this.x) : this.y = /*warning:FIELD_INITIALIZER_NOT_ASSIGNABLE*/42; | 446 B f = new B(); |
377 | 447 int x; |
378 A.c1(p): this.x = /*info:DOWN_CAST_IMPLICIT*/z, this.y = /*info:DYNAMIC_
CAST*/p; | 448 double y; |
379 | 449 x = f(3); |
380 A.c2(this.x, this.y); | 450 x = /*warning:INVALID_ASSIGNMENT*/f.col(3.0); |
381 | 451 y = /*warning:INVALID_ASSIGNMENT*/f(3); |
382 A.c3(/*severe:INVALID_PARAMETER_DECLARATION*/num this.x, String this.y); | 452 y = f.col(3.0); |
383 } | 453 f(/*warning:ARGUMENT_TYPE_NOT_ASSIGNABLE*/3.0); |
384 | 454 f.col(/*warning:ARGUMENT_TYPE_NOT_ASSIGNABLE*/3); |
385 class B extends A { | 455 } |
386 B() : super(/*warning:ARGUMENT_TYPE_NOT_ASSIGNABLE*/"hello"); | 456 { |
387 | 457 Function f = new B(); |
388 B.c2(int x, String y) : super.c2(/*warning:ARGUMENT_TYPE_NOT_ASSIGNABLE*
/y, | 458 int x; |
389 /*warning:ARGUMENT_TYPE_NOT_ASSIGNABLE*
/x); | 459 double y; |
390 | 460 x = /*info:DYNAMIC_CAST, info:DYNAMIC_INVOKE*/f(3); |
391 B.c3(num x, Object y) : super.c3(x, /*info:DOWN_CAST_IMPLICIT*/y); | 461 x = /*info:DYNAMIC_CAST, info:DYNAMIC_INVOKE, info:INVALID_ASSIGNMENT*/f.col
(3.0); |
392 } | 462 y = /*info:DYNAMIC_CAST, info:DYNAMIC_INVOKE*/f(3); |
393 | 463 y = /*info:DYNAMIC_CAST, info:DYNAMIC_INVOKE*/f.col(3.0); |
394 void main() { | 464 /*info:DYNAMIC_INVOKE*/f(3.0); |
395 A a = new A.c2(/*info:DOWN_CAST_IMPLICIT*/z, /*warning:ARGUMENT_TYPE_NO
T_ASSIGNABLE*/z); | 465 // Through type propagation, we know f is actually a B, hence the |
396 var b = new B.c2(/*warning:ARGUMENT_TYPE_NOT_ASSIGNABLE*/"hello", /*inf
o:DOWN_CAST_IMPLICIT*/obj); | 466 // hint. |
397 } | 467 /*info:DYNAMIC_INVOKE*/f.col(/*info:ARGUMENT_TYPE_NOT_ASSIGNABLE*/3); |
398 '''); | 468 } |
399 }); | 469 { |
400 | 470 A f = new B(); |
401 test('Unbound variable', () { | 471 int x; |
402 checkFile(''' | 472 double y; |
403 void main() { | 473 x = /*info:DYNAMIC_CAST, info:DYNAMIC_INVOKE*/f(3); |
404 dynamic y = /*warning:UNDEFINED_IDENTIFIER should be error*/unboundVari
able; | 474 y = /*info:DYNAMIC_CAST, info:DYNAMIC_INVOKE*/f(3); |
405 } | 475 /*info:DYNAMIC_INVOKE*/f(3.0); |
406 '''); | 476 } |
407 }); | 477 { |
408 | 478 dynamic g = new B(); |
409 test('Unbound type name', () { | 479 /*info:DYNAMIC_INVOKE*/g.call(/*info:ARGUMENT_TYPE_NOT_ASSIGNABLE*/32.0); |
410 checkFile(''' | 480 /*info:DYNAMIC_INVOKE*/g.col(42.0); |
411 void main() { | 481 /*info:DYNAMIC_INVOKE*/g.foo(42.0); |
412 /*warning:UNDEFINED_CLASS should be error*/AToB y; | 482 /*info:DYNAMIC_INVOKE*/g./*info:UNDEFINED_GETTER*/x; |
413 } | 483 A f = new B(); |
414 '''); | 484 /*info:DYNAMIC_INVOKE*/f.col(42.0); |
415 }); | 485 /*info:DYNAMIC_INVOKE*/f.foo(42.0); |
416 | 486 /*info:DYNAMIC_INVOKE*/f./*warning:UNDEFINED_GETTER*/x; |
417 // Regression test for https://github.com/dart-lang/sdk/issues/25069 | 487 } |
418 test('Void subtyping', () { | 488 } |
419 checkFile(''' | 489 '''); |
420 typedef int Foo(); | 490 } |
421 void foo() {} | 491 |
422 void main () { | 492 void test_factoryConstructorDowncast() { |
423 Foo x = /*warning:INVALID_ASSIGNMENT,info:USE_OF_VOID_RESULT*/foo(); | 493 checkFile(r''' |
424 } | 494 class Animal { |
425 '''); | 495 Animal(); |
426 }); | 496 factory Animal.cat() => new Cat(); |
427 | 497 } |
428 group('Ground type subtyping:', () { | 498 |
429 test('dynamic is top', () { | 499 class Cat extends Animal {} |
430 checkFile(''' | 500 |
431 | 501 void main() { |
432 class A {} | 502 Cat c = /*info:ASSIGNMENT_CAST*/new Animal.cat(); |
433 class B extends A {} | 503 c = /*severe:STATIC_TYPE_ERROR*/new Animal(); |
434 | 504 }'''); |
435 void main() { | 505 } |
436 dynamic y; | 506 |
437 Object o; | 507 void test_fieldFieldOverride() { |
438 int i = 0; | 508 checkFile(''' |
439 double d = 0.0; | 509 class A {} |
440 num n; | 510 class B extends A {} |
441 A a; | 511 class C extends B {} |
442 B b; | 512 |
443 y = o; | 513 class Base { |
444 y = i; | 514 B f1; |
445 y = d; | 515 B f2; |
446 y = n; | 516 B f3; |
447 y = a; | 517 B f4; |
448 y = b; | 518 } |
449 } | 519 |
450 '''); | 520 class Child extends Base { |
451 }); | 521 /*severe:INVALID_FIELD_OVERRIDE,severe:INVALID_METHOD_OVERRIDE*/A f1; // inval
id for getter |
452 | 522 /*severe:INVALID_FIELD_OVERRIDE,severe:INVALID_METHOD_OVERRIDE*/C f2; // inval
id for setter |
453 test('dynamic downcasts', () { | 523 /*severe:INVALID_FIELD_OVERRIDE*/var f3; |
454 checkFile(''' | 524 /*severe:INVALID_FIELD_OVERRIDE,severe:INVALID_METHOD_OVERRIDE,severe:INVALID_
METHOD_OVERRIDE*/dynamic f4; |
455 | 525 } |
456 class A {} | 526 |
457 class B extends A {} | 527 class Child2 implements Base { |
458 | 528 /*severe:INVALID_METHOD_OVERRIDE*/A f1; // invalid for getter |
459 void main() { | 529 /*severe:INVALID_METHOD_OVERRIDE*/C f2; // invalid for setter |
460 dynamic y; | 530 var f3; |
461 Object o; | 531 /*severe:INVALID_METHOD_OVERRIDE,severe:INVALID_METHOD_OVERRIDE*/dynamic f4; |
462 int i = 0; | 532 } |
463 double d = 0.0; | 533 '''); |
464 num n; | 534 } |
465 A a; | 535 |
466 B b; | 536 void test_fieldGetterOverride() { |
467 o = y; | 537 checkFile(''' |
468 i = /*info:DYNAMIC_CAST*/y; | 538 class A {} |
469 d = /*info:DYNAMIC_CAST*/y; | 539 class B extends A {} |
470 n = /*info:DYNAMIC_CAST*/y; | 540 class C extends B {} |
471 a = /*info:DYNAMIC_CAST*/y; | 541 |
472 b = /*info:DYNAMIC_CAST*/y; | 542 abstract class Base { |
473 } | 543 B f1; |
474 '''); | 544 B f2; |
475 }); | 545 B f3; |
476 | 546 B f4; |
477 test('assigning a class', () { | 547 } |
478 checkFile(''' | 548 |
479 | 549 class Child extends Base { |
480 class A {} | 550 /*severe:INVALID_FIELD_OVERRIDE,severe:INVALID_METHOD_OVERRIDE*/A get f1 => nu
ll; |
481 class B extends A {} | 551 /*severe:INVALID_FIELD_OVERRIDE*/C get f2 => null; |
482 | 552 /*severe:INVALID_FIELD_OVERRIDE*/get f3 => null; |
483 void main() { | 553 /*severe:INVALID_FIELD_OVERRIDE,severe:INVALID_METHOD_OVERRIDE*/dynamic get f4
=> null; |
484 dynamic y; | 554 } |
485 Object o; | 555 |
486 int i = 0; | 556 class /*warning:NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_FOUR*/Child2 impleme
nts Base { |
487 double d = 0.0; | 557 /*severe:INVALID_METHOD_OVERRIDE*/A get f1 => null; |
488 num n; | 558 C get f2 => null; |
489 A a; | 559 get f3 => null; |
490 B b; | 560 /*severe:INVALID_METHOD_OVERRIDE*/dynamic get f4 => null; |
491 y = a; | 561 } |
492 o = a; | 562 '''); |
493 i = /*warning:INVALID_ASSIGNMENT*/a; | 563 } |
494 d = /*warning:INVALID_ASSIGNMENT*/a; | 564 |
495 n = /*warning:INVALID_ASSIGNMENT*/a; | 565 void test_fieldOverride_fuzzyArrows() { |
496 a = a; | 566 checkFile(''' |
497 b = /*info:DOWN_CAST_IMPLICIT*/a; | 567 typedef void ToVoid<T>(T x); |
498 } | 568 class F { |
499 '''); | 569 final ToVoid<dynamic> f = null; |
500 }); | 570 final ToVoid<int> g = null; |
501 | 571 } |
502 test('assigning a subclass', () { | 572 |
503 checkFile(''' | 573 class G extends F { |
504 | 574 /*severe:INVALID_FIELD_OVERRIDE*/final ToVoid<int> f = null; |
505 class A {} | 575 /*severe:INVALID_FIELD_OVERRIDE, severe:INVALID_METHOD_OVERRIDE*/final ToVoid<
dynamic> g = null; |
506 class B extends A {} | 576 } |
507 class C extends A {} | 577 |
508 | 578 class H implements F { |
509 void main() { | 579 final ToVoid<int> f = null; |
510 dynamic y; | 580 /*severe:INVALID_METHOD_OVERRIDE*/final ToVoid<dynamic> g = null; |
511 Object o; | 581 } |
512 int i = 0; | 582 '''); |
513 double d = 0.0; | 583 } |
514 num n; | 584 |
515 A a; | 585 void test_fieldSetterOverride() { |
516 B b; | 586 checkFile(''' |
517 C c; | 587 class A {} |
518 y = b; | 588 class B extends A {} |
519 o = b; | 589 class C extends B {} |
520 i = /*warning:INVALID_ASSIGNMENT*/b; | 590 |
521 d = /*warning:INVALID_ASSIGNMENT*/b; | 591 class Base { |
522 n = /*warning:INVALID_ASSIGNMENT*/b; | 592 B f1; |
523 a = b; | 593 B f2; |
524 b = b; | 594 B f3; |
525 c = /*warning:INVALID_ASSIGNMENT*/b; | 595 B f4; |
526 } | 596 B f5; |
527 '''); | 597 } |
528 }); | 598 |
529 | 599 class Child extends Base { |
530 test('interfaces', () { | 600 /*severe:INVALID_FIELD_OVERRIDE*/B get f1 => null; |
531 checkFile(''' | 601 /*severe:INVALID_FIELD_OVERRIDE*/B get f2 => null; |
532 | 602 /*severe:INVALID_FIELD_OVERRIDE*/B get f3 => null; |
533 class A {} | 603 /*severe:INVALID_FIELD_OVERRIDE*/B get f4 => null; |
534 class B extends A {} | 604 /*severe:INVALID_FIELD_OVERRIDE*/B get f5 => null; |
535 class C extends A {} | 605 |
536 class D extends B implements C {} | 606 /*severe:INVALID_FIELD_OVERRIDE*/void set f1(A value) {} |
537 | 607 /*severe:INVALID_FIELD_OVERRIDE,severe:INVALID_METHOD_OVERRIDE*/void set f2(C
value) {} |
538 void main() { | 608 /*severe:INVALID_FIELD_OVERRIDE*/void set f3(value) {} |
539 A top; | 609 /*severe:INVALID_FIELD_OVERRIDE,severe:INVALID_METHOD_OVERRIDE*/void set f4(dy
namic value) {} |
540 B left; | 610 /*severe:INVALID_FIELD_OVERRIDE*/set f5(B value) {} |
541 C right; | 611 } |
542 D bot; | 612 |
543 { | 613 class Child2 implements Base { |
544 top = top; | 614 B get f1 => null; |
545 top = left; | 615 B get f2 => null; |
546 top = right; | 616 B get f3 => null; |
547 top = bot; | 617 B get f4 => null; |
548 } | 618 B get f5 => null; |
549 { | 619 |
550 left = /*info:DOWN_CAST_IMPLICIT*/top; | 620 void set f1(A value) {} |
551 left = left; | 621 /*severe:INVALID_METHOD_OVERRIDE*/void set f2(C value) {} |
552 left = /*warning:INVALID_ASSIGNMENT*/right; | 622 void set f3(value) {} |
553 left = bot; | 623 /*severe:INVALID_METHOD_OVERRIDE*/void set f4(dynamic value) {} |
554 } | 624 set f5(B value) {} |
555 { | 625 } |
556 right = /*info:DOWN_CAST_IMPLICIT*/top; | 626 '''); |
557 right = /*warning:INVALID_ASSIGNMENT*/left; | 627 } |
558 right = right; | 628 |
559 right = bot; | 629 void test_forInCastsIterateElementToVariable() { |
560 } | 630 checkFile(''' |
561 { | 631 main() { |
562 bot = /*info:DOWN_CAST_IMPLICIT*/top; | 632 // Don't choke if sequence is not iterable. |
563 bot = /*info:DOWN_CAST_IMPLICIT*/left; | 633 for (var i in /*warning:FOR_IN_OF_INVALID_TYPE*/1234) {} |
564 bot = /*info:DOWN_CAST_IMPLICIT*/right; | 634 |
565 bot = bot; | 635 // Dynamic cast. |
566 } | 636 for (String /*info:DYNAMIC_CAST*/s in <dynamic>[]) {} |
567 } | 637 |
568 '''); | 638 // Identity cast. |
569 }); | 639 for (String s in <String>[]) {} |
570 }); | 640 |
571 | 641 // Untyped. |
572 group('Function typing and subtyping:', () { | 642 for (var s in <String>[]) {} |
573 test('int and object', () { | 643 |
574 checkFile(''' | 644 // Downcast. |
575 | 645 for (int /*info:DOWN_CAST_IMPLICIT*/i in <num>[]) {} |
576 typedef Object Top(int x); // Top of the lattice | 646 } |
577 typedef int Left(int x); // Left branch | 647 '''); |
578 typedef int Left2(int x); // Left branch | 648 } |
579 typedef Object Right(Object x); // Right branch | 649 |
580 typedef int Bot(Object x); // Bottom of the lattice | 650 void test_forInCastsSupertypeSequenceToIterate() { |
581 | 651 checkFile(''' |
582 Object globalTop(int x) => x; | 652 main() { |
583 int globalLeft(int x) => x; | 653 dynamic d; |
584 Object globalRight(Object x) => x; | 654 for (var i in /*info:DYNAMIC_CAST*/d) {} |
585 int bot_(Object x) => /*info:DOWN_CAST_IMPLICIT*/x; | 655 |
586 int globalBot(Object x) => x as int; | 656 Object o; |
587 | 657 for (var i in /*info:DOWN_CAST_IMPLICIT*/o) {} |
588 void main() { | 658 } |
589 // Note: use locals so we only know the type, not that it's a specific | 659 '''); |
590 // function declaration. (we can issue better errors in that case.) | 660 } |
591 var top = globalTop; | 661 |
592 var left = globalLeft; | 662 void test_forLoopVariable() { |
593 var right = globalRight; | 663 checkFile(''' |
594 var bot = globalBot; | 664 foo() { |
595 | 665 for (int i = 0; i < 10; i++) { |
596 { // Check typedef equality | 666 i = /*warning:INVALID_ASSIGNMENT*/"hi"; |
597 Left f = left; | 667 } |
598 Left2 g = f; | 668 } |
599 } | 669 bar() { |
600 { | 670 for (var i = 0; i < 10; i++) { |
601 Top f; | 671 int j = i + 1; |
602 f = top; | 672 } |
603 f = left; | 673 } |
604 f = right; | 674 '''); |
605 f = bot; | 675 } |
606 } | 676 |
607 { | 677 void test_functionModifiers_async() { |
608 Left f; | 678 checkFile(''' |
609 f = /*warning:DOWN_CAST_COMPOSITE*/top; | 679 import 'dart:async'; |
610 f = left; | 680 import 'dart:math' show Random; |
611 f = /*warning:DOWN_CAST_COMPOSITE*/right; // Should we reject this? | 681 |
612 f = bot; | 682 dynamic x; |
613 } | 683 |
614 { | 684 foo1() async => x; |
615 Right f; | 685 Future foo2() async => x; |
616 f = /*warning:DOWN_CAST_COMPOSITE*/top; | 686 Future<int> foo3() async => /*info:DYNAMIC_CAST*/x; |
617 f = /*warning:DOWN_CAST_COMPOSITE*/left; // Should we reject this? | 687 Future<int> foo4() async => new Future<int>.value(/*info:DYNAMIC_CAST*/x); |
618 f = right; | 688 Future<int> foo5() async => |
619 f = bot; | 689 /*warning:RETURN_OF_INVALID_TYPE*/new Future<String>.value(/*info:DYNAMIC_CA
ST*/x); |
620 } | 690 |
621 { | 691 bar1() async { return x; } |
622 Bot f; | 692 Future bar2() async { return x; } |
623 f = /*warning:DOWN_CAST_COMPOSITE*/top; | 693 Future<int> bar3() async { return /*info:DYNAMIC_CAST*/x; } |
624 f = /*warning:DOWN_CAST_COMPOSITE*/left; | 694 Future<int> bar4() async { return new Future<int>.value(/*info:DYNAMIC_CAST*/x);
} |
625 f = /*warning:DOWN_CAST_COMPOSITE*/right; | 695 Future<int> bar5() async { |
626 f = bot; | 696 return /*warning:RETURN_OF_INVALID_TYPE*/new Future<String>.value(/*info:DYNAM
IC_CAST*/x); |
627 } | 697 } |
628 } | 698 |
629 '''); | 699 int y; |
630 }); | 700 Future<int> z; |
631 | 701 |
632 test('classes', () { | 702 baz() async { |
633 checkFile(''' | 703 int a = /*info:DYNAMIC_CAST*/await x; |
634 | 704 int b = await y; |
635 class A {} | 705 int c = await z; |
636 class B extends A {} | 706 String d = /*warning:INVALID_ASSIGNMENT*/await z; |
637 | 707 } |
638 typedef A Top(B x); // Top of the lattice | 708 |
639 typedef B Left(B x); // Left branch | 709 Future<bool> get issue_264 async { |
640 typedef B Left2(B x); // Left branch | 710 await 42; |
641 typedef A Right(A x); // Right branch | 711 if (new Random().nextBool()) { |
642 typedef B Bot(A x); // Bottom of the lattice | 712 return true; |
643 | 713 } else { |
644 B left(B x) => x; | 714 return new Future<bool>.value(false); |
645 B bot_(A x) => /*info:DOWN_CAST_IMPLICIT*/x; | 715 } |
646 B bot(A x) => x as B; | 716 } |
647 A top(B x) => x; | 717 '''); |
648 A right(A x) => x; | 718 } |
649 | 719 |
650 void main() { | 720 void test_functionModifiers_asyncStar() { |
651 { // Check typedef equality | 721 checkFile(''' |
652 Left f = left; | 722 import 'dart:async'; |
653 Left2 g = f; | 723 |
654 } | 724 dynamic x; |
655 { | 725 |
656 Top f; | 726 bar1() async* { yield x; } |
657 f = top; | 727 Stream bar2() async* { yield x; } |
658 f = left; | 728 Stream<int> bar3() async* { yield /*info:DYNAMIC_CAST*/x; } |
659 f = right; | 729 Stream<int> bar4() async* { yield /*warning:YIELD_OF_INVALID_TYPE*/new Stream<in
t>(); } |
660 f = bot; | 730 |
661 } | 731 baz1() async* { yield* /*info:DYNAMIC_CAST*/x; } |
662 { | 732 Stream baz2() async* { yield* /*info:DYNAMIC_CAST*/x; } |
663 Left f; | 733 Stream<int> baz3() async* { yield* /*warning:DOWN_CAST_COMPOSITE*/x; } |
664 f = /*severe:STATIC_TYPE_ERROR*/top; | 734 Stream<int> baz4() async* { yield* new Stream<int>(); } |
665 f = left; | 735 Stream<int> baz5() async* { yield* /*info:INFERRED_TYPE_ALLOCATION*/new Stream()
; } |
666 f = /*severe:STATIC_TYPE_ERROR*/right; | 736 '''); |
667 f = bot; | 737 } |
668 } | 738 |
669 { | 739 void test_functionModifiers_syncStar() { |
670 Right f; | 740 checkFile(''' |
671 f = /*severe:STATIC_TYPE_ERROR*/top; | 741 dynamic x; |
672 f = /*severe:STATIC_TYPE_ERROR*/left; | 742 |
673 f = right; | 743 bar1() sync* { yield x; } |
674 f = bot; | 744 Iterable bar2() sync* { yield x; } |
675 } | 745 Iterable<int> bar3() sync* { yield /*info:DYNAMIC_CAST*/x; } |
676 { | 746 Iterable<int> bar4() sync* { yield /*warning:YIELD_OF_INVALID_TYPE*/bar3(); } |
677 Bot f; | 747 |
678 f = /*severe:STATIC_TYPE_ERROR*/top; | 748 baz1() sync* { yield* /*info:DYNAMIC_CAST*/x; } |
679 f = /*severe:STATIC_TYPE_ERROR*/left; | 749 Iterable baz2() sync* { yield* /*info:DYNAMIC_CAST*/x; } |
680 f = /*severe:STATIC_TYPE_ERROR*/right; | 750 Iterable<int> baz3() sync* { yield* /*warning:DOWN_CAST_COMPOSITE*/x; } |
681 f = bot; | 751 Iterable<int> baz4() sync* { yield* bar3(); } |
682 } | 752 Iterable<int> baz5() sync* { yield* /*info:INFERRED_TYPE_ALLOCATION*/new List();
} |
683 } | 753 '''); |
684 '''); | 754 } |
685 }); | 755 |
686 | 756 void test_functionTypingAndSubtyping_classes() { |
687 test('dynamic', () { | 757 checkFile(''' |
688 checkFile(''' | 758 class A {} |
689 | 759 class B extends A {} |
690 class A {} | 760 |
691 | 761 typedef A Top(B x); // Top of the lattice |
692 typedef dynamic Top(dynamic x); // Top of the lattice | 762 typedef B Left(B x); // Left branch |
693 typedef dynamic Left(A x); // Left branch | 763 typedef B Left2(B x); // Left branch |
694 typedef A Right(dynamic x); // Right branch | 764 typedef A Right(A x); // Right branch |
695 typedef A Bottom(A x); // Bottom of the lattice | 765 typedef B Bot(A x); // Bottom of the lattice |
696 | 766 |
697 void main() { | 767 B left(B x) => x; |
698 Top top; | 768 B bot_(A x) => /*info:DOWN_CAST_IMPLICIT*/x; |
699 Left left; | 769 B bot(A x) => x as B; |
700 Right right; | 770 A top(B x) => x; |
701 Bottom bot; | 771 A right(A x) => x; |
702 { | 772 |
703 Top f; | 773 void main() { |
704 f = top; | 774 { // Check typedef equality |
705 f = left; | 775 Left f = left; |
706 f = right; | 776 Left2 g = f; |
707 f = bot; | 777 } |
708 } | 778 { |
709 { | 779 Top f; |
710 Left f; | 780 f = top; |
711 f = /*warning:DOWN_CAST_COMPOSITE*/top; | 781 f = left; |
712 f = left; | 782 f = right; |
713 f = /*warning:DOWN_CAST_COMPOSITE*/right; | 783 f = bot; |
714 f = bot; | 784 } |
715 } | 785 { |
716 { | 786 Left f; |
717 Right f; | 787 f = /*severe:STATIC_TYPE_ERROR*/top; |
718 f = /*warning:DOWN_CAST_COMPOSITE*/top; | 788 f = left; |
719 f = /*warning:DOWN_CAST_COMPOSITE*/left; | 789 f = /*severe:STATIC_TYPE_ERROR*/right; |
720 f = right; | 790 f = bot; |
721 f = bot; | 791 } |
722 } | 792 { |
723 { | 793 Right f; |
724 Bottom f; | 794 f = /*severe:STATIC_TYPE_ERROR*/top; |
725 f = /*warning:DOWN_CAST_COMPOSITE*/top; | 795 f = /*severe:STATIC_TYPE_ERROR*/left; |
726 f = /*warning:DOWN_CAST_COMPOSITE*/left; | 796 f = right; |
727 f = /*warning:DOWN_CAST_COMPOSITE*/right; | 797 f = bot; |
728 f = bot; | 798 } |
729 } | 799 { |
730 } | 800 Bot f; |
731 '''); | 801 f = /*severe:STATIC_TYPE_ERROR*/top; |
732 }); | 802 f = /*severe:STATIC_TYPE_ERROR*/left; |
733 | 803 f = /*severe:STATIC_TYPE_ERROR*/right; |
734 test('dynamic functions - closures are not fuzzy', () { | 804 f = bot; |
735 // Regression test for | 805 } |
736 // https://github.com/dart-lang/sdk/issues/26118 | 806 } |
737 // https://github.com/dart-lang/sdk/issues/26156 | 807 '''); |
738 checkFile(''' | 808 } |
739 void takesF(void f(int x)) {} | 809 |
740 | 810 void test_functionTypingAndSubtyping_dynamic() { |
741 typedef void TakesInt(int x); | 811 checkFile(''' |
742 | 812 class A {} |
743 void update(_) {} | 813 |
744 void updateOpt([_]) {} | 814 typedef dynamic Top(dynamic x); // Top of the lattice |
745 void updateOptNum([num x]) {} | 815 typedef dynamic Left(A x); // Left branch |
746 | 816 typedef A Right(dynamic x); // Right branch |
747 class A { | 817 typedef A Bottom(A x); // Bottom of the lattice |
748 TakesInt f; | 818 |
749 A(TakesInt g) { | 819 void main() { |
750 f = update; | 820 Top top; |
751 f = updateOpt; | 821 Left left; |
752 f = updateOptNum; | 822 Right right; |
753 } | 823 Bottom bot; |
754 TakesInt g(bool a, bool b) { | 824 { |
755 if (a) { | 825 Top f; |
756 return update; | 826 f = top; |
757 } else if (b) { | 827 f = left; |
758 return updateOpt; | 828 f = right; |
759 } else { | 829 f = bot; |
760 return updateOptNum; | 830 } |
761 } | 831 { |
762 } | 832 Left f; |
763 } | 833 f = /*warning:DOWN_CAST_COMPOSITE*/top; |
764 | 834 f = left; |
765 void test0() { | 835 f = /*warning:DOWN_CAST_COMPOSITE*/right; |
766 takesF(update); | 836 f = bot; |
767 takesF(updateOpt); | 837 } |
768 takesF(updateOptNum); | 838 { |
769 TakesInt f; | 839 Right f; |
770 f = update; | 840 f = /*warning:DOWN_CAST_COMPOSITE*/top; |
771 f = updateOpt; | 841 f = /*warning:DOWN_CAST_COMPOSITE*/left; |
772 f = updateOptNum; | 842 f = right; |
773 new A(update); | 843 f = bot; |
774 new A(updateOpt); | 844 } |
775 new A(updateOptNum); | 845 { |
776 } | 846 Bottom f; |
777 | 847 f = /*warning:DOWN_CAST_COMPOSITE*/top; |
778 void test1() { | 848 f = /*warning:DOWN_CAST_COMPOSITE*/left; |
779 void takesF(f(int x)) => null; | 849 f = /*warning:DOWN_CAST_COMPOSITE*/right; |
780 takesF((dynamic y) => 3); | 850 f = bot; |
781 } | 851 } |
782 | 852 } |
783 void test2() { | 853 '''); |
784 int x; | 854 } |
785 int f/*<T>*/(/*=T*/ t, callback(/*=T*/ x)) { return 3; } | 855 |
786 f(x, (y) => 3); | 856 void test_functionTypingAndSubtyping_dynamic_knownFunctions() { |
787 } | 857 // Our lattice should look like this: |
788 '''); | 858 // |
789 }); | 859 // |
790 | 860 // Bot -> Top |
791 test('dynamic - known functions', () { | 861 // / \ |
792 // Our lattice should look like this: | 862 // A -> Top Bot -> A |
793 // | 863 // / \ / |
794 // | 864 // Top -> Top A -> A |
795 // Bot -> Top | 865 // \ / |
796 // / \ | 866 // Top -> A |
797 // A -> Top Bot -> A | 867 // |
798 // / \ / | 868 // Note that downcasts of known functions are promoted to |
799 // Top -> Top A -> A | 869 // static type errors, since they cannot succeed. |
800 // \ / | 870 // This makes some of what look like downcasts turn into |
801 // Top -> A | 871 // type errors below. |
802 // | 872 checkFile(''' |
803 // Note that downcasts of known functions are promoted to | 873 class A {} |
804 // static type errors, since they cannot succeed. | 874 |
805 // This makes some of what look like downcasts turn into | 875 typedef dynamic BotTop(dynamic x); |
806 // type errors below. | 876 typedef dynamic ATop(A x); |
807 checkFile(''' | 877 typedef A BotA(dynamic x); |
808 class A {} | 878 typedef A AA(A x); |
809 | 879 typedef A TopA(Object x); |
810 typedef dynamic BotTop(dynamic x); | 880 typedef dynamic TopTop(Object x); |
811 typedef dynamic ATop(A x); | 881 |
812 typedef A BotA(dynamic x); | 882 dynamic aTop(A x) => x; |
813 typedef A AA(A x); | 883 A aa(A x) => x; |
814 typedef A TopA(Object x); | 884 dynamic topTop(dynamic x) => x; |
815 typedef dynamic TopTop(Object x); | 885 A topA(dynamic x) => /*info:DYNAMIC_CAST*/x; |
816 | 886 void apply/*<T>*/(/*=T*/ f0, /*=T*/ f1, /*=T*/ f2, |
817 dynamic aTop(A x) => x; | 887 /*=T*/ f3, /*=T*/ f4, /*=T*/ f5) {} |
818 A aa(A x) => x; | 888 void main() { |
819 dynamic topTop(dynamic x) => x; | 889 BotTop botTop; |
820 A topA(dynamic x) => /*info:DYNAMIC_CAST*/x; | 890 BotA botA; |
821 void apply/*<T>*/(/*=T*/ f0, /*=T*/ f1, /*=T*/ f2, | 891 { |
822 /*=T*/ f3, /*=T*/ f4, /*=T*/ f5) {} | 892 BotTop f; |
823 void main() { | 893 f = topA; |
824 BotTop botTop; | 894 f = topTop; |
825 BotA botA; | 895 f = aa; |
826 { | 896 f = aTop; |
827 BotTop f; | 897 f = botA; |
828 f = topA; | 898 f = botTop; |
829 f = topTop; | 899 apply/*<BotTop>*/( |
830 f = aa; | 900 topA, |
831 f = aTop; | 901 topTop, |
832 f = botA; | 902 aa, |
833 f = botTop; | 903 aTop, |
834 apply/*<BotTop>*/( | 904 botA, |
835 topA, | 905 botTop |
836 topTop, | 906 ); |
837 aa, | 907 apply/*<BotTop>*/( |
838 aTop, | 908 (dynamic x) => new A(), |
839 botA, | 909 (dynamic x) => (x as Object), |
840 botTop | 910 (A x) => x, |
841 ); | 911 (A x) => null, |
842 apply/*<BotTop>*/( | 912 botA, |
843 (dynamic x) => new A(), | 913 botTop |
844 (dynamic x) => (x as Object), | 914 ); |
845 (A x) => x, | 915 } |
846 (A x) => null, | 916 { |
847 botA, | 917 ATop f; |
848 botTop | 918 f = topA; |
849 ); | 919 f = topTop; |
850 } | 920 f = aa; |
851 { | 921 f = aTop; |
852 ATop f; | 922 f = /*warning:DOWN_CAST_COMPOSITE should be severe:STATIC_TYPE_ERROR*/botA; |
853 f = topA; | 923 f = /*warning:DOWN_CAST_COMPOSITE*/botTop; |
854 f = topTop; | 924 apply/*<ATop>*/( |
855 f = aa; | 925 topA, |
856 f = aTop; | 926 topTop, |
857 f = /*warning:DOWN_CAST_COMPOSITE should be severe:STATIC_TYPE_ERROR
*/botA; | 927 aa, |
858 f = /*warning:DOWN_CAST_COMPOSITE*/botTop; | 928 aTop, |
859 apply/*<ATop>*/( | 929 /*warning:DOWN_CAST_COMPOSITE should be severe:STATIC_TYPE_ERROR*/botA, |
860 topA, | 930 /*warning:DOWN_CAST_COMPOSITE*/botTop |
861 topTop, | 931 ); |
862 aa, | 932 apply/*<ATop>*/( |
863 aTop, | 933 (dynamic x) => new A(), |
864 /*warning:DOWN_CAST_COMPOSITE should be severe:STATIC_TYPE_ERROR
*/botA, | 934 (dynamic x) => (x as Object), |
865 /*warning:DOWN_CAST_COMPOSITE*/botTop | 935 (A x) => x, |
866 ); | 936 (A x) => null, |
867 apply/*<ATop>*/( | 937 /*warning:DOWN_CAST_COMPOSITE should be severe:STATIC_TYPE_ERROR*/botA, |
868 (dynamic x) => new A(), | 938 /*warning:DOWN_CAST_COMPOSITE*/botTop |
869 (dynamic x) => (x as Object), | 939 ); |
870 (A x) => x, | 940 } |
871 (A x) => null, | 941 { |
872 /*warning:DOWN_CAST_COMPOSITE should be severe:STATIC_TYPE_ERROR
*/botA, | 942 BotA f; |
873 /*warning:DOWN_CAST_COMPOSITE*/botTop | 943 f = topA; |
874 ); | 944 f = /*severe:STATIC_TYPE_ERROR*/topTop; |
875 } | 945 f = aa; |
876 { | 946 f = /*severe:STATIC_TYPE_ERROR*/aTop; |
877 BotA f; | 947 f = botA; |
878 f = topA; | 948 f = /*warning:DOWN_CAST_COMPOSITE*/botTop; |
879 f = /*severe:STATIC_TYPE_ERROR*/topTop; | 949 apply/*<BotA>*/( |
880 f = aa; | 950 topA, |
881 f = /*severe:STATIC_TYPE_ERROR*/aTop; | 951 /*severe:STATIC_TYPE_ERROR*/topTop, |
882 f = botA; | 952 aa, |
883 f = /*warning:DOWN_CAST_COMPOSITE*/botTop; | 953 /*severe:STATIC_TYPE_ERROR*/aTop, |
884 apply/*<BotA>*/( | 954 botA, |
885 topA, | 955 /*warning:DOWN_CAST_COMPOSITE*/botTop |
886 /*severe:STATIC_TYPE_ERROR*/topTop, | 956 ); |
887 aa, | 957 apply/*<BotA>*/( |
888 /*severe:STATIC_TYPE_ERROR*/aTop, | 958 (dynamic x) => new A(), |
889 botA, | 959 /*severe:STATIC_TYPE_ERROR*/(dynamic x) => (x as Object), |
890 /*warning:DOWN_CAST_COMPOSITE*/botTop | 960 (A x) => x, |
891 ); | 961 /*severe:STATIC_TYPE_ERROR*/(A x) => (x as Object), |
892 apply/*<BotA>*/( | 962 botA, |
893 (dynamic x) => new A(), | 963 /*warning:DOWN_CAST_COMPOSITE*/botTop |
894 /*severe:STATIC_TYPE_ERROR*/(dynamic x) => (x as Object), | 964 ); |
895 (A x) => x, | 965 } |
896 /*severe:STATIC_TYPE_ERROR*/(A x) => (x as Object), | 966 { |
897 botA, | 967 AA f; |
898 /*warning:DOWN_CAST_COMPOSITE*/botTop | 968 f = topA; |
899 ); | 969 f = /*severe:STATIC_TYPE_ERROR*/topTop; |
900 } | 970 f = aa; |
901 { | 971 f = /*severe:STATIC_TYPE_ERROR*/aTop; // known function |
902 AA f; | 972 f = /*warning:DOWN_CAST_COMPOSITE*/botA; |
903 f = topA; | 973 f = /*warning:DOWN_CAST_COMPOSITE*/botTop; |
904 f = /*severe:STATIC_TYPE_ERROR*/topTop; | 974 apply/*<AA>*/( |
905 f = aa; | 975 topA, |
906 f = /*severe:STATIC_TYPE_ERROR*/aTop; // known function | 976 /*severe:STATIC_TYPE_ERROR*/topTop, |
907 f = /*warning:DOWN_CAST_COMPOSITE*/botA; | 977 aa, |
908 f = /*warning:DOWN_CAST_COMPOSITE*/botTop; | 978 /*severe:STATIC_TYPE_ERROR*/aTop, // known function |
909 apply/*<AA>*/( | 979 /*warning:DOWN_CAST_COMPOSITE*/botA, |
910 topA, | 980 /*warning:DOWN_CAST_COMPOSITE*/botTop |
911 /*severe:STATIC_TYPE_ERROR*/topTop, | 981 ); |
912 aa, | 982 apply/*<AA>*/( |
913 /*severe:STATIC_TYPE_ERROR*/aTop, // known function | 983 (dynamic x) => new A(), |
914 /*warning:DOWN_CAST_COMPOSITE*/botA, | 984 /*severe:STATIC_TYPE_ERROR*/(dynamic x) => (x as Object), |
915 /*warning:DOWN_CAST_COMPOSITE*/botTop | 985 (A x) => x, |
916 ); | 986 /*severe:STATIC_TYPE_ERROR*/(A x) => (x as Object), // known function |
917 apply/*<AA>*/( | 987 /*warning:DOWN_CAST_COMPOSITE*/botA, |
918 (dynamic x) => new A(), | 988 /*warning:DOWN_CAST_COMPOSITE*/botTop |
919 /*severe:STATIC_TYPE_ERROR*/(dynamic x) => (x as Object), | 989 ); |
920 (A x) => x, | 990 } |
921 /*severe:STATIC_TYPE_ERROR*/(A x) => (x as Object), // known fun
ction | 991 { |
922 /*warning:DOWN_CAST_COMPOSITE*/botA, | 992 TopTop f; |
923 /*warning:DOWN_CAST_COMPOSITE*/botTop | 993 f = topA; |
924 ); | 994 f = topTop; |
925 } | 995 f = /*severe:STATIC_TYPE_ERROR*/aa; |
926 { | 996 f = /*severe:STATIC_TYPE_ERROR*/aTop; // known function |
927 TopTop f; | 997 f = /*warning:DOWN_CAST_COMPOSITE should be severe:STATIC_TYPE_ERROR*/botA; |
928 f = topA; | 998 f = /*warning:DOWN_CAST_COMPOSITE*/botTop; |
929 f = topTop; | 999 apply/*<TopTop>*/( |
930 f = /*severe:STATIC_TYPE_ERROR*/aa; | 1000 topA, |
931 f = /*severe:STATIC_TYPE_ERROR*/aTop; // known function | 1001 topTop, |
932 f = /*warning:DOWN_CAST_COMPOSITE should be severe:STATIC_TYPE_ERROR
*/botA; | 1002 /*severe:STATIC_TYPE_ERROR*/aa, |
933 f = /*warning:DOWN_CAST_COMPOSITE*/botTop; | 1003 /*severe:STATIC_TYPE_ERROR*/aTop, // known function |
934 apply/*<TopTop>*/( | 1004 /*warning:DOWN_CAST_COMPOSITE should be severe:STATIC_TYPE_ERROR*/botA, |
935 topA, | 1005 /*warning:DOWN_CAST_COMPOSITE*/botTop |
936 topTop, | 1006 ); |
937 /*severe:STATIC_TYPE_ERROR*/aa, | 1007 apply/*<TopTop>*/( |
938 /*severe:STATIC_TYPE_ERROR*/aTop, // known function | 1008 (dynamic x) => new A(), |
939 /*warning:DOWN_CAST_COMPOSITE should be severe:STATIC_TYPE_ERROR
*/botA, | 1009 (dynamic x) => (x as Object), |
940 /*warning:DOWN_CAST_COMPOSITE*/botTop | 1010 /*severe:STATIC_TYPE_ERROR*/(A x) => x, |
941 ); | 1011 /*severe:STATIC_TYPE_ERROR*/(A x) => (x as Object), // known function |
942 apply/*<TopTop>*/( | 1012 /*warning:DOWN_CAST_COMPOSITE should be severe:STATIC_TYPE_ERROR*/botA, |
943 (dynamic x) => new A(), | 1013 /*warning:DOWN_CAST_COMPOSITE*/botTop |
944 (dynamic x) => (x as Object), | 1014 ); |
945 /*severe:STATIC_TYPE_ERROR*/(A x) => x, | 1015 } |
946 /*severe:STATIC_TYPE_ERROR*/(A x) => (x as Object), // known fun
ction | 1016 { |
947 /*warning:DOWN_CAST_COMPOSITE should be severe:STATIC_TYPE_ERROR
*/botA, | 1017 TopA f; |
948 /*warning:DOWN_CAST_COMPOSITE*/botTop | 1018 f = topA; |
949 ); | 1019 f = /*severe:STATIC_TYPE_ERROR*/topTop; // known function |
950 } | 1020 f = /*severe:STATIC_TYPE_ERROR*/aa; // known function |
951 { | 1021 f = /*severe:STATIC_TYPE_ERROR*/aTop; // known function |
952 TopA f; | 1022 f = /*warning:DOWN_CAST_COMPOSITE*/botA; |
953 f = topA; | 1023 f = /*warning:DOWN_CAST_COMPOSITE*/botTop; |
954 f = /*severe:STATIC_TYPE_ERROR*/topTop; // known function | 1024 apply/*<TopA>*/( |
955 f = /*severe:STATIC_TYPE_ERROR*/aa; // known function | 1025 topA, |
956 f = /*severe:STATIC_TYPE_ERROR*/aTop; // known function | 1026 /*severe:STATIC_TYPE_ERROR*/topTop, // known function |
957 f = /*warning:DOWN_CAST_COMPOSITE*/botA; | 1027 /*severe:STATIC_TYPE_ERROR*/aa, // known function |
958 f = /*warning:DOWN_CAST_COMPOSITE*/botTop; | 1028 /*severe:STATIC_TYPE_ERROR*/aTop, // known function |
959 apply/*<TopA>*/( | 1029 /*warning:DOWN_CAST_COMPOSITE*/botA, |
960 topA, | 1030 /*warning:DOWN_CAST_COMPOSITE*/botTop |
961 /*severe:STATIC_TYPE_ERROR*/topTop, // known function | 1031 ); |
962 /*severe:STATIC_TYPE_ERROR*/aa, // known function | 1032 apply/*<TopA>*/( |
963 /*severe:STATIC_TYPE_ERROR*/aTop, // known function | 1033 (dynamic x) => new A(), |
964 /*warning:DOWN_CAST_COMPOSITE*/botA, | 1034 /*severe:STATIC_TYPE_ERROR*/(dynamic x) => (x as Object), // known funct
ion |
965 /*warning:DOWN_CAST_COMPOSITE*/botTop | 1035 /*severe:STATIC_TYPE_ERROR*/(A x) => x, // known function |
966 ); | 1036 /*severe:STATIC_TYPE_ERROR*/(A x) => (x as Object), // known function |
967 apply/*<TopA>*/( | 1037 /*warning:DOWN_CAST_COMPOSITE*/botA, |
968 (dynamic x) => new A(), | 1038 /*warning:DOWN_CAST_COMPOSITE*/botTop |
969 /*severe:STATIC_TYPE_ERROR*/(dynamic x) => (x as Object), // kno
wn function | 1039 ); |
970 /*severe:STATIC_TYPE_ERROR*/(A x) => x, // known function | 1040 } |
971 /*severe:STATIC_TYPE_ERROR*/(A x) => (x as Object), // known fun
ction | 1041 } |
972 /*warning:DOWN_CAST_COMPOSITE*/botA, | 1042 '''); |
973 /*warning:DOWN_CAST_COMPOSITE*/botTop | 1043 } |
974 ); | 1044 |
975 } | 1045 void test_functionTypingAndSubtyping_dynamicFunctions_clasuresAreNotFuzzy() { |
976 } | 1046 // Regression test for |
977 '''); | 1047 // https://github.com/dart-lang/sdk/issues/26118 |
978 }); | 1048 // https://github.com/dart-lang/sdk/issues/26156 |
979 | 1049 checkFile(''' |
980 test('function literal variance', () { | 1050 void takesF(void f(int x)) {} |
981 checkFile(''' | 1051 |
982 | 1052 typedef void TakesInt(int x); |
983 class A {} | 1053 |
984 class B extends A {} | 1054 void update(_) {} |
985 | 1055 void updateOpt([_]) {} |
986 typedef T Function2<S, T>(S z); | 1056 void updateOptNum([num x]) {} |
987 | 1057 |
988 A top(B x) => x; | 1058 class A { |
989 B left(B x) => x; | 1059 TakesInt f; |
990 A right(A x) => x; | 1060 A(TakesInt g) { |
991 B bot(A x) => x as B; | 1061 f = update; |
992 | 1062 f = updateOpt; |
993 void main() { | 1063 f = updateOptNum; |
994 { | 1064 } |
995 Function2<B, A> f; | 1065 TakesInt g(bool a, bool b) { |
996 f = top; | 1066 if (a) { |
997 f = left; | 1067 return update; |
998 f = right; | 1068 } else if (b) { |
999 f = bot; | 1069 return updateOpt; |
1000 } | 1070 } else { |
1001 { | 1071 return updateOptNum; |
1002 Function2<B, B> f; | |
1003 f = /*severe:STATIC_TYPE_ERROR*/top; | |
1004 f = left; | |
1005 f = /*severe:STATIC_TYPE_ERROR*/right; | |
1006 f = bot; | |
1007 } | |
1008 { | |
1009 Function2<A, A> f; | |
1010 f = /*severe:STATIC_TYPE_ERROR*/top; | |
1011 f = /*severe:STATIC_TYPE_ERROR*/left; | |
1012 f = right; | |
1013 f = bot; | |
1014 } | |
1015 { | |
1016 Function2<A, B> f; | |
1017 f = /*severe:STATIC_TYPE_ERROR*/top; | |
1018 f = /*severe:STATIC_TYPE_ERROR*/left; | |
1019 f = /*severe:STATIC_TYPE_ERROR*/right; | |
1020 f = bot; | |
1021 } | |
1022 } | |
1023 '''); | |
1024 }); | |
1025 | |
1026 test('function variable variance', () { | |
1027 checkFile(''' | |
1028 | |
1029 class A {} | |
1030 class B extends A {} | |
1031 | |
1032 typedef T Function2<S, T>(S z); | |
1033 | |
1034 void main() { | |
1035 { | |
1036 Function2<B, A> top; | |
1037 Function2<B, B> left; | |
1038 Function2<A, A> right; | |
1039 Function2<A, B> bot; | |
1040 | |
1041 top = right; | |
1042 top = bot; | |
1043 top = top; | |
1044 top = left; | |
1045 | |
1046 left = /*warning:DOWN_CAST_COMPOSITE*/top; | |
1047 left = left; | |
1048 left = /*warning:DOWN_CAST_COMPOSITE*/right; // Should we reject this? | |
1049 left = bot; | |
1050 | |
1051 right = /*warning:DOWN_CAST_COMPOSITE*/top; | |
1052 right = /*warning:DOWN_CAST_COMPOSITE*/left; // Should we reject this? | |
1053 right = right; | |
1054 right = bot; | |
1055 | |
1056 bot = /*warning:DOWN_CAST_COMPOSITE*/top; | |
1057 bot = /*warning:DOWN_CAST_COMPOSITE*/left; | |
1058 bot = /*warning:DOWN_CAST_COMPOSITE*/right; | |
1059 bot = bot; | |
1060 } | |
1061 } | |
1062 '''); | |
1063 }); | |
1064 | |
1065 test('static method variance', () { | |
1066 checkFile(''' | |
1067 | |
1068 class A {} | |
1069 class B extends A {} | |
1070 | |
1071 class C { | |
1072 static A top(B x) => x; | |
1073 static B left(B x) => x; | |
1074 static A right(A x) => x; | |
1075 static B bot(A x) => x as B; | |
1076 } | |
1077 | |
1078 typedef T Function2<S, T>(S z); | |
1079 | |
1080 void main() { | |
1081 { | |
1082 Function2<B, A> f; | |
1083 f = C.top; | |
1084 f = C.left; | |
1085 f = C.right; | |
1086 f = C.bot; | |
1087 } | |
1088 { | |
1089 Function2<B, B> f; | |
1090 f = /*severe:STATIC_TYPE_ERROR*/C.top; | |
1091 f = C.left; | |
1092 f = /*severe:STATIC_TYPE_ERROR*/C.right; | |
1093 f = C.bot; | |
1094 } | |
1095 { | |
1096 Function2<A, A> f; | |
1097 f = /*severe:STATIC_TYPE_ERROR*/C.top; | |
1098 f = /*severe:STATIC_TYPE_ERROR*/C.left; | |
1099 f = C.right; | |
1100 f = C.bot; | |
1101 } | |
1102 { | |
1103 Function2<A, B> f; | |
1104 f = /*severe:STATIC_TYPE_ERROR*/C.top; | |
1105 f = /*severe:STATIC_TYPE_ERROR*/C.left; | |
1106 f = /*severe:STATIC_TYPE_ERROR*/C.right; | |
1107 f = C.bot; | |
1108 } | |
1109 } | |
1110 '''); | |
1111 }); | |
1112 | |
1113 test('instance method variance', () { | |
1114 checkFile(''' | |
1115 | |
1116 class A {} | |
1117 class B extends A {} | |
1118 | |
1119 class C { | |
1120 A top(B x) => x; | |
1121 B left(B x) => x; | |
1122 A right(A x) => x; | |
1123 B bot(A x) => x as B; | |
1124 } | |
1125 | |
1126 typedef T Function2<S, T>(S z); | |
1127 | |
1128 void main() { | |
1129 C c = new C(); | |
1130 { | |
1131 Function2<B, A> f; | |
1132 f = c.top; | |
1133 f = c.left; | |
1134 f = c.right; | |
1135 f = c.bot; | |
1136 } | |
1137 { | |
1138 Function2<B, B> f; | |
1139 f = /*warning:DOWN_CAST_COMPOSITE*/c.top; | |
1140 f = c.left; | |
1141 f = /*warning:DOWN_CAST_COMPOSITE*/c.right; | |
1142 f = c.bot; | |
1143 } | |
1144 { | |
1145 Function2<A, A> f; | |
1146 f = /*warning:DOWN_CAST_COMPOSITE*/c.top; | |
1147 f = /*warning:DOWN_CAST_COMPOSITE*/c.left; | |
1148 f = c.right; | |
1149 f = c.bot; | |
1150 } | |
1151 { | |
1152 Function2<A, B> f; | |
1153 f = /*warning:DOWN_CAST_COMPOSITE*/c.top; | |
1154 f = /*warning:DOWN_CAST_COMPOSITE*/c.left; | |
1155 f = /*warning:DOWN_CAST_COMPOSITE*/c.right; | |
1156 f = c.bot; | |
1157 } | |
1158 } | |
1159 '''); | |
1160 }); | |
1161 | |
1162 test('higher order function literals 1', () { | |
1163 checkFile(''' | |
1164 | |
1165 class A {} | |
1166 class B extends A {} | |
1167 | |
1168 typedef T Function2<S, T>(S z); | |
1169 | |
1170 typedef A BToA(B x); // Top of the base lattice | |
1171 typedef B AToB(A x); // Bot of the base lattice | |
1172 | |
1173 BToA top(AToB f) => f; | |
1174 AToB left(AToB f) => f; | |
1175 BToA right(BToA f) => f; | |
1176 AToB bot_(BToA f) => /*warning:DOWN_CAST_COMPOSITE*/f; | |
1177 AToB bot(BToA f) => f as AToB; | |
1178 | |
1179 void main() { | |
1180 { | |
1181 Function2<AToB, BToA> f; // Top | |
1182 f = top; | |
1183 f = left; | |
1184 f = right; | |
1185 f = bot; | |
1186 } | |
1187 { | |
1188 Function2<AToB, AToB> f; // Left | |
1189 f = /*severe:STATIC_TYPE_ERROR*/top; | |
1190 f = left; | |
1191 f = /*severe:STATIC_TYPE_ERROR*/right; | |
1192 f = bot; | |
1193 } | |
1194 { | |
1195 Function2<BToA, BToA> f; // Right | |
1196 f = /*severe:STATIC_TYPE_ERROR*/top; | |
1197 f = /*severe:STATIC_TYPE_ERROR*/left; | |
1198 f = right; | |
1199 f = bot; | |
1200 } | |
1201 { | |
1202 Function2<BToA, AToB> f; // Bot | |
1203 f = bot; | |
1204 f = /*severe:STATIC_TYPE_ERROR*/left; | |
1205 f = /*severe:STATIC_TYPE_ERROR*/top; | |
1206 f = /*severe:STATIC_TYPE_ERROR*/left; | |
1207 } | |
1208 } | |
1209 '''); | |
1210 }); | |
1211 | |
1212 test('higher order function literals 2', () { | |
1213 checkFile(''' | |
1214 | |
1215 class A {} | |
1216 class B extends A {} | |
1217 | |
1218 typedef T Function2<S, T>(S z); | |
1219 | |
1220 typedef A BToA(B x); // Top of the base lattice | |
1221 typedef B AToB(A x); // Bot of the base lattice | |
1222 | |
1223 Function2<B, A> top(AToB f) => f; | |
1224 Function2<A, B> left(AToB f) => f; | |
1225 Function2<B, A> right(BToA f) => f; | |
1226 Function2<A, B> bot_(BToA f) => /*warning:DOWN_CAST_COMPOSITE*/f; | |
1227 Function2<A, B> bot(BToA f) => f as Function2<A, B>; | |
1228 | |
1229 void main() { | |
1230 { | |
1231 Function2<AToB, BToA> f; // Top | |
1232 f = top; | |
1233 f = left; | |
1234 f = right; | |
1235 f = bot; | |
1236 } | |
1237 { | |
1238 Function2<AToB, AToB> f; // Left | |
1239 f = /*severe:STATIC_TYPE_ERROR*/top; | |
1240 f = left; | |
1241 f = /*severe:STATIC_TYPE_ERROR*/right; | |
1242 f = bot; | |
1243 } | |
1244 { | |
1245 Function2<BToA, BToA> f; // Right | |
1246 f = /*severe:STATIC_TYPE_ERROR*/top; | |
1247 f = /*severe:STATIC_TYPE_ERROR*/left; | |
1248 f = right; | |
1249 f = bot; | |
1250 } | |
1251 { | |
1252 Function2<BToA, AToB> f; // Bot | |
1253 f = bot; | |
1254 f = /*severe:STATIC_TYPE_ERROR*/left; | |
1255 f = /*severe:STATIC_TYPE_ERROR*/top; | |
1256 f = /*severe:STATIC_TYPE_ERROR*/left; | |
1257 } | |
1258 } | |
1259 '''); | |
1260 }); | |
1261 | |
1262 test('higher order function literals 3', () { | |
1263 checkFile(''' | |
1264 | |
1265 class A {} | |
1266 class B extends A {} | |
1267 | |
1268 typedef T Function2<S, T>(S z); | |
1269 | |
1270 typedef A BToA(B x); // Top of the base lattice | |
1271 typedef B AToB(A x); // Bot of the base lattice | |
1272 | |
1273 BToA top(Function2<A, B> f) => f; | |
1274 AToB left(Function2<A, B> f) => f; | |
1275 BToA right(Function2<B, A> f) => f; | |
1276 AToB bot_(Function2<B, A> f) => /*warning:DOWN_CAST_COMPOSITE*/f; | |
1277 AToB bot(Function2<B, A> f) => f as AToB; | |
1278 | |
1279 void main() { | |
1280 { | |
1281 Function2<AToB, BToA> f; // Top | |
1282 f = top; | |
1283 f = left; | |
1284 f = right; | |
1285 f = bot; | |
1286 } | |
1287 { | |
1288 Function2<AToB, AToB> f; // Left | |
1289 f = /*severe:STATIC_TYPE_ERROR*/top; | |
1290 f = left; | |
1291 f = /*severe:STATIC_TYPE_ERROR*/right; | |
1292 f = bot; | |
1293 } | |
1294 { | |
1295 Function2<BToA, BToA> f; // Right | |
1296 f = /*severe:STATIC_TYPE_ERROR*/top; | |
1297 f = /*severe:STATIC_TYPE_ERROR*/left; | |
1298 f = right; | |
1299 f = bot; | |
1300 } | |
1301 { | |
1302 Function2<BToA, AToB> f; // Bot | |
1303 f = bot; | |
1304 f = /*severe:STATIC_TYPE_ERROR*/left; | |
1305 f = /*severe:STATIC_TYPE_ERROR*/top; | |
1306 f = /*severe:STATIC_TYPE_ERROR*/left; | |
1307 } | |
1308 } | |
1309 '''); | |
1310 }); | |
1311 | |
1312 test('higher order function variables', () { | |
1313 checkFile(''' | |
1314 | |
1315 class A {} | |
1316 class B extends A {} | |
1317 | |
1318 typedef T Function2<S, T>(S z); | |
1319 | |
1320 void main() { | |
1321 { | |
1322 Function2<Function2<A, B>, Function2<B, A>> top; | |
1323 Function2<Function2<B, A>, Function2<B, A>> right; | |
1324 Function2<Function2<A, B>, Function2<A, B>> left; | |
1325 Function2<Function2<B, A>, Function2<A, B>> bot; | |
1326 | |
1327 top = right; | |
1328 top = bot; | |
1329 top = top; | |
1330 top = left; | |
1331 | |
1332 left = /*warning:DOWN_CAST_COMPOSITE*/top; | |
1333 left = left; | |
1334 left = | |
1335 /*warning:DOWN_CAST_COMPOSITE should be severe:STATIC_TYPE_ERROR*/ri
ght; | |
1336 left = bot; | |
1337 | |
1338 right = /*warning:DOWN_CAST_COMPOSITE*/top; | |
1339 right = | |
1340 /*warning:DOWN_CAST_COMPOSITE should be severe:STATIC_TYPE_ERROR*/le
ft; | |
1341 right = right; | |
1342 right = bot; | |
1343 | |
1344 bot = /*warning:DOWN_CAST_COMPOSITE*/top; | |
1345 bot = /*warning:DOWN_CAST_COMPOSITE*/left; | |
1346 bot = /*warning:DOWN_CAST_COMPOSITE*/right; | |
1347 bot = bot; | |
1348 } | |
1349 } | 1072 } |
1350 '''); | 1073 } |
1351 }); | 1074 } |
1352 | 1075 |
1353 test('named and optional parameters', () { | 1076 void test0() { |
1354 checkFile(''' | 1077 takesF(update); |
1355 | 1078 takesF(updateOpt); |
1356 class A {} | 1079 takesF(updateOptNum); |
1357 | 1080 TakesInt f; |
1358 typedef A FR(A x); | 1081 f = update; |
1359 typedef A FO([A x]); | 1082 f = updateOpt; |
1360 typedef A FN({A x}); | 1083 f = updateOptNum; |
1361 typedef A FRR(A x, A y); | 1084 new A(update); |
1362 typedef A FRO(A x, [A y]); | 1085 new A(updateOpt); |
1363 typedef A FRN(A x, {A n}); | 1086 new A(updateOptNum); |
1364 typedef A FOO([A x, A y]); | 1087 } |
1365 typedef A FNN({A x, A y}); | 1088 |
1366 typedef A FNNN({A z, A y, A x}); | 1089 void test1() { |
1367 | 1090 void takesF(f(int x)) => null; |
1368 void main() { | 1091 takesF((dynamic y) => 3); |
1369 FR r; | 1092 } |
1370 FO o; | 1093 |
1371 FN n; | 1094 void test2() { |
1372 FRR rr; | 1095 int x; |
1373 FRO ro; | 1096 int f/*<T>*/(/*=T*/ t, callback(/*=T*/ x)) { return 3; } |
1374 FRN rn; | 1097 f(x, (y) => 3); |
1375 FOO oo; | 1098 } |
1376 FNN nn; | 1099 '''); |
1377 FNNN nnn; | 1100 } |
1378 | 1101 |
1379 r = r; | 1102 void test_functionTypingAndSubtyping_functionLiteralVariance() { |
1380 r = o; | 1103 checkFile(''' |
1381 r = /*warning:INVALID_ASSIGNMENT*/n; | 1104 class A {} |
1382 r = /*warning:INVALID_ASSIGNMENT*/rr; | 1105 class B extends A {} |
1383 r = ro; | 1106 |
1384 r = rn; | 1107 typedef T Function2<S, T>(S z); |
1385 r = oo; | 1108 |
1386 r = /*warning:INVALID_ASSIGNMENT*/nn; | 1109 A top(B x) => x; |
1387 r = /*warning:INVALID_ASSIGNMENT*/nnn; | 1110 B left(B x) => x; |
1388 | 1111 A right(A x) => x; |
1389 o = /*warning:DOWN_CAST_COMPOSITE*/r; | 1112 B bot(A x) => x as B; |
1390 o = o; | 1113 |
1391 o = /*warning:INVALID_ASSIGNMENT*/n; | 1114 void main() { |
1392 o = /*warning:INVALID_ASSIGNMENT*/rr; | 1115 { |
1393 o = /*warning:INVALID_ASSIGNMENT*/ro; | 1116 Function2<B, A> f; |
1394 o = /*warning:INVALID_ASSIGNMENT*/rn; | 1117 f = top; |
1395 o = oo; | 1118 f = left; |
1396 o = /*warning:INVALID_ASSIGNMENT*/nn; | 1119 f = right; |
1397 o = /*warning:INVALID_ASSIGNMENT*/nnn; | 1120 f = bot; |
1398 | 1121 } |
1399 n = /*warning:INVALID_ASSIGNMENT*/r; | 1122 { |
1400 n = /*warning:INVALID_ASSIGNMENT*/o; | 1123 Function2<B, B> f; |
1401 n = n; | 1124 f = /*severe:STATIC_TYPE_ERROR*/top; |
1402 n = /*warning:INVALID_ASSIGNMENT*/rr; | 1125 f = left; |
1403 n = /*warning:INVALID_ASSIGNMENT*/ro; | 1126 f = /*severe:STATIC_TYPE_ERROR*/right; |
1404 n = /*warning:INVALID_ASSIGNMENT*/rn; | 1127 f = bot; |
1405 n = /*warning:INVALID_ASSIGNMENT*/oo; | 1128 } |
1406 n = nn; | 1129 { |
1407 n = nnn; | 1130 Function2<A, A> f; |
1408 | 1131 f = /*severe:STATIC_TYPE_ERROR*/top; |
1409 rr = /*warning:INVALID_ASSIGNMENT*/r; | 1132 f = /*severe:STATIC_TYPE_ERROR*/left; |
1410 rr = /*warning:INVALID_ASSIGNMENT*/o; | 1133 f = right; |
1411 rr = /*warning:INVALID_ASSIGNMENT*/n; | 1134 f = bot; |
1412 rr = rr; | 1135 } |
1413 rr = ro; | 1136 { |
1414 rr = /*warning:INVALID_ASSIGNMENT*/rn; | 1137 Function2<A, B> f; |
1415 rr = oo; | 1138 f = /*severe:STATIC_TYPE_ERROR*/top; |
1416 rr = /*warning:INVALID_ASSIGNMENT*/nn; | 1139 f = /*severe:STATIC_TYPE_ERROR*/left; |
1417 rr = /*warning:INVALID_ASSIGNMENT*/nnn; | 1140 f = /*severe:STATIC_TYPE_ERROR*/right; |
1418 | 1141 f = bot; |
1419 ro = /*warning:DOWN_CAST_COMPOSITE*/r; | 1142 } |
1420 ro = /*warning:INVALID_ASSIGNMENT*/o; | 1143 } |
1421 ro = /*warning:INVALID_ASSIGNMENT*/n; | 1144 '''); |
1422 ro = /*warning:DOWN_CAST_COMPOSITE*/rr; | 1145 } |
1423 ro = ro; | 1146 |
1424 ro = /*warning:INVALID_ASSIGNMENT*/rn; | 1147 void test_functionTypingAndSubtyping_functionVariableVariance() { |
1425 ro = oo; | 1148 checkFile(''' |
1426 ro = /*warning:INVALID_ASSIGNMENT*/nn; | 1149 class A {} |
1427 ro = /*warning:INVALID_ASSIGNMENT*/nnn; | 1150 class B extends A {} |
1428 | 1151 |
1429 rn = /*warning:DOWN_CAST_COMPOSITE*/r; | 1152 typedef T Function2<S, T>(S z); |
1430 rn = /*warning:INVALID_ASSIGNMENT*/o; | 1153 |
1431 rn = /*warning:INVALID_ASSIGNMENT*/n; | 1154 void main() { |
1432 rn = /*warning:INVALID_ASSIGNMENT*/rr; | 1155 { |
1433 rn = /*warning:INVALID_ASSIGNMENT*/ro; | 1156 Function2<B, A> top; |
1434 rn = rn; | 1157 Function2<B, B> left; |
1435 rn = /*warning:INVALID_ASSIGNMENT*/oo; | 1158 Function2<A, A> right; |
1436 rn = /*warning:INVALID_ASSIGNMENT*/nn; | 1159 Function2<A, B> bot; |
1437 rn = /*warning:INVALID_ASSIGNMENT*/nnn; | 1160 |
1438 | 1161 top = right; |
1439 oo = /*warning:DOWN_CAST_COMPOSITE*/r; | 1162 top = bot; |
1440 oo = /*warning:DOWN_CAST_COMPOSITE*/o; | 1163 top = top; |
1441 oo = /*warning:INVALID_ASSIGNMENT*/n; | 1164 top = left; |
1442 oo = /*warning:DOWN_CAST_COMPOSITE*/rr; | 1165 |
1443 oo = /*warning:DOWN_CAST_COMPOSITE*/ro; | 1166 left = /*warning:DOWN_CAST_COMPOSITE*/top; |
1444 oo = /*warning:INVALID_ASSIGNMENT*/rn; | 1167 left = left; |
1445 oo = oo; | 1168 left = /*warning:DOWN_CAST_COMPOSITE*/right; // Should we reject this? |
1446 oo = /*warning:INVALID_ASSIGNMENT*/nn; | 1169 left = bot; |
1447 oo = /*warning:INVALID_ASSIGNMENT*/nnn; | 1170 |
1448 | 1171 right = /*warning:DOWN_CAST_COMPOSITE*/top; |
1449 nn = /*warning:INVALID_ASSIGNMENT*/r; | 1172 right = /*warning:DOWN_CAST_COMPOSITE*/left; // Should we reject this? |
1450 nn = /*warning:INVALID_ASSIGNMENT*/o; | 1173 right = right; |
1451 nn = /*warning:DOWN_CAST_COMPOSITE*/n; | 1174 right = bot; |
1452 nn = /*warning:INVALID_ASSIGNMENT*/rr; | 1175 |
1453 nn = /*warning:INVALID_ASSIGNMENT*/ro; | 1176 bot = /*warning:DOWN_CAST_COMPOSITE*/top; |
1454 nn = /*warning:INVALID_ASSIGNMENT*/rn; | 1177 bot = /*warning:DOWN_CAST_COMPOSITE*/left; |
1455 nn = /*warning:INVALID_ASSIGNMENT*/oo; | 1178 bot = /*warning:DOWN_CAST_COMPOSITE*/right; |
1456 nn = nn; | 1179 bot = bot; |
1457 nn = nnn; | 1180 } |
1458 | 1181 } |
1459 nnn = /*warning:INVALID_ASSIGNMENT*/r; | 1182 '''); |
1460 nnn = /*warning:INVALID_ASSIGNMENT*/o; | 1183 } |
1461 nnn = /*warning:DOWN_CAST_COMPOSITE*/n; | 1184 |
1462 nnn = /*warning:INVALID_ASSIGNMENT*/rr; | 1185 void test_functionTypingAndSubtyping_higherOrderFunctionLiteral1() { |
1463 nnn = /*warning:INVALID_ASSIGNMENT*/ro; | 1186 checkFile(''' |
1464 nnn = /*warning:INVALID_ASSIGNMENT*/rn; | 1187 class A {} |
1465 nnn = /*warning:INVALID_ASSIGNMENT*/oo; | 1188 class B extends A {} |
1466 nnn = /*warning:DOWN_CAST_COMPOSITE*/nn; | 1189 |
1467 nnn = nnn; | 1190 typedef T Function2<S, T>(S z); |
1468 } | 1191 |
1469 '''); | 1192 typedef A BToA(B x); // Top of the base lattice |
1470 }); | 1193 typedef B AToB(A x); // Bot of the base lattice |
1471 | 1194 |
1472 test('Function subtyping: objects with call methods', () { | 1195 BToA top(AToB f) => f; |
1473 checkFile(''' | 1196 AToB left(AToB f) => f; |
1474 | 1197 BToA right(BToA f) => f; |
1475 typedef int I2I(int x); | 1198 AToB bot_(BToA f) => /*warning:DOWN_CAST_COMPOSITE*/f; |
1476 typedef num N2N(num x); | 1199 AToB bot(BToA f) => f as AToB; |
1477 class A { | 1200 |
1478 int call(int x) => x; | 1201 void main() { |
1479 } | 1202 { |
1480 class B { | 1203 Function2<AToB, BToA> f; // Top |
1481 num call(num x) => x; | 1204 f = top; |
1482 } | 1205 f = left; |
1483 int i2i(int x) => x; | 1206 f = right; |
1484 num n2n(num x) => x; | 1207 f = bot; |
1485 void main() { | 1208 } |
1486 { | 1209 { |
1487 I2I f; | 1210 Function2<AToB, AToB> f; // Left |
1488 f = new A(); | 1211 f = /*severe:STATIC_TYPE_ERROR*/top; |
1489 f = /*warning:INVALID_ASSIGNMENT*/new B(); | 1212 f = left; |
1490 f = i2i; | 1213 f = /*severe:STATIC_TYPE_ERROR*/right; |
1491 f = /*severe:STATIC_TYPE_ERROR*/n2n; | 1214 f = bot; |
1492 f = /*warning:DOWN_CAST_COMPOSITE*/i2i as Object; | 1215 } |
1493 f = /*warning:DOWN_CAST_COMPOSITE*/n2n as Function; | 1216 { |
1494 } | 1217 Function2<BToA, BToA> f; // Right |
1495 { | 1218 f = /*severe:STATIC_TYPE_ERROR*/top; |
1496 N2N f; | 1219 f = /*severe:STATIC_TYPE_ERROR*/left; |
1497 f = /*warning:INVALID_ASSIGNMENT*/new A(); | 1220 f = right; |
1498 f = new B(); | 1221 f = bot; |
1499 f = /*severe:STATIC_TYPE_ERROR*/i2i; | 1222 } |
1500 f = n2n; | 1223 { |
1501 f = /*warning:DOWN_CAST_COMPOSITE*/i2i as Object; | 1224 Function2<BToA, AToB> f; // Bot |
1502 f = /*warning:DOWN_CAST_COMPOSITE*/n2n as Function; | 1225 f = bot; |
1503 } | 1226 f = /*severe:STATIC_TYPE_ERROR*/left; |
1504 { | 1227 f = /*severe:STATIC_TYPE_ERROR*/top; |
1505 A f; | 1228 f = /*severe:STATIC_TYPE_ERROR*/left; |
1506 f = new A(); | 1229 } |
1507 f = /*warning:INVALID_ASSIGNMENT*/new B(); | 1230 } |
1508 f = /*warning:INVALID_ASSIGNMENT*/i2i; | 1231 '''); |
1509 f = /*warning:INVALID_ASSIGNMENT*/n2n; | 1232 } |
1510 f = /*info:DOWN_CAST_IMPLICIT*/i2i as Object; | 1233 |
1511 f = /*info:DOWN_CAST_IMPLICIT*/n2n as Function; | 1234 void test_functionTypingAndSubtyping_higherOrderFunctionLiteral2() { |
1512 } | 1235 checkFile(''' |
1513 { | 1236 class A {} |
1514 B f; | 1237 class B extends A {} |
1515 f = /*warning:INVALID_ASSIGNMENT*/new A(); | 1238 |
1516 f = new B(); | 1239 typedef T Function2<S, T>(S z); |
1517 f = /*warning:INVALID_ASSIGNMENT*/i2i; | 1240 |
1518 f = /*warning:INVALID_ASSIGNMENT*/n2n; | 1241 typedef A BToA(B x); // Top of the base lattice |
1519 f = /*info:DOWN_CAST_IMPLICIT*/i2i as Object; | 1242 typedef B AToB(A x); // Bot of the base lattice |
1520 f = /*info:DOWN_CAST_IMPLICIT*/n2n as Function; | 1243 |
1521 } | 1244 Function2<B, A> top(AToB f) => f; |
1522 { | 1245 Function2<A, B> left(AToB f) => f; |
1523 Function f; | 1246 Function2<B, A> right(BToA f) => f; |
1524 f = new A(); | 1247 Function2<A, B> bot_(BToA f) => /*warning:DOWN_CAST_COMPOSITE*/f; |
1525 f = new B(); | 1248 Function2<A, B> bot(BToA f) => f as Function2<A, B>; |
1526 f = i2i; | 1249 |
1527 f = n2n; | 1250 void main() { |
1528 f = /*info:DOWN_CAST_IMPLICIT*/i2i as Object; | 1251 { |
1529 f = (n2n as Function); | 1252 Function2<AToB, BToA> f; // Top |
1530 } | 1253 f = top; |
1531 } | 1254 f = left; |
1532 '''); | 1255 f = right; |
1533 }); | 1256 f = bot; |
1534 | 1257 } |
1535 test('void', () { | 1258 { |
1536 checkFile(''' | 1259 Function2<AToB, AToB> f; // Left |
1537 | 1260 f = /*severe:STATIC_TYPE_ERROR*/top; |
1538 class A { | 1261 f = left; |
1539 void bar() => null; | 1262 f = /*severe:STATIC_TYPE_ERROR*/right; |
1540 void foo() => bar(); // allowed | 1263 f = bot; |
1541 } | 1264 } |
1542 '''); | 1265 { |
1543 }); | 1266 Function2<BToA, BToA> f; // Right |
1544 | 1267 f = /*severe:STATIC_TYPE_ERROR*/top; |
1545 test('uninferred closure', () { | 1268 f = /*severe:STATIC_TYPE_ERROR*/left; |
1546 checkFile(''' | 1269 f = right; |
1547 typedef num Num2Num(num x); | 1270 f = bot; |
1548 void main() { | 1271 } |
1549 Num2Num g = /*info:INFERRED_TYPE_CLOSURE,severe:STATIC_TYPE_ERROR*/(in
t x) { return x; }; | 1272 { |
1550 print(g(42)); | 1273 Function2<BToA, AToB> f; // Bot |
1551 } | 1274 f = bot; |
1552 '''); | 1275 f = /*severe:STATIC_TYPE_ERROR*/left; |
1553 }); | 1276 f = /*severe:STATIC_TYPE_ERROR*/top; |
1554 | 1277 f = /*severe:STATIC_TYPE_ERROR*/left; |
1555 test('subtype of universal type', () { | 1278 } |
1556 checkFile(''' | 1279 } |
1557 void main() { | 1280 '''); |
1558 nonGenericFn(x) => null; | 1281 } |
1559 { | 1282 |
1560 /*=R*/ f/*<P, R>*/(/*=P*/ p) => null; | 1283 void test_functionTypingAndSubtyping_higherOrderFunctionLiteral3() { |
1561 /*=T*/ g/*<S, T>*/(/*=S*/ s) => null; | 1284 checkFile(''' |
1562 | 1285 class A {} |
1563 var local = f; | 1286 class B extends A {} |
1564 local = g; // valid | 1287 |
1565 | 1288 typedef T Function2<S, T>(S z); |
1566 // Non-generic function cannot subtype a generic one. | 1289 |
1567 local = /*warning:INVALID_ASSIGNMENT*/(x) => null; | 1290 typedef A BToA(B x); // Top of the base lattice |
1568 local = /*warning:INVALID_ASSIGNMENT*/nonGenericFn; | 1291 typedef B AToB(A x); // Bot of the base lattice |
1569 } | 1292 |
1570 { | 1293 BToA top(Function2<A, B> f) => f; |
1571 Iterable/*<R>*/ f/*<P, R>*/(List/*<P>*/ p) => null; | 1294 AToB left(Function2<A, B> f) => f; |
1572 List/*<T>*/ g/*<S, T>*/(Iterable/*<S>*/ s) => null; | 1295 BToA right(Function2<B, A> f) => f; |
1573 | 1296 AToB bot_(Function2<B, A> f) => /*warning:DOWN_CAST_COMPOSITE*/f; |
1574 var local = f; | 1297 AToB bot(Function2<B, A> f) => f as AToB; |
1575 local = g; // valid | 1298 |
1576 | 1299 void main() { |
1577 var local2 = g; | 1300 { |
1578 local = local2; | 1301 Function2<AToB, BToA> f; // Top |
1579 local2 = /*severe:STATIC_TYPE_ERROR*/f; | 1302 f = top; |
1580 local2 = /*warning:DOWN_CAST_COMPOSITE*/local; | 1303 f = left; |
1581 | 1304 f = right; |
1582 // Non-generic function cannot subtype a generic one. | 1305 f = bot; |
1583 local = /*warning:INVALID_ASSIGNMENT*/(x) => null; | 1306 } |
1584 local = /*warning:INVALID_ASSIGNMENT*/nonGenericFn; | 1307 { |
1585 } | 1308 Function2<AToB, AToB> f; // Left |
1586 } | 1309 f = /*severe:STATIC_TYPE_ERROR*/top; |
1587 '''); | 1310 f = left; |
1588 }); | 1311 f = /*severe:STATIC_TYPE_ERROR*/right; |
1589 }); | 1312 f = bot; |
1590 | 1313 } |
1591 test('Relaxed casts', () { | 1314 { |
1592 checkFile(''' | 1315 Function2<BToA, BToA> f; // Right |
1593 | 1316 f = /*severe:STATIC_TYPE_ERROR*/top; |
1594 class A {} | 1317 f = /*severe:STATIC_TYPE_ERROR*/left; |
1595 | 1318 f = right; |
1596 class L<T> {} | 1319 f = bot; |
1597 class M<T> extends L<T> {} | 1320 } |
1598 // L<dynamic|Object> | 1321 { |
1599 // / \ | 1322 Function2<BToA, AToB> f; // Bot |
1600 // M<dynamic|Object> L<A> | 1323 f = bot; |
1601 // \ / | 1324 f = /*severe:STATIC_TYPE_ERROR*/left; |
1602 // M<A> | 1325 f = /*severe:STATIC_TYPE_ERROR*/top; |
1603 // In normal Dart, there are additional edges | 1326 f = /*severe:STATIC_TYPE_ERROR*/left; |
1604 // from M<A> to M<dynamic> | 1327 } |
1605 // from L<A> to M<dynamic> | 1328 } |
1606 // from L<A> to L<dynamic> | 1329 '''); |
1607 void main() { | 1330 } |
1608 L lOfDs; | 1331 |
1609 L<Object> lOfOs; | 1332 void test_functionTypingAndSubtyping_higherOrderFunctionVariables() { |
1610 L<A> lOfAs; | 1333 checkFile(''' |
1611 | 1334 class A {} |
1612 M mOfDs; | 1335 class B extends A {} |
1613 M<Object> mOfOs; | 1336 |
1614 M<A> mOfAs; | 1337 typedef T Function2<S, T>(S z); |
1615 | 1338 |
1616 { | 1339 void main() { |
1617 lOfDs = mOfDs; | 1340 { |
1618 lOfDs = mOfOs; | 1341 Function2<Function2<A, B>, Function2<B, A>> top; |
1619 lOfDs = mOfAs; | 1342 Function2<Function2<B, A>, Function2<B, A>> right; |
1620 lOfDs = lOfDs; | 1343 Function2<Function2<A, B>, Function2<A, B>> left; |
1621 lOfDs = lOfOs; | 1344 Function2<Function2<B, A>, Function2<A, B>> bot; |
1622 lOfDs = lOfAs; | 1345 |
1623 lOfDs = new L(); // Reset type propagation. | 1346 top = right; |
1624 } | 1347 top = bot; |
1625 { | 1348 top = top; |
1626 lOfOs = mOfDs; | 1349 top = left; |
1627 lOfOs = mOfOs; | 1350 |
1628 lOfOs = mOfAs; | 1351 left = /*warning:DOWN_CAST_COMPOSITE*/top; |
1629 lOfOs = lOfDs; | 1352 left = left; |
1630 lOfOs = lOfOs; | 1353 left = |
1631 lOfOs = lOfAs; | 1354 /*warning:DOWN_CAST_COMPOSITE should be severe:STATIC_TYPE_ERROR*/right; |
1632 lOfOs = new L<Object>(); // Reset type propagation. | 1355 left = bot; |
1633 } | 1356 |
1634 { | 1357 right = /*warning:DOWN_CAST_COMPOSITE*/top; |
1635 lOfAs = /*warning:DOWN_CAST_COMPOSITE*/mOfDs; | 1358 right = |
1636 lOfAs = /*warning:INVALID_ASSIGNMENT*/mOfOs; | 1359 /*warning:DOWN_CAST_COMPOSITE should be severe:STATIC_TYPE_ERROR*/left; |
1637 lOfAs = mOfAs; | 1360 right = right; |
1638 lOfAs = /*warning:DOWN_CAST_COMPOSITE*/lOfDs; | 1361 right = bot; |
1639 lOfAs = /*info:DOWN_CAST_IMPLICIT*/lOfOs; | 1362 |
1640 lOfAs = lOfAs; | 1363 bot = /*warning:DOWN_CAST_COMPOSITE*/top; |
1641 lOfAs = new L<A>(); // Reset type propagation. | 1364 bot = /*warning:DOWN_CAST_COMPOSITE*/left; |
1642 } | 1365 bot = /*warning:DOWN_CAST_COMPOSITE*/right; |
1643 { | 1366 bot = bot; |
1644 mOfDs = mOfDs; | 1367 } |
1645 mOfDs = mOfOs; | 1368 } |
1646 mOfDs = mOfAs; | 1369 '''); |
1647 mOfDs = /*info:DOWN_CAST_IMPLICIT*/lOfDs; | 1370 } |
1648 mOfDs = /*info:DOWN_CAST_IMPLICIT*/lOfOs; | 1371 |
1649 mOfDs = /*warning:DOWN_CAST_COMPOSITE*/lOfAs; | 1372 void test_functionTypingAndSubtyping_instanceMethodVariance() { |
1650 mOfDs = new M(); // Reset type propagation. | 1373 checkFile(''' |
1651 } | 1374 class A {} |
1652 { | 1375 class B extends A {} |
1653 mOfOs = mOfDs; | 1376 |
1654 mOfOs = mOfOs; | 1377 class C { |
1655 mOfOs = mOfAs; | 1378 A top(B x) => x; |
1656 mOfOs = /*info:DOWN_CAST_IMPLICIT*/lOfDs; | 1379 B left(B x) => x; |
1657 mOfOs = /*info:DOWN_CAST_IMPLICIT*/lOfOs; | 1380 A right(A x) => x; |
1658 mOfOs = /*warning:INVALID_ASSIGNMENT*/lOfAs; | 1381 B bot(A x) => x as B; |
1659 mOfOs = new M<Object>(); // Reset type propagation. | 1382 } |
1660 } | 1383 |
1661 { | 1384 typedef T Function2<S, T>(S z); |
1662 mOfAs = /*warning:DOWN_CAST_COMPOSITE*/mOfDs; | 1385 |
1663 mOfAs = /*info:DOWN_CAST_IMPLICIT*/mOfOs; | 1386 void main() { |
1664 mOfAs = mOfAs; | 1387 C c = new C(); |
1665 mOfAs = /*warning:DOWN_CAST_COMPOSITE*/lOfDs; | 1388 { |
1666 mOfAs = /*info:DOWN_CAST_IMPLICIT*/lOfOs; | 1389 Function2<B, A> f; |
1667 mOfAs = /*info:DOWN_CAST_IMPLICIT*/lOfAs; | 1390 f = c.top; |
1668 } | 1391 f = c.left; |
1669 } | 1392 f = c.right; |
1670 '''); | 1393 f = c.bot; |
1671 }); | 1394 } |
1672 | 1395 { |
1673 test('Type checking literals', () { | 1396 Function2<B, B> f; |
1674 checkFile(''' | 1397 f = /*warning:DOWN_CAST_COMPOSITE*/c.top; |
1675 test() { | 1398 f = c.left; |
1676 num n = 3; | 1399 f = /*warning:DOWN_CAST_COMPOSITE*/c.right; |
1677 int i = 3; | 1400 f = c.bot; |
1678 String s = "hello"; | 1401 } |
1679 { | 1402 { |
1680 List<int> l = <int>[i]; | 1403 Function2<A, A> f; |
1681 l = <int>[/*warning:LIST_ELEMENT_TYPE_NOT_ASSIGNABLE*/s]; | 1404 f = /*warning:DOWN_CAST_COMPOSITE*/c.top; |
1682 l = <int>[/*info:DOWN_CAST_IMPLICIT*/n]; | 1405 f = /*warning:DOWN_CAST_COMPOSITE*/c.left; |
1683 l = <int>[i, /*info:DOWN_CAST_IMPLICIT*/n, /*warning:LIST_ELEMENT
_TYPE_NOT_ASSIGNABLE*/s]; | 1406 f = c.right; |
1684 } | 1407 f = c.bot; |
1685 { | 1408 } |
1686 List l = /*info:INFERRED_TYPE_LITERAL*/[i]; | 1409 { |
1687 l = /*info:INFERRED_TYPE_LITERAL*/[s]; | 1410 Function2<A, B> f; |
1688 l = /*info:INFERRED_TYPE_LITERAL*/[n]; | 1411 f = /*warning:DOWN_CAST_COMPOSITE*/c.top; |
1689 l = /*info:INFERRED_TYPE_LITERAL*/[i, n, s]; | 1412 f = /*warning:DOWN_CAST_COMPOSITE*/c.left; |
1690 } | 1413 f = /*warning:DOWN_CAST_COMPOSITE*/c.right; |
1691 { | 1414 f = c.bot; |
1692 Map<String, int> m = <String, int>{s: i}; | 1415 } |
1693 m = <String, int>{s: /*warning:MAP_VALUE_TYPE_NOT_ASSIGNABLE*/s}; | 1416 } |
1694 m = <String, int>{s: /*info:DOWN_CAST_IMPLICIT*/n}; | 1417 '''); |
1695 m = <String, int>{s: i, | 1418 } |
1696 s: /*info:DOWN_CAST_IMPLICIT*/n, | 1419 |
1697 s: /*warning:MAP_VALUE_TYPE_NOT_ASSIGNABLE*/s}; | 1420 void test_functionTypingAndSubtyping_intAndObject() { |
1698 } | 1421 checkFile(''' |
1699 // TODO(leafp): We can't currently test for key errors since the | 1422 typedef Object Top(int x); // Top of the lattice |
1700 // error marker binds to the entire entry. | 1423 typedef int Left(int x); // Left branch |
1701 { | 1424 typedef int Left2(int x); // Left branch |
1702 Map m = /*info:INFERRED_TYPE_LITERAL*/{s: i}; | 1425 typedef Object Right(Object x); // Right branch |
1703 m = /*info:INFERRED_TYPE_LITERAL*/{s: s}; | 1426 typedef int Bot(Object x); // Bottom of the lattice |
1704 m = /*info:INFERRED_TYPE_LITERAL*/{s: n}; | 1427 |
1705 m = /*info:INFERRED_TYPE_LITERAL*/ | 1428 Object globalTop(int x) => x; |
1706 {s: i, | 1429 int globalLeft(int x) => x; |
1707 s: n, | 1430 Object globalRight(Object x) => x; |
1708 s: s}; | 1431 int bot_(Object x) => /*info:DOWN_CAST_IMPLICIT*/x; |
1709 m = /*info:INFERRED_TYPE_LITERAL*/ | 1432 int globalBot(Object x) => x as int; |
1710 {i: s, | 1433 |
1711 n: s, | 1434 void main() { |
1712 s: s}; | 1435 // Note: use locals so we only know the type, not that it's a specific |
1713 } | 1436 // function declaration. (we can issue better errors in that case.) |
1714 } | 1437 var top = globalTop; |
1715 '''); | 1438 var left = globalLeft; |
1716 }); | 1439 var right = globalRight; |
1717 | 1440 var bot = globalBot; |
1718 test('casts in constant contexts', () { | 1441 |
1719 checkFile(''' | 1442 { // Check typedef equality |
1720 class A { | 1443 Left f = left; |
1721 static const num n = 3.0; | 1444 Left2 g = f; |
1722 // The severe error is from constant evaluation where we know the | 1445 } |
1723 // concrete type. | 1446 { |
1724 static const int /*severe:VARIABLE_TYPE_MISMATCH*/i = /*info:ASSIGNM
ENT_CAST*/n; | 1447 Top f; |
1725 final int fi; | 1448 f = top; |
1726 const A(num a) : this.fi = /*info:DOWN_CAST_IMPLICIT*/a; | 1449 f = left; |
1727 } | 1450 f = right; |
1728 class B extends A { | 1451 f = bot; |
1729 const B(Object a) : super(/*info:DOWN_CAST_IMPLICIT*/a); | 1452 } |
1730 } | 1453 { |
1731 void foo(Object o) { | 1454 Left f; |
1732 var a = const A(/*info:DOWN_CAST_IMPLICIT, severe:CONST_WITH_NON_CON
STANT_ARGUMENT, severe:INVALID_CONSTANT*/o); | 1455 f = /*warning:DOWN_CAST_COMPOSITE*/top; |
1733 } | 1456 f = left; |
1734 '''); | 1457 f = /*warning:DOWN_CAST_COMPOSITE*/right; // Should we reject this? |
1735 }); | 1458 f = bot; |
1736 | 1459 } |
1737 test('casts in conditionals', () { | 1460 { |
1738 checkFile(''' | 1461 Right f; |
1739 main() { | 1462 f = /*warning:DOWN_CAST_COMPOSITE*/top; |
1740 bool b = true; | 1463 f = /*warning:DOWN_CAST_COMPOSITE*/left; // Should we reject this? |
1741 num x = b ? 1 : 2.3; | 1464 f = right; |
1742 int y = /*info:ASSIGNMENT_CAST*/b ? 1 : 2.3; | 1465 f = bot; |
1743 String z = !b ? "hello" : null; | 1466 } |
1744 z = b ? null : "hello"; | 1467 { |
1745 } | 1468 Bot f; |
1746 '''); | 1469 f = /*warning:DOWN_CAST_COMPOSITE*/top; |
1747 }); | 1470 f = /*warning:DOWN_CAST_COMPOSITE*/left; |
1748 | 1471 f = /*warning:DOWN_CAST_COMPOSITE*/right; |
1749 // This is a regression test for https://github.com/dart-lang/sdk/issues/25071 | 1472 f = bot; |
1750 test('unbound redirecting constructor', () { | 1473 } |
1751 checkFile(''' | 1474 } |
1752 class Foo { | 1475 '''); |
1753 Foo() : /*severe:REDIRECT_GENERATIVE_TO_MISSING_CONSTRUCTOR*/this.init()
; | 1476 } |
1754 } | 1477 |
1755 '''); | 1478 void test_functionTypingAndSubtyping_namedAndOptionalParameters() { |
1756 }); | 1479 checkFile(''' |
1757 | 1480 class A {} |
1758 test('redirecting constructor', () { | 1481 |
1759 checkFile(''' | 1482 typedef A FR(A x); |
1760 class A { | 1483 typedef A FO([A x]); |
1761 A(A x) {} | 1484 typedef A FN({A x}); |
1762 A.two() : this(/*warning:ARGUMENT_TYPE_NOT_ASSIGNABLE*/3); | 1485 typedef A FRR(A x, A y); |
1763 } | 1486 typedef A FRO(A x, [A y]); |
1764 '''); | 1487 typedef A FRN(A x, {A n}); |
1765 }); | 1488 typedef A FOO([A x, A y]); |
1766 | 1489 typedef A FNN({A x, A y}); |
1767 test('super constructor', () { | 1490 typedef A FNNN({A z, A y, A x}); |
1768 checkFile(''' | 1491 |
1769 class A { A(A x) {} } | 1492 void main() { |
1770 class B extends A { | 1493 FR r; |
1771 B() : super(/*warning:ARGUMENT_TYPE_NOT_ASSIGNABLE*/3); | 1494 FO o; |
1772 } | 1495 FN n; |
1773 '''); | 1496 FRR rr; |
1774 }); | 1497 FRO ro; |
1775 | 1498 FRN rn; |
1776 test('factory constructor downcast', () { | 1499 FOO oo; |
| 1500 FNN nn; |
| 1501 FNNN nnn; |
| 1502 |
| 1503 r = r; |
| 1504 r = o; |
| 1505 r = /*warning:INVALID_ASSIGNMENT*/n; |
| 1506 r = /*warning:INVALID_ASSIGNMENT*/rr; |
| 1507 r = ro; |
| 1508 r = rn; |
| 1509 r = oo; |
| 1510 r = /*warning:INVALID_ASSIGNMENT*/nn; |
| 1511 r = /*warning:INVALID_ASSIGNMENT*/nnn; |
| 1512 |
| 1513 o = /*warning:DOWN_CAST_COMPOSITE*/r; |
| 1514 o = o; |
| 1515 o = /*warning:INVALID_ASSIGNMENT*/n; |
| 1516 o = /*warning:INVALID_ASSIGNMENT*/rr; |
| 1517 o = /*warning:INVALID_ASSIGNMENT*/ro; |
| 1518 o = /*warning:INVALID_ASSIGNMENT*/rn; |
| 1519 o = oo; |
| 1520 o = /*warning:INVALID_ASSIGNMENT*/nn; |
| 1521 o = /*warning:INVALID_ASSIGNMENT*/nnn; |
| 1522 |
| 1523 n = /*warning:INVALID_ASSIGNMENT*/r; |
| 1524 n = /*warning:INVALID_ASSIGNMENT*/o; |
| 1525 n = n; |
| 1526 n = /*warning:INVALID_ASSIGNMENT*/rr; |
| 1527 n = /*warning:INVALID_ASSIGNMENT*/ro; |
| 1528 n = /*warning:INVALID_ASSIGNMENT*/rn; |
| 1529 n = /*warning:INVALID_ASSIGNMENT*/oo; |
| 1530 n = nn; |
| 1531 n = nnn; |
| 1532 |
| 1533 rr = /*warning:INVALID_ASSIGNMENT*/r; |
| 1534 rr = /*warning:INVALID_ASSIGNMENT*/o; |
| 1535 rr = /*warning:INVALID_ASSIGNMENT*/n; |
| 1536 rr = rr; |
| 1537 rr = ro; |
| 1538 rr = /*warning:INVALID_ASSIGNMENT*/rn; |
| 1539 rr = oo; |
| 1540 rr = /*warning:INVALID_ASSIGNMENT*/nn; |
| 1541 rr = /*warning:INVALID_ASSIGNMENT*/nnn; |
| 1542 |
| 1543 ro = /*warning:DOWN_CAST_COMPOSITE*/r; |
| 1544 ro = /*warning:INVALID_ASSIGNMENT*/o; |
| 1545 ro = /*warning:INVALID_ASSIGNMENT*/n; |
| 1546 ro = /*warning:DOWN_CAST_COMPOSITE*/rr; |
| 1547 ro = ro; |
| 1548 ro = /*warning:INVALID_ASSIGNMENT*/rn; |
| 1549 ro = oo; |
| 1550 ro = /*warning:INVALID_ASSIGNMENT*/nn; |
| 1551 ro = /*warning:INVALID_ASSIGNMENT*/nnn; |
| 1552 |
| 1553 rn = /*warning:DOWN_CAST_COMPOSITE*/r; |
| 1554 rn = /*warning:INVALID_ASSIGNMENT*/o; |
| 1555 rn = /*warning:INVALID_ASSIGNMENT*/n; |
| 1556 rn = /*warning:INVALID_ASSIGNMENT*/rr; |
| 1557 rn = /*warning:INVALID_ASSIGNMENT*/ro; |
| 1558 rn = rn; |
| 1559 rn = /*warning:INVALID_ASSIGNMENT*/oo; |
| 1560 rn = /*warning:INVALID_ASSIGNMENT*/nn; |
| 1561 rn = /*warning:INVALID_ASSIGNMENT*/nnn; |
| 1562 |
| 1563 oo = /*warning:DOWN_CAST_COMPOSITE*/r; |
| 1564 oo = /*warning:DOWN_CAST_COMPOSITE*/o; |
| 1565 oo = /*warning:INVALID_ASSIGNMENT*/n; |
| 1566 oo = /*warning:DOWN_CAST_COMPOSITE*/rr; |
| 1567 oo = /*warning:DOWN_CAST_COMPOSITE*/ro; |
| 1568 oo = /*warning:INVALID_ASSIGNMENT*/rn; |
| 1569 oo = oo; |
| 1570 oo = /*warning:INVALID_ASSIGNMENT*/nn; |
| 1571 oo = /*warning:INVALID_ASSIGNMENT*/nnn; |
| 1572 |
| 1573 nn = /*warning:INVALID_ASSIGNMENT*/r; |
| 1574 nn = /*warning:INVALID_ASSIGNMENT*/o; |
| 1575 nn = /*warning:DOWN_CAST_COMPOSITE*/n; |
| 1576 nn = /*warning:INVALID_ASSIGNMENT*/rr; |
| 1577 nn = /*warning:INVALID_ASSIGNMENT*/ro; |
| 1578 nn = /*warning:INVALID_ASSIGNMENT*/rn; |
| 1579 nn = /*warning:INVALID_ASSIGNMENT*/oo; |
| 1580 nn = nn; |
| 1581 nn = nnn; |
| 1582 |
| 1583 nnn = /*warning:INVALID_ASSIGNMENT*/r; |
| 1584 nnn = /*warning:INVALID_ASSIGNMENT*/o; |
| 1585 nnn = /*warning:DOWN_CAST_COMPOSITE*/n; |
| 1586 nnn = /*warning:INVALID_ASSIGNMENT*/rr; |
| 1587 nnn = /*warning:INVALID_ASSIGNMENT*/ro; |
| 1588 nnn = /*warning:INVALID_ASSIGNMENT*/rn; |
| 1589 nnn = /*warning:INVALID_ASSIGNMENT*/oo; |
| 1590 nnn = /*warning:DOWN_CAST_COMPOSITE*/nn; |
| 1591 nnn = nnn; |
| 1592 } |
| 1593 '''); |
| 1594 } |
| 1595 |
| 1596 void test_functionTypingAndSubtyping_objectsWithCallMethods() { |
| 1597 checkFile(''' |
| 1598 typedef int I2I(int x); |
| 1599 typedef num N2N(num x); |
| 1600 class A { |
| 1601 int call(int x) => x; |
| 1602 } |
| 1603 class B { |
| 1604 num call(num x) => x; |
| 1605 } |
| 1606 int i2i(int x) => x; |
| 1607 num n2n(num x) => x; |
| 1608 void main() { |
| 1609 { |
| 1610 I2I f; |
| 1611 f = new A(); |
| 1612 f = /*warning:INVALID_ASSIGNMENT*/new B(); |
| 1613 f = i2i; |
| 1614 f = /*severe:STATIC_TYPE_ERROR*/n2n; |
| 1615 f = /*warning:DOWN_CAST_COMPOSITE*/i2i as Object; |
| 1616 f = /*warning:DOWN_CAST_COMPOSITE*/n2n as Function; |
| 1617 } |
| 1618 { |
| 1619 N2N f; |
| 1620 f = /*warning:INVALID_ASSIGNMENT*/new A(); |
| 1621 f = new B(); |
| 1622 f = /*severe:STATIC_TYPE_ERROR*/i2i; |
| 1623 f = n2n; |
| 1624 f = /*warning:DOWN_CAST_COMPOSITE*/i2i as Object; |
| 1625 f = /*warning:DOWN_CAST_COMPOSITE*/n2n as Function; |
| 1626 } |
| 1627 { |
| 1628 A f; |
| 1629 f = new A(); |
| 1630 f = /*warning:INVALID_ASSIGNMENT*/new B(); |
| 1631 f = /*warning:INVALID_ASSIGNMENT*/i2i; |
| 1632 f = /*warning:INVALID_ASSIGNMENT*/n2n; |
| 1633 f = /*info:DOWN_CAST_IMPLICIT*/i2i as Object; |
| 1634 f = /*info:DOWN_CAST_IMPLICIT*/n2n as Function; |
| 1635 } |
| 1636 { |
| 1637 B f; |
| 1638 f = /*warning:INVALID_ASSIGNMENT*/new A(); |
| 1639 f = new B(); |
| 1640 f = /*warning:INVALID_ASSIGNMENT*/i2i; |
| 1641 f = /*warning:INVALID_ASSIGNMENT*/n2n; |
| 1642 f = /*info:DOWN_CAST_IMPLICIT*/i2i as Object; |
| 1643 f = /*info:DOWN_CAST_IMPLICIT*/n2n as Function; |
| 1644 } |
| 1645 { |
| 1646 Function f; |
| 1647 f = new A(); |
| 1648 f = new B(); |
| 1649 f = i2i; |
| 1650 f = n2n; |
| 1651 f = /*info:DOWN_CAST_IMPLICIT*/i2i as Object; |
| 1652 f = (n2n as Function); |
| 1653 } |
| 1654 } |
| 1655 '''); |
| 1656 } |
| 1657 |
| 1658 void test_functionTypingAndSubtyping_staticMethodVariance() { |
| 1659 checkFile(''' |
| 1660 class A {} |
| 1661 class B extends A {} |
| 1662 |
| 1663 class C { |
| 1664 static A top(B x) => x; |
| 1665 static B left(B x) => x; |
| 1666 static A right(A x) => x; |
| 1667 static B bot(A x) => x as B; |
| 1668 } |
| 1669 |
| 1670 typedef T Function2<S, T>(S z); |
| 1671 |
| 1672 void main() { |
| 1673 { |
| 1674 Function2<B, A> f; |
| 1675 f = C.top; |
| 1676 f = C.left; |
| 1677 f = C.right; |
| 1678 f = C.bot; |
| 1679 } |
| 1680 { |
| 1681 Function2<B, B> f; |
| 1682 f = /*severe:STATIC_TYPE_ERROR*/C.top; |
| 1683 f = C.left; |
| 1684 f = /*severe:STATIC_TYPE_ERROR*/C.right; |
| 1685 f = C.bot; |
| 1686 } |
| 1687 { |
| 1688 Function2<A, A> f; |
| 1689 f = /*severe:STATIC_TYPE_ERROR*/C.top; |
| 1690 f = /*severe:STATIC_TYPE_ERROR*/C.left; |
| 1691 f = C.right; |
| 1692 f = C.bot; |
| 1693 } |
| 1694 { |
| 1695 Function2<A, B> f; |
| 1696 f = /*severe:STATIC_TYPE_ERROR*/C.top; |
| 1697 f = /*severe:STATIC_TYPE_ERROR*/C.left; |
| 1698 f = /*severe:STATIC_TYPE_ERROR*/C.right; |
| 1699 f = C.bot; |
| 1700 } |
| 1701 } |
| 1702 '''); |
| 1703 } |
| 1704 |
| 1705 void test_functionTypingAndSubtyping_subtypeOfUniversalType() { |
| 1706 checkFile(''' |
| 1707 void main() { |
| 1708 nonGenericFn(x) => null; |
| 1709 { |
| 1710 /*=R*/ f/*<P, R>*/(/*=P*/ p) => null; |
| 1711 /*=T*/ g/*<S, T>*/(/*=S*/ s) => null; |
| 1712 |
| 1713 var local = f; |
| 1714 local = g; // valid |
| 1715 |
| 1716 // Non-generic function cannot subtype a generic one. |
| 1717 local = /*warning:INVALID_ASSIGNMENT*/(x) => null; |
| 1718 local = /*warning:INVALID_ASSIGNMENT*/nonGenericFn; |
| 1719 } |
| 1720 { |
| 1721 Iterable/*<R>*/ f/*<P, R>*/(List/*<P>*/ p) => null; |
| 1722 List/*<T>*/ g/*<S, T>*/(Iterable/*<S>*/ s) => null; |
| 1723 |
| 1724 var local = f; |
| 1725 local = g; // valid |
| 1726 |
| 1727 var local2 = g; |
| 1728 local = local2; |
| 1729 local2 = /*severe:STATIC_TYPE_ERROR*/f; |
| 1730 local2 = /*warning:DOWN_CAST_COMPOSITE*/local; |
| 1731 |
| 1732 // Non-generic function cannot subtype a generic one. |
| 1733 local = /*warning:INVALID_ASSIGNMENT*/(x) => null; |
| 1734 local = /*warning:INVALID_ASSIGNMENT*/nonGenericFn; |
| 1735 } |
| 1736 } |
| 1737 '''); |
| 1738 } |
| 1739 |
| 1740 void test_functionTypingAndSubtyping_uninferredClosure() { |
| 1741 checkFile(''' |
| 1742 typedef num Num2Num(num x); |
| 1743 void main() { |
| 1744 Num2Num g = /*info:INFERRED_TYPE_CLOSURE,severe:STATIC_TYPE_ERROR*/(int x) { r
eturn x; }; |
| 1745 print(g(42)); |
| 1746 } |
| 1747 '''); |
| 1748 } |
| 1749 |
| 1750 void test_functionTypingAndSubtyping_void() { |
| 1751 checkFile(''' |
| 1752 class A { |
| 1753 void bar() => null; |
| 1754 void foo() => bar(); // allowed |
| 1755 } |
| 1756 '''); |
| 1757 } |
| 1758 |
| 1759 void test_genericClassMethodOverride() { |
| 1760 checkFile(''' |
| 1761 class A {} |
| 1762 class B extends A {} |
| 1763 |
| 1764 class Base<T extends B> { |
| 1765 T foo() => null; |
| 1766 } |
| 1767 |
| 1768 class Derived<S extends A> extends Base<B> { |
| 1769 /*severe:INVALID_METHOD_OVERRIDE*/S |
| 1770 /*warning:INVALID_METHOD_OVERRIDE_RETURN_TYPE*/foo() => null; |
| 1771 } |
| 1772 |
| 1773 class Derived2<S extends B> extends Base<B> { |
| 1774 S foo() => null; |
| 1775 } |
| 1776 '''); |
| 1777 } |
| 1778 |
| 1779 void test_genericFunctionWrongNumberOfArguments() { |
1777 checkFile(r''' | 1780 checkFile(r''' |
1778 class Animal { | 1781 /*=T*/ foo/*<T>*/(/*=T*/ x, /*=T*/ y) => x; |
1779 Animal(); | 1782 /*=T*/ bar/*<T>*/({/*=T*/ x, /*=T*/ y}) => x; |
1780 factory Animal.cat() => new Cat(); | 1783 |
1781 } | 1784 main() { |
1782 | 1785 String x; |
1783 class Cat extends Animal {} | 1786 // resolving these shouldn't crash. |
1784 | 1787 foo/*warning:EXTRA_POSITIONAL_ARGUMENTS*/(1, 2, 3); |
1785 void main() { | 1788 x = foo/*warning:EXTRA_POSITIONAL_ARGUMENTS*/('1', '2', '3'); |
1786 Cat c = /*info:ASSIGNMENT_CAST*/new Animal.cat(); | 1789 foo/*warning:NOT_ENOUGH_REQUIRED_ARGUMENTS*/(1); |
1787 c = /*severe:STATIC_TYPE_ERROR*/new Animal(); | 1790 x = foo/*warning:NOT_ENOUGH_REQUIRED_ARGUMENTS*/('1'); |
1788 }'''); | 1791 x = /*info:DYNAMIC_CAST*/foo/*warning:EXTRA_POSITIONAL_ARGUMENTS*/(1, 2, 3); |
1789 }); | 1792 x = /*info:DYNAMIC_CAST*/foo/*warning:NOT_ENOUGH_REQUIRED_ARGUMENTS*/(1); |
1790 | 1793 |
1791 test('field/field override', () { | 1794 // named arguments |
1792 checkFile(''' | 1795 bar(y: 1, x: 2, /*warning:UNDEFINED_NAMED_PARAMETER*/z: 3); |
1793 class A {} | 1796 x = bar(/*warning:UNDEFINED_NAMED_PARAMETER*/z: '1', x: '2', y: '3'); |
1794 class B extends A {} | 1797 bar(y: 1); |
1795 class C extends B {} | 1798 x = bar(x: '1', /*warning:UNDEFINED_NAMED_PARAMETER*/z: 42); |
1796 | 1799 x = /*info:DYNAMIC_CAST*/bar(y: 1, x: 2, /*warning:UNDEFINED_NAMED_PARAMETER*/
z: 3); |
1797 class Base { | 1800 x = /*info:DYNAMIC_CAST*/bar(x: 1); |
1798 B f1; | 1801 } |
1799 B f2; | 1802 '''); |
1800 B f3; | 1803 } |
1801 B f4; | 1804 |
1802 } | 1805 void test_genericMethodOverride() { |
1803 | 1806 checkFile(''' |
1804 class Child extends Base { | 1807 class Future<T> { |
1805 /*severe:INVALID_FIELD_OVERRIDE,severe:INVALID_METHOD_OVERRIDE*/A f1
; // invalid for getter | 1808 /*=S*/ then/*<S>*/(/*=S*/ onValue(T t)) => null; |
1806 /*severe:INVALID_FIELD_OVERRIDE,severe:INVALID_METHOD_OVERRIDE*/C f2
; // invalid for setter | 1809 } |
1807 /*severe:INVALID_FIELD_OVERRIDE*/var f3; | 1810 |
1808 /*severe:INVALID_FIELD_OVERRIDE,severe:INVALID_METHOD_OVERRIDE,sever
e:INVALID_METHOD_OVERRIDE*/dynamic f4; | 1811 class DerivedFuture<T> extends Future<T> { |
1809 } | 1812 /*=S*/ then/*<S>*/(/*=S*/ onValue(T t)) => null; |
1810 | 1813 } |
1811 class Child2 implements Base { | 1814 |
1812 /*severe:INVALID_METHOD_OVERRIDE*/A f1; // invalid for getter | 1815 class DerivedFuture2<A> extends Future<A> { |
1813 /*severe:INVALID_METHOD_OVERRIDE*/C f2; // invalid for setter | 1816 /*=B*/ then/*<B>*/(/*=B*/ onValue(A a)) => null; |
1814 var f3; | 1817 } |
1815 /*severe:INVALID_METHOD_OVERRIDE,severe:INVALID_METHOD_OVERRIDE*/dyn
amic f4; | 1818 |
1816 } | 1819 class DerivedFuture3<T> extends Future<T> { |
1817 '''); | 1820 /*=S*/ then/*<S>*/(Object onValue(T t)) => null; |
1818 }); | 1821 } |
1819 | 1822 |
1820 test('private override', () { | 1823 class DerivedFuture4<A> extends Future<A> { |
1821 addFile( | 1824 /*=B*/ then/*<B>*/(Object onValue(A a)) => null; |
1822 ''' | 1825 } |
1823 import 'main.dart' as main; | 1826 '''); |
1824 | 1827 } |
1825 class Base { | 1828 |
1826 var f1; | 1829 void test_getterGetterOverride() { |
1827 var _f2; | 1830 checkFile(''' |
1828 var _f3; | 1831 class A {} |
1829 get _f4 => null; | 1832 class B extends A {} |
1830 | 1833 class C extends B {} |
1831 int _m1() => null; | 1834 |
1832 } | 1835 abstract class Base { |
1833 | 1836 B get f1; |
1834 class GrandChild extends main.Child { | 1837 B get f2; |
1835 /*severe:INVALID_FIELD_OVERRIDE*/var _f2; | 1838 B get f3; |
1836 /*severe:INVALID_FIELD_OVERRIDE*/var _f3; | 1839 B get f4; |
1837 var _f4; | 1840 } |
1838 | 1841 |
1839 /*severe:INVALID_METHOD_OVERRIDE*/String | 1842 class Child extends Base { |
1840 /*warning:INVALID_METHOD_OVERRIDE_RETURN_TYPE*/_m1() => null; | 1843 /*severe:INVALID_METHOD_OVERRIDE*/A get f1 => null; |
1841 } | 1844 C get f2 => null; |
1842 ''', | 1845 get f3 => null; |
1843 name: '/helper.dart'); | 1846 /*severe:INVALID_METHOD_OVERRIDE*/dynamic get f4 => null; |
1844 checkFile(''' | 1847 } |
1845 import 'helper.dart' as helper; | 1848 '''); |
1846 | 1849 } |
1847 class Child extends helper.Base { | 1850 |
1848 /*severe:INVALID_FIELD_OVERRIDE*/var f1; | 1851 void test_getterOverride_fuzzyArrows() { |
1849 var _f2; | 1852 checkFile(''' |
1850 var _f4; | 1853 typedef void ToVoid<T>(T x); |
1851 | 1854 |
1852 String _m1() => null; | 1855 class F { |
1853 } | 1856 ToVoid<dynamic> get f => null; |
1854 '''); | 1857 ToVoid<int> get g => null; |
1855 }); | 1858 } |
1856 | 1859 |
1857 test('getter/getter override', () { | 1860 class G extends F { |
1858 checkFile(''' | 1861 ToVoid<int> get f => null; |
1859 class A {} | 1862 /*severe:INVALID_METHOD_OVERRIDE*/ToVoid<dynamic> get g => null; |
1860 class B extends A {} | 1863 } |
1861 class C extends B {} | 1864 |
1862 | 1865 class H implements F { |
1863 abstract class Base { | 1866 ToVoid<int> get f => null; |
1864 B get f1; | 1867 /*severe:INVALID_METHOD_OVERRIDE*/ToVoid<dynamic> get g => null; |
1865 B get f2; | 1868 } |
1866 B get f3; | 1869 '''); |
1867 B get f4; | 1870 } |
1868 } | 1871 |
1869 | 1872 void test_ifForDoWhileStatementsUseBooleanConversion() { |
1870 class Child extends Base { | 1873 checkFile(''' |
1871 /*severe:INVALID_METHOD_OVERRIDE*/A get f1 => null; | 1874 main() { |
1872 C get f2 => null; | 1875 dynamic dyn = 42; |
1873 get f3 => null; | 1876 Object obj = 42; |
1874 /*severe:INVALID_METHOD_OVERRIDE*/dynamic get f4 => null; | 1877 int i = 42; |
1875 } | 1878 bool b = false; |
1876 '''); | 1879 |
1877 }); | 1880 if (b) {} |
1878 | 1881 if (/*info:DYNAMIC_CAST*/dyn) {} |
1879 test('field/getter override', () { | 1882 if (/*info:DOWN_CAST_IMPLICIT*/obj) {} |
1880 checkFile(''' | 1883 if (/*warning:NON_BOOL_CONDITION*/i) {} |
1881 class A {} | 1884 |
1882 class B extends A {} | 1885 while (b) {} |
1883 class C extends B {} | 1886 while (/*info:DYNAMIC_CAST*/dyn) {} |
1884 | 1887 while (/*info:DOWN_CAST_IMPLICIT*/obj) {} |
1885 abstract class Base { | 1888 while (/*warning:NON_BOOL_CONDITION*/i) {} |
1886 B f1; | 1889 |
1887 B f2; | 1890 do {} while (b); |
1888 B f3; | 1891 do {} while (/*info:DYNAMIC_CAST*/dyn); |
1889 B f4; | 1892 do {} while (/*info:DOWN_CAST_IMPLICIT*/obj); |
1890 } | 1893 do {} while (/*warning:NON_BOOL_CONDITION*/i); |
1891 | 1894 |
1892 class Child extends Base { | 1895 for (;b;) {} |
1893 /*severe:INVALID_FIELD_OVERRIDE,severe:INVALID_METHOD_OVERRIDE*/A ge
t f1 => null; | 1896 for (;/*info:DYNAMIC_CAST*/dyn;) {} |
1894 /*severe:INVALID_FIELD_OVERRIDE*/C get f2 => null; | 1897 for (;/*info:DOWN_CAST_IMPLICIT*/obj;) {} |
1895 /*severe:INVALID_FIELD_OVERRIDE*/get f3 => null; | 1898 for (;/*warning:NON_BOOL_CONDITION*/i;) {} |
1896 /*severe:INVALID_FIELD_OVERRIDE,severe:INVALID_METHOD_OVERRIDE*/dyna
mic get f4 => null; | 1899 } |
1897 } | 1900 '''); |
1898 | 1901 } |
1899 class /*warning:NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_FOUR*/Chil
d2 implements Base { | 1902 |
1900 /*severe:INVALID_METHOD_OVERRIDE*/A get f1 => null; | 1903 void test_invalidOverrides_baseClassOverrideToChildInterface() { |
1901 C get f2 => null; | 1904 checkFile(''' |
1902 get f3 => null; | 1905 class A {} |
1903 /*severe:INVALID_METHOD_OVERRIDE*/dynamic get f4 => null; | 1906 class B {} |
1904 } | 1907 |
1905 '''); | 1908 abstract class I { |
1906 }); | 1909 m(A a); |
1907 | 1910 } |
1908 test('setter/setter override', () { | 1911 |
1909 checkFile(''' | 1912 class Base { |
1910 class A {} | 1913 m(B a) {} |
1911 class B extends A {} | 1914 } |
1912 class C extends B {} | 1915 |
1913 | 1916 class /*warning:INCONSISTENT_METHOD_INHERITANCE*/T1 |
1914 abstract class Base { | 1917 /*severe:INVALID_METHOD_OVERRIDE*/extends Base implements I {} |
1915 void set f1(B value); | 1918 '''); |
1916 void set f2(B value); | 1919 } |
1917 void set f3(B value); | 1920 |
1918 void set f4(B value); | 1921 void test_invalidOverrides_childOverride() { |
1919 void set f5(B value); | 1922 checkFile(''' |
1920 } | 1923 class A {} |
1921 | 1924 class B {} |
1922 class Child extends Base { | 1925 |
1923 void set f1(A value) {} | 1926 class Base { |
1924 /*severe:INVALID_METHOD_OVERRIDE*/void set f2(C value) {} | 1927 A f; |
1925 void set f3(value) {} | 1928 } |
1926 /*severe:INVALID_METHOD_OVERRIDE*/void set f4(dynamic value) {} | 1929 |
1927 set f5(B value) {} | 1930 class T1 extends Base { |
1928 } | 1931 /*warning:MISMATCHED_GETTER_AND_SETTER_TYPES_FROM_SUPERTYPE, severe:INVALID_FI
ELD_OVERRIDE, severe:INVALID_METHOD_OVERRIDE*/B get |
1929 '''); | 1932 /*warning:INVALID_GETTER_OVERRIDE_RETURN_TYPE*/f => null; |
1930 }); | 1933 } |
1931 | 1934 |
1932 test('field/setter override', () { | 1935 class T2 extends Base { |
1933 checkFile(''' | 1936 /*warning:MISMATCHED_GETTER_AND_SETTER_TYPES_FROM_SUPERTYPE, severe:INVALID_FI
ELD_OVERRIDE, severe:INVALID_METHOD_OVERRIDE*/set f( |
1934 class A {} | 1937 /*warning:INVALID_SETTER_OVERRIDE_NORMAL_PARAM_TYPE*/B b) => null; |
1935 class B extends A {} | 1938 } |
1936 class C extends B {} | 1939 |
1937 | 1940 class T3 extends Base { |
1938 class Base { | 1941 /*severe:INVALID_FIELD_OVERRIDE, severe:INVALID_METHOD_OVERRIDE*/final B |
1939 B f1; | 1942 /*warning:FINAL_NOT_INITIALIZED, warning:INVALID_GETTER_OVERRIDE_RETURN_TY
PE*/f; |
1940 B f2; | 1943 } |
1941 B f3; | 1944 class T4 extends Base { |
1942 B f4; | 1945 // two: one for the getter one for the setter. |
1943 B f5; | 1946 /*severe:INVALID_FIELD_OVERRIDE, severe:INVALID_METHOD_OVERRIDE, severe:INVALI
D_METHOD_OVERRIDE*/B |
1944 } | 1947 /*warning:INVALID_GETTER_OVERRIDE_RETURN_TYPE, warning:INVALID_SETTER_OVER
RIDE_NORMAL_PARAM_TYPE*/f; |
1945 | 1948 } |
1946 class Child extends Base { | 1949 |
1947 /*severe:INVALID_FIELD_OVERRIDE*/B get f1 => null; | 1950 class /*warning:NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_ONE*/T5 implements B
ase { |
1948 /*severe:INVALID_FIELD_OVERRIDE*/B get f2 => null; | 1951 /*warning:MISMATCHED_GETTER_AND_SETTER_TYPES_FROM_SUPERTYPE, severe:INVALID_ME
THOD_OVERRIDE*/B get |
1949 /*severe:INVALID_FIELD_OVERRIDE*/B get f3 => null; | 1952 /*warning:INVALID_GETTER_OVERRIDE_RETURN_TYPE*/f => null; |
1950 /*severe:INVALID_FIELD_OVERRIDE*/B get f4 => null; | 1953 } |
1951 /*severe:INVALID_FIELD_OVERRIDE*/B get f5 => null; | 1954 |
1952 | 1955 class /*warning:NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_ONE*/T6 implements B
ase { |
1953 /*severe:INVALID_FIELD_OVERRIDE*/void set f1(A value) {} | 1956 /*warning:MISMATCHED_GETTER_AND_SETTER_TYPES_FROM_SUPERTYPE, severe:INVALID_ME
THOD_OVERRIDE*/set f( |
1954 /*severe:INVALID_FIELD_OVERRIDE,severe:INVALID_METHOD_OVERRIDE*/void
set f2(C value) {} | 1957 /*warning:INVALID_SETTER_OVERRIDE_NORMAL_PARAM_TYPE*/B b) => null; |
1955 /*severe:INVALID_FIELD_OVERRIDE*/void set f3(value) {} | 1958 } |
1956 /*severe:INVALID_FIELD_OVERRIDE,severe:INVALID_METHOD_OVERRIDE*/void
set f4(dynamic value) {} | 1959 |
1957 /*severe:INVALID_FIELD_OVERRIDE*/set f5(B value) {} | 1960 class /*warning:NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_ONE*/T7 implements B
ase { |
1958 } | 1961 /*severe:INVALID_METHOD_OVERRIDE*/final B |
1959 | 1962 /*warning:INVALID_GETTER_OVERRIDE_RETURN_TYPE*/f = null; |
1960 class Child2 implements Base { | 1963 } |
1961 B get f1 => null; | 1964 class T8 implements Base { |
1962 B get f2 => null; | 1965 // two: one for the getter one for the setter. |
1963 B get f3 => null; | 1966 /*severe:INVALID_METHOD_OVERRIDE, severe:INVALID_METHOD_OVERRIDE*/B |
1964 B get f4 => null; | 1967 /*warning:INVALID_GETTER_OVERRIDE_RETURN_TYPE, warning:INVALID_SETTER_OVER
RIDE_NORMAL_PARAM_TYPE*/f; |
1965 B get f5 => null; | 1968 } |
1966 | 1969 '''); |
1967 void set f1(A value) {} | 1970 } |
1968 /*severe:INVALID_METHOD_OVERRIDE*/void set f2(C value) {} | 1971 |
1969 void set f3(value) {} | 1972 void test_invalidOverrides_childOverride2() { |
1970 /*severe:INVALID_METHOD_OVERRIDE*/void set f4(dynamic value) {} | 1973 checkFile(''' |
1971 set f5(B value) {} | 1974 class A {} |
1972 } | 1975 class B {} |
1973 '''); | 1976 |
1974 }); | 1977 class Base { |
1975 | 1978 m(A a) {} |
1976 test('method override', () { | 1979 } |
1977 checkFile(''' | 1980 |
1978 class A {} | 1981 class Test extends Base { |
1979 class B extends A {} | 1982 /*severe:INVALID_METHOD_OVERRIDE*/m( |
1980 class C extends B {} | 1983 /*warning:INVALID_METHOD_OVERRIDE_NORMAL_PARAM_TYPE*/B a) {} |
1981 | 1984 } |
1982 class Base { | 1985 '''); |
1983 B m1(B a) => null; | 1986 } |
1984 B m2(B a) => null; | 1987 |
1985 B m3(B a) => null; | 1988 void test_invalidOverrides_classOverrideOfInterface() { |
1986 B m4(B a) => null; | 1989 checkFile(''' |
1987 B m5(B a) => null; | 1990 class A {} |
1988 B m6(B a) => null; | 1991 class B {} |
1989 } | 1992 |
1990 | 1993 abstract class I { |
1991 class Child extends Base { | 1994 m(A a); |
1992 /*severe:INVALID_METHOD_OVERRIDE*/A m1(A value) => null; | 1995 } |
1993 /*severe:INVALID_METHOD_OVERRIDE*/C m2(C value) => null; | 1996 |
1994 /*severe:INVALID_METHOD_OVERRIDE*/A m3(C value) => null; | 1997 class T1 implements I { |
1995 C m4(A value) => null; | 1998 /*severe:INVALID_METHOD_OVERRIDE*/m( |
1996 m5(value) => null; | 1999 /*warning:INVALID_METHOD_OVERRIDE_NORMAL_PARAM_TYPE*/B a) {} |
1997 /*severe:INVALID_METHOD_OVERRIDE*/dynamic m6(dynamic value) => null; | 2000 } |
1998 } | 2001 '''); |
1999 '''); | 2002 } |
2000 }); | 2003 |
2001 | 2004 void test_invalidOverrides_doubleOverride() { |
2002 test('method override, fuzzy arrows', () { | 2005 checkFile(''' |
2003 checkFile(''' | 2006 class A {} |
2004 abstract class A { | 2007 class B {} |
2005 bool operator ==(Object object); | 2008 |
2006 } | 2009 class Grandparent { |
2007 | 2010 m(A a) {} |
2008 class B implements A {} | 2011 } |
2009 | 2012 class Parent extends Grandparent { |
2010 | 2013 m(A a) {} |
2011 class F { | 2014 } |
2012 void f(x) {} | 2015 |
2013 void g(int x) {} | 2016 class Test extends Parent { |
2014 } | 2017 // Reported only once |
2015 | 2018 /*severe:INVALID_METHOD_OVERRIDE*/m( |
2016 class G extends F { | 2019 /*warning:INVALID_METHOD_OVERRIDE_NORMAL_PARAM_TYPE*/B a) {} |
2017 /*severe:INVALID_METHOD_OVERRIDE*/void f(int x) {} | 2020 } |
2018 void g(dynamic x) {} | 2021 '''); |
2019 } | 2022 } |
2020 | 2023 |
2021 class H implements F { | 2024 void test_invalidOverrides_doubleOverride2() { |
2022 /*severe:INVALID_METHOD_OVERRIDE*/void f(int x) {} | 2025 checkFile(''' |
2023 void g(dynamic x) {} | 2026 class A {} |
2024 } | 2027 class B {} |
2025 | 2028 |
2026 '''); | 2029 class Grandparent { |
2027 }); | 2030 m(A a) {} |
2028 | 2031 } |
2029 test('getter override, fuzzy arrows', () { | 2032 class Parent extends Grandparent { |
2030 checkFile(''' | 2033 /*severe:INVALID_METHOD_OVERRIDE*/m( |
2031 typedef void ToVoid<T>(T x); | 2034 /*warning:INVALID_METHOD_OVERRIDE_NORMAL_PARAM_TYPE*/B a) {} |
2032 class F { | 2035 } |
2033 ToVoid<dynamic> get f => null; | 2036 |
2034 ToVoid<int> get g => null; | 2037 class Test extends Parent { |
2035 } | 2038 m(B a) {} |
2036 | 2039 } |
2037 class G extends F { | 2040 '''); |
2038 ToVoid<int> get f => null; | 2041 } |
2039 /*severe:INVALID_METHOD_OVERRIDE*/ToVoid<dynamic> get g => null; | 2042 |
2040 } | 2043 void test_invalidOverrides_grandChildOverride() { |
2041 | 2044 checkFile(''' |
2042 class H implements F { | 2045 class A {} |
2043 ToVoid<int> get f => null; | 2046 class B {} |
2044 /*severe:INVALID_METHOD_OVERRIDE*/ToVoid<dynamic> get g => null; | 2047 |
2045 } | 2048 class Grandparent { |
2046 '''); | 2049 m(A a) {} |
2047 }); | 2050 int x; |
2048 | 2051 } |
2049 test('setter override, fuzzy arrows', () { | 2052 class Parent extends Grandparent { |
2050 checkFile(''' | 2053 } |
2051 typedef void ToVoid<T>(T x); | 2054 |
2052 class F { | 2055 class Test extends Parent { |
2053 void set f(ToVoid<dynamic> x) {} | 2056 /*severe:INVALID_METHOD_OVERRIDE*/m( |
2054 void set g(ToVoid<int> x) {} | 2057 /*warning:INVALID_METHOD_OVERRIDE_NORMAL_PARAM_TYPE*/B a) {} |
2055 void set h(dynamic x) {} | 2058 /*severe:INVALID_FIELD_OVERRIDE*/int x; |
2056 void set i(int x) {} | 2059 } |
2057 } | 2060 '''); |
2058 | 2061 } |
2059 class G extends F { | 2062 |
2060 /*severe:INVALID_METHOD_OVERRIDE*/void set f(ToVoid<int> x) {} | 2063 void test_invalidOverrides_mixinOverrideOfInterface() { |
2061 void set g(ToVoid<dynamic> x) {} | 2064 checkFile(''' |
2062 void set h(int x) {} | 2065 class A {} |
2063 /*severe:INVALID_METHOD_OVERRIDE*/void set i(dynamic x) {} | 2066 class B {} |
2064 } | 2067 |
2065 | 2068 abstract class I { |
2066 class H implements F { | 2069 m(A a); |
2067 /*severe:INVALID_METHOD_OVERRIDE*/void set f(ToVoid<int> x) {} | 2070 } |
2068 void set g(ToVoid<dynamic> x) {} | 2071 |
2069 void set h(int x) {} | 2072 class M { |
2070 /*severe:INVALID_METHOD_OVERRIDE*/void set i(dynamic x) {} | 2073 m(B a) {} |
2071 } | 2074 } |
2072 '''); | 2075 |
2073 }); | 2076 class /*warning:INCONSISTENT_METHOD_INHERITANCE*/T1 |
2074 | 2077 extends Object with /*severe:INVALID_METHOD_OVERRIDE*/M |
2075 test('field override, fuzzy arrows', () { | 2078 implements I {} |
2076 checkFile(''' | 2079 '''); |
2077 typedef void ToVoid<T>(T x); | 2080 } |
2078 class F { | 2081 |
2079 final ToVoid<dynamic> f = null; | 2082 void test_invalidOverrides_mixinOverrideToBase() { |
2080 final ToVoid<int> g = null; | 2083 checkFile(''' |
2081 } | 2084 class A {} |
2082 | 2085 class B {} |
2083 class G extends F { | 2086 |
2084 /*severe:INVALID_FIELD_OVERRIDE*/final ToVoid<int> f = null; | 2087 class Base { |
2085 /*severe:INVALID_FIELD_OVERRIDE, severe:INVALID_METHOD_OVERRIDE*/final T
oVoid<dynamic> g = null; | 2088 m(A a) {} |
2086 } | 2089 int x; |
2087 | 2090 } |
2088 class H implements F { | 2091 |
2089 final ToVoid<int> f = null; | 2092 class M1 { |
2090 /*severe:INVALID_METHOD_OVERRIDE*/final ToVoid<dynamic> g = null; | 2093 m(B a) {} |
2091 } | 2094 } |
2092 '''); | 2095 |
2093 }); | 2096 class M2 { |
2094 | 2097 int x; |
2095 test('generic class method override', () { | 2098 } |
2096 checkFile(''' | 2099 |
2097 class A {} | 2100 class /*warning:INCONSISTENT_METHOD_INHERITANCE*/T1 extends Base |
2098 class B extends A {} | 2101 with /*severe:INVALID_METHOD_OVERRIDE*/M1 {} |
2099 | 2102 class /*warning:INCONSISTENT_METHOD_INHERITANCE*/T2 extends Base |
2100 class Base<T extends B> { | 2103 with /*severe:INVALID_METHOD_OVERRIDE*/M1, /*severe:INVALID_FIELD_OVERRIDE*/
M2 {} |
2101 T foo() => null; | 2104 class /*warning:INCONSISTENT_METHOD_INHERITANCE*/T3 extends Base |
2102 } | 2105 with /*severe:INVALID_FIELD_OVERRIDE*/M2, /*severe:INVALID_METHOD_OVERRIDE*/
M1 {} |
2103 | 2106 '''); |
2104 class Derived<S extends A> extends Base<B> { | 2107 } |
2105 /*severe:INVALID_METHOD_OVERRIDE*/S | 2108 |
2106 /*warning:INVALID_METHOD_OVERRIDE_RETURN_TYPE*/foo() => null; | 2109 void test_invalidOverrides_mixinOverrideToMixin() { |
2107 } | 2110 checkFile(''' |
2108 | 2111 class A {} |
2109 class Derived2<S extends B> extends Base<B> { | 2112 class B {} |
2110 S foo() => null; | 2113 |
2111 } | 2114 class Base { |
2112 '''); | 2115 } |
2113 }); | 2116 |
2114 | 2117 class M1 { |
2115 test('generic method override', () { | 2118 m(B a) {} |
2116 checkFile(''' | 2119 int x; |
2117 class Future<T> { | 2120 } |
2118 /*=S*/ then/*<S>*/(/*=S*/ onValue(T t)) => null; | 2121 |
2119 } | 2122 class M2 { |
2120 | 2123 m(A a) {} |
2121 class DerivedFuture<T> extends Future<T> { | 2124 int x; |
2122 /*=S*/ then/*<S>*/(/*=S*/ onValue(T t)) => null; | 2125 } |
2123 } | 2126 |
2124 | 2127 class /*warning:INCONSISTENT_METHOD_INHERITANCE*/T1 extends Base |
2125 class DerivedFuture2<A> extends Future<A> { | 2128 with M1, |
2126 /*=B*/ then/*<B>*/(/*=B*/ onValue(A a)) => null; | 2129 /*severe:INVALID_METHOD_OVERRIDE,severe:INVALID_FIELD_OVERRIDE*/M2 {} |
2127 } | 2130 '''); |
2128 | 2131 } |
2129 class DerivedFuture3<T> extends Future<T> { | 2132 |
2130 /*=S*/ then/*<S>*/(Object onValue(T t)) => null; | 2133 void test_invalidOverrides_noDuplicateMixinOverride() { |
2131 } | |
2132 | |
2133 class DerivedFuture4<A> extends Future<A> { | |
2134 /*=B*/ then/*<B>*/(Object onValue(A a)) => null; | |
2135 } | |
2136 '''); | |
2137 }); | |
2138 | |
2139 test('generic function wrong number of arguments', () { | |
2140 checkFile(r''' | |
2141 /*=T*/ foo/*<T>*/(/*=T*/ x, /*=T*/ y) => x; | |
2142 /*=T*/ bar/*<T>*/({/*=T*/ x, /*=T*/ y}) => x; | |
2143 | |
2144 main() { | |
2145 String x; | |
2146 // resolving these shouldn't crash. | |
2147 foo/*warning:EXTRA_POSITIONAL_ARGUMENTS*/(1, 2, 3); | |
2148 x = foo/*warning:EXTRA_POSITIONAL_ARGUMENTS*/('1', '2', '3'); | |
2149 foo/*warning:NOT_ENOUGH_REQUIRED_ARGUMENTS*/(1); | |
2150 x = foo/*warning:NOT_ENOUGH_REQUIRED_ARGUMENTS*/('1'); | |
2151 x = /*info:DYNAMIC_CAST*/foo/*warning:EXTRA_POSITIONAL_ARGUMENTS*/(1
, 2, 3); | |
2152 x = /*info:DYNAMIC_CAST*/foo/*warning:NOT_ENOUGH_REQUIRED_ARGUMENTS*
/(1); | |
2153 | |
2154 // named arguments | |
2155 bar(y: 1, x: 2, /*warning:UNDEFINED_NAMED_PARAMETER*/z: 3); | |
2156 x = bar(/*warning:UNDEFINED_NAMED_PARAMETER*/z: '1', x: '2', y: '3')
; | |
2157 bar(y: 1); | |
2158 x = bar(x: '1', /*warning:UNDEFINED_NAMED_PARAMETER*/z: 42); | |
2159 x = /*info:DYNAMIC_CAST*/bar(y: 1, x: 2, /*warning:UNDEFINED_NAMED_P
ARAMETER*/z: 3); | |
2160 x = /*info:DYNAMIC_CAST*/bar(x: 1); | |
2161 } | |
2162 '''); | |
2163 }); | |
2164 | |
2165 test('type promotion from dynamic', () { | |
2166 checkFile(r''' | |
2167 f() { | |
2168 dynamic x; | |
2169 if (x is int) { | |
2170 int y = x; | |
2171 String z = /*warning:INVALID_ASSIGNMENT*/x; | |
2172 } | |
2173 } | |
2174 g() { | |
2175 Object x; | |
2176 if (x is int) { | |
2177 int y = x; | |
2178 String z = /*warning:INVALID_ASSIGNMENT*/x; | |
2179 } | |
2180 } | |
2181 '''); | |
2182 }); | |
2183 | |
2184 test('unary operators', () { | |
2185 checkFile(''' | |
2186 class A { | |
2187 A operator ~() => null; | |
2188 A operator +(int x) => null; | |
2189 A operator -(int x) => null; | |
2190 A operator -() => null; | |
2191 } | |
2192 | |
2193 foo() => new A(); | |
2194 | |
2195 test() { | |
2196 A a = new A(); | |
2197 var c = foo(); | |
2198 dynamic d; | |
2199 | |
2200 ~a; | |
2201 (/*info:DYNAMIC_INVOKE*/~d); | |
2202 | |
2203 !/*warning:NON_BOOL_NEGATION_EXPRESSION*/a; | |
2204 !/*info:DYNAMIC_CAST*/d; | |
2205 | |
2206 -a; | |
2207 (/*info:DYNAMIC_INVOKE*/-d); | |
2208 | |
2209 ++a; | |
2210 --a; | |
2211 (/*info:DYNAMIC_INVOKE*/++d); | |
2212 (/*info:DYNAMIC_INVOKE*/--d); | |
2213 | |
2214 a++; | |
2215 a--; | |
2216 (/*info:DYNAMIC_INVOKE*/d++); | |
2217 (/*info:DYNAMIC_INVOKE*/d--); | |
2218 }'''); | |
2219 }); | |
2220 | |
2221 test('binary and index operators', () { | |
2222 checkFile(''' | |
2223 class A { | |
2224 A operator *(B b) => null; | |
2225 A operator /(B b) => null; | |
2226 A operator ~/(B b) => null; | |
2227 A operator %(B b) => null; | |
2228 A operator +(B b) => null; | |
2229 A operator -(B b) => null; | |
2230 A operator <<(B b) => null; | |
2231 A operator >>(B b) => null; | |
2232 A operator &(B b) => null; | |
2233 A operator ^(B b) => null; | |
2234 A operator |(B b) => null; | |
2235 A operator[](B b) => null; | |
2236 } | |
2237 | |
2238 class B { | |
2239 A operator -(B b) => null; | |
2240 } | |
2241 | |
2242 foo() => new A(); | |
2243 | |
2244 test() { | |
2245 A a = new A(); | |
2246 B b = new B(); | |
2247 var c = foo(); | |
2248 a = a * b; | |
2249 a = a * /*info:DYNAMIC_CAST*/c; | |
2250 a = a / b; | |
2251 a = a ~/ b; | |
2252 a = a % b; | |
2253 a = a + b; | |
2254 a = a + /*warning:ARGUMENT_TYPE_NOT_ASSIGNABLE*/a; | |
2255 a = a - b; | |
2256 b = /*warning:INVALID_ASSIGNMENT*/b - b; | |
2257 a = a << b; | |
2258 a = a >> b; | |
2259 a = a & b; | |
2260 a = a ^ b; | |
2261 a = a | b; | |
2262 c = (/*info:DYNAMIC_INVOKE*/c + b); | |
2263 | |
2264 String x = 'hello'; | |
2265 int y = 42; | |
2266 x = x + x; | |
2267 x = x + /*info:DYNAMIC_CAST*/c; | |
2268 x = x + /*warning:ARGUMENT_TYPE_NOT_ASSIGNABLE*/y; | |
2269 | |
2270 bool p = true; | |
2271 p = p && p; | |
2272 p = p && /*info:DYNAMIC_CAST*/c; | |
2273 p = (/*info:DYNAMIC_CAST*/c) && p; | |
2274 p = (/*info:DYNAMIC_CAST*/c) && /*info:DYNAMIC_CAST*/c; | |
2275 p = /*warning:NON_BOOL_OPERAND*/y && p; | |
2276 p = c == y; | |
2277 | |
2278 a = a[b]; | |
2279 a = a[/*info:DYNAMIC_CAST*/c]; | |
2280 c = (/*info:DYNAMIC_INVOKE*/c[b]); | |
2281 a[/*warning:ARGUMENT_TYPE_NOT_ASSIGNABLE*/y]; | |
2282 } | |
2283 '''); | |
2284 }); | |
2285 | |
2286 test('null coalescing operator', () { | |
2287 checkFile(''' | |
2288 class A {} | |
2289 class C<T> {} | |
2290 main() { | |
2291 A a, b; | |
2292 a ??= new A(); | |
2293 b = b ?? new A(); | |
2294 | |
2295 // downwards inference | |
2296 C<int> c, d; | |
2297 c ??= /*info:INFERRED_TYPE_ALLOCATION*/new C(); | |
2298 d = d ?? /*info:INFERRED_TYPE_ALLOCATION*/new C(); | |
2299 } | |
2300 '''); | |
2301 }); | |
2302 | |
2303 test('compound assignments', () { | |
2304 checkFile(''' | |
2305 class A { | |
2306 A operator *(B b) => null; | |
2307 A operator /(B b) => null; | |
2308 A operator ~/(B b) => null; | |
2309 A operator %(B b) => null; | |
2310 A operator +(B b) => null; | |
2311 A operator -(B b) => null; | |
2312 A operator <<(B b) => null; | |
2313 A operator >>(B b) => null; | |
2314 A operator &(B b) => null; | |
2315 A operator ^(B b) => null; | |
2316 A operator |(B b) => null; | |
2317 D operator [](B index) => null; | |
2318 void operator []=(B index, D value) => null; | |
2319 } | |
2320 | |
2321 class B { | |
2322 A operator -(B b) => null; | |
2323 } | |
2324 | |
2325 class D { | |
2326 D operator +(D d) => null; | |
2327 } | |
2328 | |
2329 foo() => new A(); | |
2330 | |
2331 test() { | |
2332 int x = 0; | |
2333 x += 5; | |
2334 /*severe:STATIC_TYPE_ERROR*/x += 3.14; | |
2335 | |
2336 double y = 0.0; | |
2337 y += 5; | |
2338 y += 3.14; | |
2339 | |
2340 num z = 0; | |
2341 z += 5; | |
2342 z += 3.14; | |
2343 | |
2344 x = /*info:DOWN_CAST_IMPLICIT*/x + z; | |
2345 x += /*info:DOWN_CAST_IMPLICIT*/z; | |
2346 y = y + z; | |
2347 y += z; | |
2348 | |
2349 dynamic w = 42; | |
2350 x += /*info:DYNAMIC_CAST*/w; | |
2351 y += /*info:DYNAMIC_CAST*/w; | |
2352 z += /*info:DYNAMIC_CAST*/w; | |
2353 | |
2354 A a = new A(); | |
2355 B b = new B(); | |
2356 var c = foo(); | |
2357 a = a * b; | |
2358 a *= b; | |
2359 a *= /*info:DYNAMIC_CAST*/c; | |
2360 a /= b; | |
2361 a ~/= b; | |
2362 a %= b; | |
2363 a += b; | |
2364 a += /*warning:ARGUMENT_TYPE_NOT_ASSIGNABLE*/a; | |
2365 a -= b; | |
2366 /*severe:STATIC_TYPE_ERROR*/b -= /*warning:INVALID_ASSIGNMENT*/b; | |
2367 a <<= b; | |
2368 a >>= b; | |
2369 a &= b; | |
2370 a ^= b; | |
2371 a |= b; | |
2372 /*info:DYNAMIC_INVOKE*/c += b; | |
2373 | |
2374 var d = new D(); | |
2375 a[b] += d; | |
2376 a[/*info:DYNAMIC_CAST*/c] += d; | |
2377 a[/*warning:ARGUMENT_TYPE_NOT_ASSIGNABLE*/z] += d; | |
2378 a[b] += /*info:DYNAMIC_CAST*/c; | |
2379 a[b] += /*warning:ARGUMENT_TYPE_NOT_ASSIGNABLE*/z; | |
2380 /*info:DYNAMIC_INVOKE,info:DYNAMIC_INVOKE*/c[b] += d; | |
2381 } | |
2382 '''); | |
2383 }); | |
2384 | |
2385 test('super call placement', () { | |
2386 checkFile(''' | |
2387 class Base { | |
2388 var x; | |
2389 Base() : x = print('Base.1') { print('Base.2'); } | |
2390 } | |
2391 | |
2392 class Derived extends Base { | |
2393 var y, z; | |
2394 Derived() | |
2395 : y = print('Derived.1'), | |
2396 /*severe:INVALID_SUPER_INVOCATION*/super(), | |
2397 z = print('Derived.2') { | |
2398 print('Derived.3'); | |
2399 } | |
2400 } | |
2401 | |
2402 class Valid extends Base { | |
2403 var y, z; | |
2404 Valid() | |
2405 : y = print('Valid.1'), | |
2406 z = print('Valid.2'), | |
2407 super() { | |
2408 print('Valid.3'); | |
2409 } | |
2410 } | |
2411 | |
2412 class AlsoValid extends Base { | |
2413 AlsoValid() : super(); | |
2414 } | |
2415 | |
2416 main() => new Derived(); | |
2417 '''); | |
2418 }); | |
2419 | |
2420 test('for loop variable', () { | |
2421 checkFile(''' | |
2422 foo() { | |
2423 for (int i = 0; i < 10; i++) { | |
2424 i = /*warning:INVALID_ASSIGNMENT*/"hi"; | |
2425 } | |
2426 } | |
2427 bar() { | |
2428 for (var i = 0; i < 10; i++) { | |
2429 int j = i + 1; | |
2430 } | |
2431 } | |
2432 '''); | |
2433 }); | |
2434 | |
2435 test('loadLibrary', () { | |
2436 addFile('''library lib1;''', name: '/lib1.dart'); | |
2437 checkFile(r''' | |
2438 import 'lib1.dart' deferred as lib1; | |
2439 import 'dart:async' show Future; | |
2440 main() { | |
2441 Future f = lib1.loadLibrary(); | |
2442 }'''); | |
2443 }); | |
2444 | |
2445 group('invalid overrides', () { | |
2446 test('child override', () { | |
2447 checkFile(''' | |
2448 class A {} | |
2449 class B {} | |
2450 | |
2451 class Base { | |
2452 A f; | |
2453 } | |
2454 | |
2455 class T1 extends Base { | |
2456 /*warning:MISMATCHED_GETTER_AND_SETTER_TYPES_FROM_SUPERTYPE, sever
e:INVALID_FIELD_OVERRIDE, severe:INVALID_METHOD_OVERRIDE*/B get | |
2457 /*warning:INVALID_GETTER_OVERRIDE_RETURN_TYPE*/f => null; | |
2458 } | |
2459 | |
2460 class T2 extends Base { | |
2461 /*warning:MISMATCHED_GETTER_AND_SETTER_TYPES_FROM_SUPERTYPE, sever
e:INVALID_FIELD_OVERRIDE, severe:INVALID_METHOD_OVERRIDE*/set f( | |
2462 /*warning:INVALID_SETTER_OVERRIDE_NORMAL_PARAM_TYPE*/B b) => n
ull; | |
2463 } | |
2464 | |
2465 class T3 extends Base { | |
2466 /*severe:INVALID_FIELD_OVERRIDE, severe:INVALID_METHOD_OVERRIDE*/f
inal B | |
2467 /*warning:FINAL_NOT_INITIALIZED, warning:INVALID_GETTER_OVERRI
DE_RETURN_TYPE*/f; | |
2468 } | |
2469 class T4 extends Base { | |
2470 // two: one for the getter one for the setter. | |
2471 /*severe:INVALID_FIELD_OVERRIDE, severe:INVALID_METHOD_OVERRIDE, s
evere:INVALID_METHOD_OVERRIDE*/B | |
2472 /*warning:INVALID_GETTER_OVERRIDE_RETURN_TYPE, warning:INVALID
_SETTER_OVERRIDE_NORMAL_PARAM_TYPE*/f; | |
2473 } | |
2474 | |
2475 class /*warning:NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_ONE*/T5
implements Base { | |
2476 /*warning:MISMATCHED_GETTER_AND_SETTER_TYPES_FROM_SUPERTYPE, sever
e:INVALID_METHOD_OVERRIDE*/B get | |
2477 /*warning:INVALID_GETTER_OVERRIDE_RETURN_TYPE*/f => null; | |
2478 } | |
2479 | |
2480 class /*warning:NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_ONE*/T6
implements Base { | |
2481 /*warning:MISMATCHED_GETTER_AND_SETTER_TYPES_FROM_SUPERTYPE, sever
e:INVALID_METHOD_OVERRIDE*/set f( | |
2482 /*warning:INVALID_SETTER_OVERRIDE_NORMAL_PARAM_TYPE*/B b) => n
ull; | |
2483 } | |
2484 | |
2485 class /*warning:NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_ONE*/T7
implements Base { | |
2486 /*severe:INVALID_METHOD_OVERRIDE*/final B | |
2487 /*warning:INVALID_GETTER_OVERRIDE_RETURN_TYPE*/f = null; | |
2488 } | |
2489 class T8 implements Base { | |
2490 // two: one for the getter one for the setter. | |
2491 /*severe:INVALID_METHOD_OVERRIDE, severe:INVALID_METHOD_OVERRIDE*/
B | |
2492 /*warning:INVALID_GETTER_OVERRIDE_RETURN_TYPE, warning:INVALID
_SETTER_OVERRIDE_NORMAL_PARAM_TYPE*/f; | |
2493 } | |
2494 '''); | |
2495 }); | |
2496 | |
2497 test('child override 2', () { | |
2498 checkFile(''' | |
2499 class A {} | |
2500 class B {} | |
2501 | |
2502 class Base { | |
2503 m(A a) {} | |
2504 } | |
2505 | |
2506 class Test extends Base { | |
2507 /*severe:INVALID_METHOD_OVERRIDE*/m( | |
2508 /*warning:INVALID_METHOD_OVERRIDE_NORMAL_PARAM_TYPE*/B a) {} | |
2509 } | |
2510 '''); | |
2511 }); | |
2512 test('grandchild override', () { | |
2513 checkFile(''' | |
2514 class A {} | |
2515 class B {} | |
2516 | |
2517 class Grandparent { | |
2518 m(A a) {} | |
2519 int x; | |
2520 } | |
2521 class Parent extends Grandparent { | |
2522 } | |
2523 | |
2524 class Test extends Parent { | |
2525 /*severe:INVALID_METHOD_OVERRIDE*/m( | |
2526 /*warning:INVALID_METHOD_OVERRIDE_NORMAL_PARAM_TYPE*/B a)
{} | |
2527 /*severe:INVALID_FIELD_OVERRIDE*/int x; | |
2528 } | |
2529 '''); | |
2530 }); | |
2531 | |
2532 test('double override', () { | |
2533 checkFile(''' | |
2534 class A {} | |
2535 class B {} | |
2536 | |
2537 class Grandparent { | |
2538 m(A a) {} | |
2539 } | |
2540 class Parent extends Grandparent { | |
2541 m(A a) {} | |
2542 } | |
2543 | |
2544 class Test extends Parent { | |
2545 // Reported only once | |
2546 /*severe:INVALID_METHOD_OVERRIDE*/m( | |
2547 /*warning:INVALID_METHOD_OVERRIDE_NORMAL_PARAM_TYPE*/B a) {} | |
2548 } | |
2549 '''); | |
2550 }); | |
2551 | |
2552 test('double override 2', () { | |
2553 checkFile(''' | |
2554 class A {} | |
2555 class B {} | |
2556 | |
2557 class Grandparent { | |
2558 m(A a) {} | |
2559 } | |
2560 class Parent extends Grandparent { | |
2561 /*severe:INVALID_METHOD_OVERRIDE*/m( | |
2562 /*warning:INVALID_METHOD_OVERRIDE_NORMAL_PARAM_TYPE*/B a) {} | |
2563 } | |
2564 | |
2565 class Test extends Parent { | |
2566 m(B a) {} | |
2567 } | |
2568 '''); | |
2569 }); | |
2570 | |
2571 test('mixin override to base', () { | |
2572 checkFile(''' | |
2573 class A {} | |
2574 class B {} | |
2575 | |
2576 class Base { | |
2577 m(A a) {} | |
2578 int x; | |
2579 } | |
2580 | |
2581 class M1 { | |
2582 m(B a) {} | |
2583 } | |
2584 | |
2585 class M2 { | |
2586 int x; | |
2587 } | |
2588 | |
2589 class /*warning:INCONSISTENT_METHOD_INHERITANCE*/T1 extends Base | |
2590 with /*severe:INVALID_METHOD_OVERRIDE*/M1 {} | |
2591 class /*warning:INCONSISTENT_METHOD_INHERITANCE*/T2 extends Base | |
2592 with /*severe:INVALID_METHOD_OVERRIDE*/M1, /*severe:INVALID_FIEL
D_OVERRIDE*/M2 {} | |
2593 class /*warning:INCONSISTENT_METHOD_INHERITANCE*/T3 extends Base | |
2594 with /*severe:INVALID_FIELD_OVERRIDE*/M2, /*severe:INVALID_METHO
D_OVERRIDE*/M1 {} | |
2595 '''); | |
2596 }); | |
2597 | |
2598 test('mixin override to mixin', () { | |
2599 checkFile(''' | |
2600 class A {} | |
2601 class B {} | |
2602 | |
2603 class Base { | |
2604 } | |
2605 | |
2606 class M1 { | |
2607 m(B a) {} | |
2608 int x; | |
2609 } | |
2610 | |
2611 class M2 { | |
2612 m(A a) {} | |
2613 int x; | |
2614 } | |
2615 | |
2616 class /*warning:INCONSISTENT_METHOD_INHERITANCE*/T1 extends Base | |
2617 with M1, | |
2618 /*severe:INVALID_METHOD_OVERRIDE,severe:INVALID_FIELD_OVERRIDE*/
M2 {} | |
2619 '''); | |
2620 }); | |
2621 | |
2622 // This is a regression test for a bug in an earlier implementation were | 2134 // This is a regression test for a bug in an earlier implementation were |
2623 // names were hiding errors if the first mixin override looked correct, | 2135 // names were hiding errors if the first mixin override looked correct, |
2624 // but subsequent ones did not. | 2136 // but subsequent ones did not. |
2625 test('no duplicate mixin override', () { | 2137 checkFile(''' |
2626 checkFile(''' | 2138 class A {} |
2627 class A {} | 2139 class B {} |
2628 class B {} | 2140 |
2629 | 2141 class Base { |
2630 class Base { | 2142 m(A a) {} |
2631 m(A a) {} | 2143 } |
2632 } | 2144 |
2633 | 2145 class M1 { |
2634 class M1 { | 2146 m(A a) {} |
2635 m(A a) {} | 2147 } |
2636 } | 2148 |
2637 | 2149 class M2 { |
2638 class M2 { | 2150 m(B a) {} |
2639 m(B a) {} | 2151 } |
2640 } | 2152 |
2641 | 2153 class M3 { |
2642 class M3 { | 2154 m(B a) {} |
2643 m(B a) {} | 2155 } |
2644 } | 2156 |
2645 | 2157 class /*warning:INCONSISTENT_METHOD_INHERITANCE*/T1 extends Base |
2646 class /*warning:INCONSISTENT_METHOD_INHERITANCE*/T1 extends Base | 2158 with M1, /*severe:INVALID_METHOD_OVERRIDE*/M2, M3 {} |
2647 with M1, /*severe:INVALID_METHOD_OVERRIDE*/M2, M3 {} | 2159 '''); |
2648 '''); | 2160 } |
2649 }); | 2161 |
2650 | 2162 void |
2651 test('class override of interface', () { | 2163 test_invalidOverrides_noErrorsIfSubclassCorrectlyOverrideBaseAndInterface(
) { |
2652 checkFile(''' | |
2653 class A {} | |
2654 class B {} | |
2655 | |
2656 abstract class I { | |
2657 m(A a); | |
2658 } | |
2659 | |
2660 class T1 implements I { | |
2661 /*severe:INVALID_METHOD_OVERRIDE*/m( | |
2662 /*warning:INVALID_METHOD_OVERRIDE_NORMAL_PARAM_TYPE*/B a) {} | |
2663 } | |
2664 '''); | |
2665 }); | |
2666 | |
2667 test('base class override to child interface', () { | |
2668 checkFile(''' | |
2669 class A {} | |
2670 class B {} | |
2671 | |
2672 abstract class I { | |
2673 m(A a); | |
2674 } | |
2675 | |
2676 class Base { | |
2677 m(B a) {} | |
2678 } | |
2679 | |
2680 class /*warning:INCONSISTENT_METHOD_INHERITANCE*/T1 | |
2681 /*severe:INVALID_METHOD_OVERRIDE*/extends Base implements I {} | |
2682 '''); | |
2683 }); | |
2684 | |
2685 test('mixin override of interface', () { | |
2686 checkFile(''' | |
2687 class A {} | |
2688 class B {} | |
2689 | |
2690 abstract class I { | |
2691 m(A a); | |
2692 } | |
2693 | |
2694 class M { | |
2695 m(B a) {} | |
2696 } | |
2697 | |
2698 class /*warning:INCONSISTENT_METHOD_INHERITANCE*/T1 | |
2699 extends Object with /*severe:INVALID_METHOD_OVERRIDE*/M | |
2700 implements I {} | |
2701 '''); | |
2702 }); | |
2703 | |
2704 // This is a case were it is incorrect to say that the base class | 2164 // This is a case were it is incorrect to say that the base class |
2705 // incorrectly overrides the interface. | 2165 // incorrectly overrides the interface. |
2706 test('no errors if subclass correctly overrides base and interface', () { | 2166 checkFile(''' |
2707 checkFile(''' | 2167 class A {} |
2708 class A {} | 2168 class B {} |
2709 class B {} | 2169 |
2710 | 2170 class Base { |
2711 class Base { | 2171 m(A a) {} |
2712 m(A a) {} | 2172 } |
2713 } | 2173 |
2714 | 2174 class I1 { |
2715 class I1 { | 2175 m(B a) {} |
2716 m(B a) {} | 2176 } |
2717 } | 2177 |
2718 | 2178 class /*warning:INCONSISTENT_METHOD_INHERITANCE*/T1 |
2719 class /*warning:INCONSISTENT_METHOD_INHERITANCE*/T1 | 2179 /*severe:INVALID_METHOD_OVERRIDE*/extends Base |
2720 /*severe:INVALID_METHOD_OVERRIDE*/extends Base | 2180 implements I1 {} |
2721 implements I1 {} | 2181 |
2722 | 2182 class T2 extends Base implements I1 { |
2723 class T2 extends Base implements I1 { | 2183 m(a) {} |
2724 m(a) {} | 2184 } |
2725 } | 2185 |
2726 | 2186 class /*warning:INCONSISTENT_METHOD_INHERITANCE*/T3 |
2727 class /*warning:INCONSISTENT_METHOD_INHERITANCE*/T3 | 2187 extends Object with /*severe:INVALID_METHOD_OVERRIDE*/Base |
2728 extends Object with /*severe:INVALID_METHOD_OVERRIDE*/Base | 2188 implements I1 {} |
2729 implements I1 {} | 2189 |
2730 | 2190 class T4 extends Object with Base implements I1 { |
2731 class T4 extends Object with Base implements I1 { | 2191 m(a) {} |
2732 m(a) {} | 2192 } |
2733 } | 2193 '''); |
2734 '''); | 2194 } |
2735 }); | 2195 |
2736 }); | 2196 void test_invalidRuntimeChecks() { |
2737 | 2197 checkFile(''' |
2738 group('class override of grand interface', () { | 2198 typedef int I2I(int x); |
2739 test('interface of interface of child', () { | 2199 typedef int D2I(x); |
2740 checkFile(''' | 2200 typedef int II2I(int x, int y); |
2741 class A {} | 2201 typedef int DI2I(x, int y); |
2742 class B {} | 2202 typedef int ID2I(int x, y); |
2743 | 2203 typedef int DD2I(x, y); |
2744 abstract class I1 { | 2204 |
2745 m(A a); | 2205 typedef I2D(int x); |
2746 } | 2206 typedef D2D(x); |
2747 abstract class I2 implements I1 {} | 2207 typedef II2D(int x, int y); |
2748 | 2208 typedef DI2D(x, int y); |
2749 class T1 implements I2 { | 2209 typedef ID2D(int x, y); |
2750 /*severe:INVALID_METHOD_OVERRIDE*/m( | 2210 typedef DD2D(x, y); |
2751 /*warning:INVALID_METHOD_OVERRIDE_NORMAL_PARAM_TYPE*/B a) {} | 2211 |
2752 } | 2212 int foo(int x) => x; |
2753 '''); | 2213 int bar(int x, int y) => x + y; |
2754 }); | 2214 |
2755 test('superclass of interface of child', () { | 2215 void main() { |
2756 checkFile(''' | 2216 bool b; |
2757 class A {} | 2217 b = /*info:NON_GROUND_TYPE_CHECK_INFO*/foo is I2I; |
2758 class B {} | 2218 b = /*info:NON_GROUND_TYPE_CHECK_INFO*/foo is D2I; |
2759 | 2219 b = /*info:NON_GROUND_TYPE_CHECK_INFO*/foo is I2D; |
2760 abstract class I1 { | 2220 b = foo is D2D; |
2761 m(A a); | 2221 |
2762 } | 2222 b = /*info:NON_GROUND_TYPE_CHECK_INFO*/bar is II2I; |
2763 abstract class I2 extends I1 {} | 2223 b = /*info:NON_GROUND_TYPE_CHECK_INFO*/bar is DI2I; |
2764 | 2224 b = /*info:NON_GROUND_TYPE_CHECK_INFO*/bar is ID2I; |
2765 class T1 implements I2 { | 2225 b = /*info:NON_GROUND_TYPE_CHECK_INFO*/bar is II2D; |
2766 /*severe:INVALID_METHOD_OVERRIDE*/m( | 2226 b = /*info:NON_GROUND_TYPE_CHECK_INFO*/bar is DD2I; |
2767 /*warning:INVALID_METHOD_OVERRIDE_NORMAL_PARAM_TYPE*/B a) {} | 2227 b = /*info:NON_GROUND_TYPE_CHECK_INFO*/bar is DI2D; |
2768 } | 2228 b = /*info:NON_GROUND_TYPE_CHECK_INFO*/bar is ID2D; |
2769 '''); | 2229 b = bar is DD2D; |
2770 }); | 2230 |
2771 test('mixin of interface of child', () { | 2231 // For as, the validity of checks is deferred to runtime. |
2772 checkFile(''' | 2232 Function f; |
2773 class A {} | 2233 f = foo as I2I; |
2774 class B {} | 2234 f = foo as D2I; |
2775 | 2235 f = foo as I2D; |
2776 abstract class M1 { | 2236 f = foo as D2D; |
2777 m(A a); | 2237 |
2778 } | 2238 f = bar as II2I; |
2779 abstract class I2 extends Object with M1 {} | 2239 f = bar as DI2I; |
2780 | 2240 f = bar as ID2I; |
2781 class T1 implements I2 { | 2241 f = bar as II2D; |
2782 /*severe:INVALID_METHOD_OVERRIDE*/m( | 2242 f = bar as DD2I; |
2783 /*warning:INVALID_METHOD_OVERRIDE_NORMAL_PARAM_TYPE*/B a) {} | 2243 f = bar as DI2D; |
2784 } | 2244 f = bar as ID2D; |
2785 '''); | 2245 f = bar as DD2D; |
2786 }); | 2246 } |
2787 test('interface of abstract superclass', () { | 2247 '''); |
2788 checkFile(''' | 2248 } |
2789 class A {} | 2249 |
2790 class B {} | 2250 void test_leastUpperBounds() { |
2791 | 2251 checkFile(''' |
2792 abstract class I1 { | 2252 typedef T Returns<T>(); |
2793 m(A a); | 2253 |
2794 } | 2254 // regression test for https://github.com/dart-lang/sdk/issues/26094 |
2795 abstract class Base implements I1 {} | 2255 class A <S extends Returns<S>, T extends Returns<T>> { |
2796 | 2256 int test(bool b) { |
2797 class T1 extends Base { | 2257 S s; |
2798 /*severe:INVALID_METHOD_OVERRIDE*/m( | 2258 T t; |
2799 /*warning:INVALID_METHOD_OVERRIDE_NORMAL_PARAM_TYPE*/B a) {} | 2259 if (b) { |
2800 } | 2260 return /*warning:RETURN_OF_INVALID_TYPE*/b ? s : t; |
2801 '''); | 2261 } else { |
2802 }); | 2262 return /*warning:RETURN_OF_INVALID_TYPE*/s ?? t; |
2803 test('interface of concrete superclass', () { | 2263 } |
2804 checkFile(''' | 2264 } |
2805 class A {} | 2265 } |
2806 class B {} | 2266 |
2807 | 2267 class B<S, T extends S> { |
2808 abstract class I1 { | 2268 T t; |
2809 m(A a); | 2269 S s; |
2810 } | 2270 int test(bool b) { |
2811 | 2271 return /*warning:RETURN_OF_INVALID_TYPE*/b ? t : s; |
2812 class /*warning:NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_ONE*/B
ase | 2272 } |
2813 implements I1 {} | 2273 } |
2814 | 2274 |
2815 class T1 extends Base { | 2275 class C { |
2816 // not reported technically because if the class is concrete, | 2276 // Check that the least upper bound of two types with the same |
2817 // it should implement all its interfaces and hence it is | 2277 // class but different type arguments produces the pointwise |
2818 // sufficient to check overrides against it. | 2278 // least upper bound of the type arguments |
2819 m(/*warning:INVALID_METHOD_OVERRIDE_NORMAL_PARAM_TYPE*/B a) {} | 2279 int test1(bool b) { |
2820 } | 2280 List<int> li; |
2821 '''); | 2281 List<double> ld; |
2822 }); | 2282 return /*warning:RETURN_OF_INVALID_TYPE*/b ? li : ld; |
2823 }); | 2283 } |
2824 | 2284 // TODO(leafp): This case isn't handled yet. This test checks |
2825 group('mixin override of grand interface', () { | 2285 // the case where two related classes are instantiated with related |
2826 test('interface of interface of child', () { | 2286 // but different types. |
2827 checkFile(''' | 2287 Iterable<num> test2(bool b) { |
2828 class A {} | 2288 List<int> li; |
2829 class B {} | 2289 Iterable<double> id; |
2830 | 2290 int x = |
2831 abstract class I1 { | 2291 /*info:ASSIGNMENT_CAST should be warning:INVALID_ASSIGNMENT*/ |
2832 m(A a); | 2292 b ? li : id; |
2833 } | 2293 return /*warning:DOWN_CAST_COMPOSITE should be pass*/b ? li : id; |
2834 abstract class I2 implements I1 {} | 2294 } |
2835 | 2295 } |
2836 class M { | 2296 '''); |
2837 m(B a) {} | 2297 } |
2838 } | 2298 |
2839 | 2299 void test_loadLibrary() { |
2840 class /*warning:INCONSISTENT_METHOD_INHERITANCE*/T1 | 2300 addFile('''library lib1;''', name: '/lib1.dart'); |
2841 extends Object with /*severe:INVALID_METHOD_OVERRIDE*/M | 2301 checkFile(r''' |
2842 implements I2 {} | 2302 import 'lib1.dart' deferred as lib1; |
2843 '''); | 2303 import 'dart:async' show Future; |
2844 }); | 2304 main() { |
2845 test('superclass of interface of child', () { | 2305 Future f = lib1.loadLibrary(); |
2846 checkFile(''' | 2306 }'''); |
2847 class A {} | 2307 } |
2848 class B {} | 2308 |
2849 | 2309 void test_methodOverride() { |
2850 abstract class I1 { | 2310 checkFile(''' |
2851 m(A a); | 2311 class A {} |
2852 } | 2312 class B extends A {} |
2853 abstract class I2 extends I1 {} | 2313 class C extends B {} |
2854 | 2314 |
2855 class M { | 2315 class Base { |
2856 m(B a) {} | 2316 B m1(B a) => null; |
2857 } | 2317 B m2(B a) => null; |
2858 | 2318 B m3(B a) => null; |
2859 class /*warning:INCONSISTENT_METHOD_INHERITANCE*/T1 | 2319 B m4(B a) => null; |
2860 extends Object with /*severe:INVALID_METHOD_OVERRIDE*/M | 2320 B m5(B a) => null; |
2861 implements I2 {} | 2321 B m6(B a) => null; |
2862 '''); | 2322 } |
2863 }); | 2323 |
2864 test('mixin of interface of child', () { | 2324 class Child extends Base { |
2865 checkFile(''' | 2325 /*severe:INVALID_METHOD_OVERRIDE*/A m1(A value) => null; |
2866 class A {} | 2326 /*severe:INVALID_METHOD_OVERRIDE*/C m2(C value) => null; |
2867 class B {} | 2327 /*severe:INVALID_METHOD_OVERRIDE*/A m3(C value) => null; |
2868 | 2328 C m4(A value) => null; |
2869 abstract class M1 { | 2329 m5(value) => null; |
2870 m(A a); | 2330 /*severe:INVALID_METHOD_OVERRIDE*/dynamic m6(dynamic value) => null; |
2871 } | 2331 } |
2872 abstract class I2 extends Object with M1 {} | 2332 '''); |
2873 | 2333 } |
2874 class M { | 2334 |
2875 m(B a) {} | 2335 void test_methodOverride_fuzzyArrows() { |
2876 } | 2336 checkFile(''' |
2877 | 2337 abstract class A { |
2878 class /*warning:INCONSISTENT_METHOD_INHERITANCE*/T1 | 2338 bool operator ==(Object object); |
2879 extends Object with /*severe:INVALID_METHOD_OVERRIDE*/M | 2339 } |
2880 implements I2 {} | 2340 |
2881 '''); | 2341 class B implements A {} |
2882 }); | 2342 |
2883 test('interface of abstract superclass', () { | 2343 class F { |
2884 checkFile(''' | 2344 void f(x) {} |
2885 class A {} | 2345 void g(int x) {} |
2886 class B {} | 2346 } |
2887 | 2347 |
2888 abstract class I1 { | 2348 class G extends F { |
2889 m(A a); | 2349 /*severe:INVALID_METHOD_OVERRIDE*/void f(int x) {} |
2890 } | 2350 void g(dynamic x) {} |
2891 abstract class Base implements I1 {} | 2351 } |
2892 | 2352 |
2893 class M { | 2353 class H implements F { |
2894 m(B a) {} | 2354 /*severe:INVALID_METHOD_OVERRIDE*/void f(int x) {} |
2895 } | 2355 void g(dynamic x) {} |
2896 | 2356 } |
2897 class /*warning:INCONSISTENT_METHOD_INHERITANCE*/T1 extends Base | 2357 '''); |
2898 with /*severe:INVALID_METHOD_OVERRIDE*/M {} | 2358 } |
2899 '''); | 2359 |
2900 }); | 2360 void test_mixinOverrideOfGrandInterface_interfaceOfAbstractSuperclass() { |
2901 test('interface of concrete superclass', () { | 2361 checkFile(''' |
2902 checkFile(''' | 2362 class A {} |
2903 class A {} | 2363 class B {} |
2904 class B {} | 2364 |
2905 | 2365 abstract class I1 { |
2906 abstract class I1 { | 2366 m(A a); |
2907 m(A a); | 2367 } |
2908 } | 2368 abstract class Base implements I1 {} |
2909 | 2369 |
2910 class /*warning:NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_ONE*/B
ase | 2370 class M { |
2911 implements I1 {} | 2371 m(B a) {} |
2912 | 2372 } |
2913 class M { | 2373 |
2914 m(B a) {} | 2374 class /*warning:INCONSISTENT_METHOD_INHERITANCE*/T1 extends Base |
2915 } | 2375 with /*severe:INVALID_METHOD_OVERRIDE*/M {} |
2916 | 2376 '''); |
2917 class /*warning:INCONSISTENT_METHOD_INHERITANCE*/T1 extends Base | 2377 } |
2918 with M {} | 2378 |
2919 '''); | 2379 void test_mixinOverrideOfGrandInterface_interfaceOfConcreteSuperclass() { |
2920 }); | 2380 checkFile(''' |
2921 }); | 2381 class A {} |
2922 | 2382 class B {} |
2923 group('superclass override of grand interface', () { | 2383 |
2924 test('interface of interface of child', () { | 2384 abstract class I1 { |
2925 checkFile(''' | 2385 m(A a); |
2926 class A {} | 2386 } |
2927 class B {} | 2387 |
2928 | 2388 class /*warning:NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_ONE*/Base |
2929 abstract class I1 { | 2389 implements I1 {} |
2930 m(A a); | 2390 |
2931 } | 2391 class M { |
2932 abstract class I2 implements I1 {} | 2392 m(B a) {} |
2933 | 2393 } |
2934 class Base { | 2394 |
2935 m(B a) {} | 2395 class /*warning:INCONSISTENT_METHOD_INHERITANCE*/T1 extends Base |
2936 } | 2396 with M {} |
2937 | 2397 '''); |
2938 class /*warning:INCONSISTENT_METHOD_INHERITANCE*/T1 | 2398 } |
2939 /*severe:INVALID_METHOD_OVERRIDE*/extends Base implements I2 {
} | 2399 |
2940 '''); | 2400 void test_mixinOverrideOfGrandInterface_interfaceOfInterfaceOfChild() { |
2941 }); | 2401 checkFile(''' |
2942 test('superclass of interface of child', () { | 2402 class A {} |
2943 checkFile(''' | 2403 class B {} |
2944 class A {} | 2404 |
2945 class B {} | 2405 abstract class I1 { |
2946 | 2406 m(A a); |
2947 abstract class I1 { | 2407 } |
2948 m(A a); | 2408 abstract class I2 implements I1 {} |
2949 } | 2409 |
2950 abstract class I2 extends I1 {} | 2410 class M { |
2951 | 2411 m(B a) {} |
2952 class Base { | 2412 } |
2953 m(B a) {} | 2413 |
2954 } | 2414 class /*warning:INCONSISTENT_METHOD_INHERITANCE*/T1 |
2955 | 2415 extends Object with /*severe:INVALID_METHOD_OVERRIDE*/M |
2956 class /*warning:INCONSISTENT_METHOD_INHERITANCE*/T1 | 2416 implements I2 {} |
2957 /*severe:INVALID_METHOD_OVERRIDE*/extends Base | 2417 '''); |
2958 implements I2 {} | 2418 } |
2959 '''); | 2419 |
2960 }); | 2420 void test_mixinOverrideOfGrandInterface_mixinOfInterfaceOfChild() { |
2961 test('mixin of interface of child', () { | 2421 checkFile(''' |
2962 checkFile(''' | 2422 class A {} |
2963 class A {} | 2423 class B {} |
2964 class B {} | 2424 |
2965 | 2425 abstract class M1 { |
2966 abstract class M1 { | 2426 m(A a); |
2967 m(A a); | 2427 } |
2968 } | 2428 abstract class I2 extends Object with M1 {} |
2969 abstract class I2 extends Object with M1 {} | 2429 |
2970 | 2430 class M { |
2971 class Base { | 2431 m(B a) {} |
2972 m(B a) {} | 2432 } |
2973 } | 2433 |
2974 | 2434 class /*warning:INCONSISTENT_METHOD_INHERITANCE*/T1 |
2975 class /*warning:INCONSISTENT_METHOD_INHERITANCE*/T1 | 2435 extends Object with /*severe:INVALID_METHOD_OVERRIDE*/M |
2976 /*severe:INVALID_METHOD_OVERRIDE*/extends Base | 2436 implements I2 {} |
2977 implements I2 {} | 2437 '''); |
2978 '''); | 2438 } |
2979 }); | 2439 |
2980 test('interface of abstract superclass', () { | 2440 void test_mixinOverrideOfGrandInterface_superclassOfInterfaceOfChild() { |
2981 checkFile(''' | 2441 checkFile(''' |
2982 class A {} | 2442 class A {} |
2983 class B {} | 2443 class B {} |
2984 | 2444 |
2985 abstract class I1 { | 2445 abstract class I1 { |
2986 m(A a); | 2446 m(A a); |
2987 } | 2447 } |
2988 | 2448 abstract class I2 extends I1 {} |
2989 abstract class Base implements I1 { | 2449 |
2990 /*severe:INVALID_METHOD_OVERRIDE*/m( | 2450 class M { |
2991 /*warning:INVALID_METHOD_OVERRIDE_NORMAL_PARAM_TYPE*/B a) {} | 2451 m(B a) {} |
2992 } | 2452 } |
2993 | 2453 |
2994 class T1 extends Base { | 2454 class /*warning:INCONSISTENT_METHOD_INHERITANCE*/T1 |
2995 // we consider the base class incomplete because it is | 2455 extends Object with /*severe:INVALID_METHOD_OVERRIDE*/M |
2996 // abstract, so we report the error here too. | 2456 implements I2 {} |
2997 // TODO(sigmund): consider tracking overrides in a fine-grain | 2457 '''); |
2998 // manner, then this and the double-overrides would not be | 2458 } |
2999 // reported. | 2459 |
3000 /*severe:INVALID_METHOD_OVERRIDE*/m(B a) {} | 2460 void |
3001 } | 2461 test_noDuplicateReportsFromOverridingInterfaces_baseTypeAndMixinOverrideSa
meMethodInInterface() { |
3002 '''); | 2462 checkFile(''' |
3003 }); | 2463 class A {} |
3004 test('interface of concrete superclass', () { | 2464 class B {} |
3005 checkFile(''' | 2465 |
3006 class A {} | 2466 abstract class I1 { |
3007 class B {} | 2467 m(A a); |
3008 | 2468 } |
3009 abstract class I1 { | 2469 |
3010 m(A a); | 2470 class Base { |
3011 } | 2471 m(B a) {} |
3012 | 2472 } |
3013 class Base implements I1 { | 2473 |
3014 /*severe:INVALID_METHOD_OVERRIDE*/m( | 2474 class M { |
3015 /*warning:INVALID_METHOD_OVERRIDE_NORMAL_PARAM_TYPE*/B a) {} | 2475 m(B a) {} |
3016 } | 2476 } |
3017 | 2477 |
3018 class T1 extends Base { | 2478 // Here we want to report both, because the error location is |
3019 m(B a) {} | 2479 // different. |
3020 } | 2480 // TODO(sigmund): should we merge these as well? |
3021 '''); | 2481 class /*warning:INCONSISTENT_METHOD_INHERITANCE*/T1 |
3022 }); | 2482 /*severe:INVALID_METHOD_OVERRIDE*/extends Base |
3023 }); | 2483 with /*severe:INVALID_METHOD_OVERRIDE*/M |
3024 | 2484 implements I1 {} |
3025 group('no duplicate reports from overriding interfaces', () { | 2485 '''); |
3026 test('type overrides same method in multiple interfaces', () { | 2486 } |
3027 checkFile(''' | 2487 |
3028 class A {} | 2488 void |
3029 class B {} | 2489 test_noDuplicateReportsFromOverridingInterfaces_twoGrandTypesOverrideSameM
ethodInInterface() { |
3030 | 2490 checkFile(''' |
3031 abstract class I1 { | 2491 class A {} |
3032 m(A a); | 2492 class B {} |
3033 } | 2493 |
3034 abstract class I2 implements I1 { | 2494 abstract class I1 { |
3035 m(A a); | 2495 m(A a); |
3036 } | 2496 } |
3037 | 2497 |
3038 class Base {} | 2498 class Grandparent { |
3039 | 2499 m(B a) {} |
3040 class T1 implements I2 { | 2500 } |
3041 /*severe:INVALID_METHOD_OVERRIDE*/m( | 2501 |
3042 /*warning:INVALID_METHOD_OVERRIDE_NORMAL_PARAM_TYPE*/B a) {} | 2502 class Parent1 extends Grandparent { |
3043 } | 2503 m(B a) {} |
3044 '''); | 2504 } |
3045 }); | 2505 class Parent2 extends Grandparent {} |
3046 | 2506 |
3047 test('type and base type override same method in interface', () { | 2507 // Note: otherwise both errors would be reported on this line |
3048 checkFile(''' | 2508 class /*warning:INCONSISTENT_METHOD_INHERITANCE*/T1 |
3049 class A {} | 2509 /*severe:INVALID_METHOD_OVERRIDE*/extends Parent1 |
3050 class B {} | 2510 implements I1 {} |
3051 | 2511 class /*warning:INCONSISTENT_METHOD_INHERITANCE*/T2 |
3052 abstract class I1 { | 2512 /*severe:INVALID_METHOD_OVERRIDE*/extends Parent2 |
3053 m(A a); | 2513 implements I1 {} |
3054 } | 2514 '''); |
3055 | 2515 } |
3056 class Base { | 2516 |
3057 m(B a) {} | 2517 void |
3058 } | 2518 test_noDuplicateReportsFromOverridingInterfaces_twoMixinsOverrideSameMetho
dInInterface() { |
3059 | 2519 checkFile(''' |
3060 // Note: no error reported in `extends Base` to avoid duplicating | 2520 class A {} |
3061 // the error in T1. | 2521 class B {} |
3062 class T1 extends Base implements I1 { | 2522 |
3063 /*severe:INVALID_METHOD_OVERRIDE*/m( | 2523 abstract class I1 { |
3064 /*warning:INVALID_METHOD_OVERRIDE_NORMAL_PARAM_TYPE*/B a) {} | 2524 m(A a); |
3065 } | 2525 } |
3066 | 2526 |
3067 // If there is no error in the class, we do report the error at | 2527 class M1 { |
3068 // the base class: | 2528 m(B a) {} |
3069 class /*warning:INCONSISTENT_METHOD_INHERITANCE*/T2 | 2529 } |
3070 /*severe:INVALID_METHOD_OVERRIDE*/extends Base | 2530 |
3071 implements I1 {} | 2531 class M2 { |
3072 '''); | 2532 m(B a) {} |
3073 }); | 2533 } |
3074 | 2534 |
3075 test('type and mixin override same method in interface', () { | 2535 // Here we want to report both, because the error location is |
3076 checkFile(''' | 2536 // different. |
3077 class A {} | 2537 // TODO(sigmund): should we merge these as well? |
3078 class B {} | 2538 class /*warning:INCONSISTENT_METHOD_INHERITANCE*/T1 extends Object |
3079 | 2539 with /*severe:INVALID_METHOD_OVERRIDE*/M1, |
3080 abstract class I1 { | 2540 /*severe:INVALID_METHOD_OVERRIDE*/M2 |
3081 m(A a); | 2541 implements I1 {} |
3082 } | 2542 '''); |
3083 | 2543 } |
3084 class M { | 2544 |
3085 m(B a) {} | 2545 void |
3086 } | 2546 test_noDuplicateReportsFromOverridingInterfaces_typeAndBaseTypeOverrideSam
eMethodInInterface() { |
3087 | 2547 checkFile(''' |
3088 class T1 extends Object with M implements I1 { | 2548 class A {} |
3089 /*severe:INVALID_METHOD_OVERRIDE*/m( | 2549 class B {} |
3090 /*warning:INVALID_METHOD_OVERRIDE_NORMAL_PARAM_TYPE*/B a) {} | 2550 |
3091 } | 2551 abstract class I1 { |
3092 | 2552 m(A a); |
3093 class /*warning:INCONSISTENT_METHOD_INHERITANCE*/T2 | 2553 } |
3094 extends Object with /*severe:INVALID_METHOD_OVERRIDE*/M | 2554 |
3095 implements I1 {} | 2555 class Base { |
3096 '''); | 2556 m(B a) {} |
3097 }); | 2557 } |
3098 | 2558 |
3099 test('two grand types override same method in interface', () { | 2559 // Note: no error reported in `extends Base` to avoid duplicating |
3100 checkFile(''' | 2560 // the error in T1. |
3101 class A {} | 2561 class T1 extends Base implements I1 { |
3102 class B {} | 2562 /*severe:INVALID_METHOD_OVERRIDE*/m( |
3103 | 2563 /*warning:INVALID_METHOD_OVERRIDE_NORMAL_PARAM_TYPE*/B a) {} |
3104 abstract class I1 { | 2564 } |
3105 m(A a); | 2565 |
3106 } | 2566 // If there is no error in the class, we do report the error at |
3107 | 2567 // the base class: |
3108 class Grandparent { | 2568 class /*warning:INCONSISTENT_METHOD_INHERITANCE*/T2 |
3109 m(B a) {} | 2569 /*severe:INVALID_METHOD_OVERRIDE*/extends Base |
3110 } | 2570 implements I1 {} |
3111 | 2571 '''); |
3112 class Parent1 extends Grandparent { | 2572 } |
3113 m(B a) {} | 2573 |
3114 } | 2574 void |
3115 class Parent2 extends Grandparent {} | 2575 test_noDuplicateReportsFromOverridingInterfaces_typeAndMixinOverrideSameMe
thodInInterface() { |
3116 | 2576 checkFile(''' |
3117 // Note: otherwise both errors would be reported on this line | 2577 class A {} |
3118 class /*warning:INCONSISTENT_METHOD_INHERITANCE*/T1 | 2578 class B {} |
3119 /*severe:INVALID_METHOD_OVERRIDE*/extends Parent1 | 2579 |
3120 implements I1 {} | 2580 abstract class I1 { |
3121 class /*warning:INCONSISTENT_METHOD_INHERITANCE*/T2 | 2581 m(A a); |
3122 /*severe:INVALID_METHOD_OVERRIDE*/extends Parent2 | 2582 } |
3123 implements I1 {} | 2583 |
3124 '''); | 2584 class M { |
3125 }); | 2585 m(B a) {} |
3126 | 2586 } |
3127 test('two mixins override same method in interface', () { | 2587 |
3128 checkFile(''' | 2588 class T1 extends Object with M implements I1 { |
3129 class A {} | 2589 /*severe:INVALID_METHOD_OVERRIDE*/m( |
3130 class B {} | 2590 /*warning:INVALID_METHOD_OVERRIDE_NORMAL_PARAM_TYPE*/B a) {} |
3131 | 2591 } |
3132 abstract class I1 { | 2592 |
3133 m(A a); | 2593 class /*warning:INCONSISTENT_METHOD_INHERITANCE*/T2 |
3134 } | 2594 extends Object with /*severe:INVALID_METHOD_OVERRIDE*/M |
3135 | 2595 implements I1 {} |
3136 class M1 { | 2596 '''); |
3137 m(B a) {} | 2597 } |
3138 } | 2598 |
3139 | 2599 void |
3140 class M2 { | 2600 test_noDuplicateReportsFromOverridingInterfaces_typeOverridesSomeMethodInM
ultipleInterfaces() { |
3141 m(B a) {} | 2601 checkFile(''' |
3142 } | 2602 class A {} |
3143 | 2603 class B {} |
3144 // Here we want to report both, because the error location is | 2604 |
3145 // different. | 2605 abstract class I1 { |
3146 // TODO(sigmund): should we merge these as well? | 2606 m(A a); |
3147 class /*warning:INCONSISTENT_METHOD_INHERITANCE*/T1 extends Object | 2607 } |
3148 with /*severe:INVALID_METHOD_OVERRIDE*/M1, | 2608 abstract class I2 implements I1 { |
3149 /*severe:INVALID_METHOD_OVERRIDE*/M2 | 2609 m(A a); |
3150 implements I1 {} | 2610 } |
3151 '''); | 2611 |
3152 }); | 2612 class Base {} |
3153 | 2613 |
3154 test('base type and mixin override same method in interface', () { | 2614 class T1 implements I2 { |
3155 checkFile(''' | 2615 /*severe:INVALID_METHOD_OVERRIDE*/m( |
3156 class A {} | 2616 /*warning:INVALID_METHOD_OVERRIDE_NORMAL_PARAM_TYPE*/B a) {} |
3157 class B {} | 2617 } |
3158 | 2618 '''); |
3159 abstract class I1 { | 2619 } |
3160 m(A a); | 2620 |
3161 } | 2621 void test_nullCoalescingOperator() { |
3162 | 2622 checkFile(''' |
3163 class Base { | 2623 class A {} |
3164 m(B a) {} | 2624 class C<T> {} |
3165 } | 2625 main() { |
3166 | 2626 A a, b; |
3167 class M { | 2627 a ??= new A(); |
3168 m(B a) {} | 2628 b = b ?? new A(); |
3169 } | 2629 |
3170 | 2630 // downwards inference |
3171 // Here we want to report both, because the error location is | 2631 C<int> c, d; |
3172 // different. | 2632 c ??= /*info:INFERRED_TYPE_ALLOCATION*/new C(); |
3173 // TODO(sigmund): should we merge these as well? | 2633 d = d ?? /*info:INFERRED_TYPE_ALLOCATION*/new C(); |
3174 class /*warning:INCONSISTENT_METHOD_INHERITANCE*/T1 | 2634 } |
3175 /*severe:INVALID_METHOD_OVERRIDE*/extends Base | 2635 '''); |
3176 with /*severe:INVALID_METHOD_OVERRIDE*/M | 2636 } |
3177 implements I1 {} | 2637 |
3178 '''); | 2638 void test_privateOverride() { |
3179 }); | 2639 addFile( |
3180 }); | 2640 ''' |
3181 | 2641 import 'main.dart' as main; |
3182 test('invalid runtime checks', () { | 2642 |
3183 checkFile(''' | 2643 class Base { |
3184 typedef int I2I(int x); | 2644 var f1; |
3185 typedef int D2I(x); | 2645 var _f2; |
3186 typedef int II2I(int x, int y); | 2646 var _f3; |
3187 typedef int DI2I(x, int y); | 2647 get _f4 => null; |
3188 typedef int ID2I(int x, y); | 2648 |
3189 typedef int DD2I(x, y); | 2649 int _m1() => null; |
3190 | 2650 } |
3191 typedef I2D(int x); | 2651 |
3192 typedef D2D(x); | 2652 class GrandChild extends main.Child { |
3193 typedef II2D(int x, int y); | 2653 /*severe:INVALID_FIELD_OVERRIDE*/var _f2; |
3194 typedef DI2D(x, int y); | 2654 /*severe:INVALID_FIELD_OVERRIDE*/var _f3; |
3195 typedef ID2D(int x, y); | 2655 var _f4; |
3196 typedef DD2D(x, y); | 2656 |
3197 | 2657 /*severe:INVALID_METHOD_OVERRIDE*/String |
3198 int foo(int x) => x; | 2658 /*warning:INVALID_METHOD_OVERRIDE_RETURN_TYPE*/_m1() => null; |
3199 int bar(int x, int y) => x + y; | 2659 } |
3200 | 2660 ''', |
3201 void main() { | 2661 name: '/helper.dart'); |
3202 bool b; | 2662 checkFile(''' |
3203 b = /*info:NON_GROUND_TYPE_CHECK_INFO*/foo is I2I; | 2663 import 'helper.dart' as helper; |
3204 b = /*info:NON_GROUND_TYPE_CHECK_INFO*/foo is D2I; | 2664 |
3205 b = /*info:NON_GROUND_TYPE_CHECK_INFO*/foo is I2D; | 2665 class Child extends helper.Base { |
3206 b = foo is D2D; | 2666 /*severe:INVALID_FIELD_OVERRIDE*/var f1; |
3207 | 2667 var _f2; |
3208 b = /*info:NON_GROUND_TYPE_CHECK_INFO*/bar is II2I; | 2668 var _f4; |
3209 b = /*info:NON_GROUND_TYPE_CHECK_INFO*/bar is DI2I; | 2669 |
3210 b = /*info:NON_GROUND_TYPE_CHECK_INFO*/bar is ID2I; | 2670 String _m1() => null; |
3211 b = /*info:NON_GROUND_TYPE_CHECK_INFO*/bar is II2D; | 2671 } |
3212 b = /*info:NON_GROUND_TYPE_CHECK_INFO*/bar is DD2I; | 2672 '''); |
3213 b = /*info:NON_GROUND_TYPE_CHECK_INFO*/bar is DI2D; | 2673 } |
3214 b = /*info:NON_GROUND_TYPE_CHECK_INFO*/bar is ID2D; | 2674 |
3215 b = bar is DD2D; | 2675 void test_redirectingConstructor() { |
3216 | 2676 checkFile(''' |
3217 // For as, the validity of checks is deferred to runtime. | 2677 class A { |
3218 Function f; | 2678 A(A x) {} |
3219 f = foo as I2I; | 2679 A.two() : this(/*warning:ARGUMENT_TYPE_NOT_ASSIGNABLE*/3); |
3220 f = foo as D2I; | 2680 } |
3221 f = foo as I2D; | 2681 '''); |
3222 f = foo as D2D; | 2682 } |
3223 | 2683 |
3224 f = bar as II2I; | 2684 void test_relaxedCasts() { |
3225 f = bar as DI2I; | 2685 checkFile(''' |
3226 f = bar as ID2I; | 2686 class A {} |
3227 f = bar as II2D; | 2687 |
3228 f = bar as DD2I; | 2688 class L<T> {} |
3229 f = bar as DI2D; | 2689 class M<T> extends L<T> {} |
3230 f = bar as ID2D; | 2690 // L<dynamic|Object> |
3231 f = bar as DD2D; | 2691 // / \ |
3232 } | 2692 // M<dynamic|Object> L<A> |
3233 '''); | 2693 // \ / |
3234 }); | 2694 // M<A> |
3235 | 2695 // In normal Dart, there are additional edges |
3236 group('function modifiers', () { | 2696 // from M<A> to M<dynamic> |
3237 test('async', () { | 2697 // from L<A> to M<dynamic> |
3238 checkFile(''' | 2698 // from L<A> to L<dynamic> |
3239 import 'dart:async'; | 2699 void main() { |
3240 import 'dart:math' show Random; | 2700 L lOfDs; |
3241 | 2701 L<Object> lOfOs; |
3242 dynamic x; | 2702 L<A> lOfAs; |
3243 | 2703 |
3244 foo1() async => x; | 2704 M mOfDs; |
3245 Future foo2() async => x; | 2705 M<Object> mOfOs; |
3246 Future<int> foo3() async => /*info:DYNAMIC_CAST*/x; | 2706 M<A> mOfAs; |
3247 Future<int> foo4() async => new Future<int>.value(/*info:DYNAMIC_CAST*/x
); | 2707 |
3248 Future<int> foo5() async => | 2708 { |
3249 /*warning:RETURN_OF_INVALID_TYPE*/new Future<String>.value(/*info:DY
NAMIC_CAST*/x); | 2709 lOfDs = mOfDs; |
3250 | 2710 lOfDs = mOfOs; |
3251 bar1() async { return x; } | 2711 lOfDs = mOfAs; |
3252 Future bar2() async { return x; } | 2712 lOfDs = lOfDs; |
3253 Future<int> bar3() async { return /*info:DYNAMIC_CAST*/x; } | 2713 lOfDs = lOfOs; |
3254 Future<int> bar4() async { return new Future<int>.value(/*info:DYNAMIC_C
AST*/x); } | 2714 lOfDs = lOfAs; |
3255 Future<int> bar5() async { | 2715 lOfDs = new L(); // Reset type propagation. |
3256 return /*warning:RETURN_OF_INVALID_TYPE*/new Future<String>.value(/*in
fo:DYNAMIC_CAST*/x); | 2716 } |
3257 } | 2717 { |
3258 | 2718 lOfOs = mOfDs; |
3259 int y; | 2719 lOfOs = mOfOs; |
3260 Future<int> z; | 2720 lOfOs = mOfAs; |
3261 | 2721 lOfOs = lOfDs; |
3262 baz() async { | 2722 lOfOs = lOfOs; |
3263 int a = /*info:DYNAMIC_CAST*/await x; | 2723 lOfOs = lOfAs; |
3264 int b = await y; | 2724 lOfOs = new L<Object>(); // Reset type propagation. |
3265 int c = await z; | 2725 } |
3266 String d = /*warning:INVALID_ASSIGNMENT*/await z; | 2726 { |
3267 } | 2727 lOfAs = /*warning:DOWN_CAST_COMPOSITE*/mOfDs; |
3268 | 2728 lOfAs = /*warning:INVALID_ASSIGNMENT*/mOfOs; |
3269 Future<bool> get issue_264 async { | 2729 lOfAs = mOfAs; |
3270 await 42; | 2730 lOfAs = /*warning:DOWN_CAST_COMPOSITE*/lOfDs; |
3271 if (new Random().nextBool()) { | 2731 lOfAs = /*info:DOWN_CAST_IMPLICIT*/lOfOs; |
3272 return true; | 2732 lOfAs = lOfAs; |
3273 } else { | 2733 lOfAs = new L<A>(); // Reset type propagation. |
3274 return new Future<bool>.value(false); | 2734 } |
3275 } | 2735 { |
3276 } | 2736 mOfDs = mOfDs; |
3277 '''); | 2737 mOfDs = mOfOs; |
3278 }); | 2738 mOfDs = mOfAs; |
3279 | 2739 mOfDs = /*info:DOWN_CAST_IMPLICIT*/lOfDs; |
3280 test('async*', () { | 2740 mOfDs = /*info:DOWN_CAST_IMPLICIT*/lOfOs; |
3281 checkFile(''' | 2741 mOfDs = /*warning:DOWN_CAST_COMPOSITE*/lOfAs; |
3282 import 'dart:async'; | 2742 mOfDs = new M(); // Reset type propagation. |
3283 | 2743 } |
3284 dynamic x; | 2744 { |
3285 | 2745 mOfOs = mOfDs; |
3286 bar1() async* { yield x; } | 2746 mOfOs = mOfOs; |
3287 Stream bar2() async* { yield x; } | 2747 mOfOs = mOfAs; |
3288 Stream<int> bar3() async* { yield /*info:DYNAMIC_CAST*/x; } | 2748 mOfOs = /*info:DOWN_CAST_IMPLICIT*/lOfDs; |
3289 Stream<int> bar4() async* { yield /*warning:YIELD_OF_INVALID_TYPE*/new S
tream<int>(); } | 2749 mOfOs = /*info:DOWN_CAST_IMPLICIT*/lOfOs; |
3290 | 2750 mOfOs = /*warning:INVALID_ASSIGNMENT*/lOfAs; |
3291 baz1() async* { yield* /*info:DYNAMIC_CAST*/x; } | 2751 mOfOs = new M<Object>(); // Reset type propagation. |
3292 Stream baz2() async* { yield* /*info:DYNAMIC_CAST*/x; } | 2752 } |
3293 Stream<int> baz3() async* { yield* /*warning:DOWN_CAST_COMPOSITE*/x; } | 2753 { |
3294 Stream<int> baz4() async* { yield* new Stream<int>(); } | 2754 mOfAs = /*warning:DOWN_CAST_COMPOSITE*/mOfDs; |
3295 Stream<int> baz5() async* { yield* /*info:INFERRED_TYPE_ALLOCATION*/new
Stream(); } | 2755 mOfAs = /*info:DOWN_CAST_IMPLICIT*/mOfOs; |
3296 '''); | 2756 mOfAs = mOfAs; |
3297 }); | 2757 mOfAs = /*warning:DOWN_CAST_COMPOSITE*/lOfDs; |
3298 | 2758 mOfAs = /*info:DOWN_CAST_IMPLICIT*/lOfOs; |
3299 test('sync*', () { | 2759 mOfAs = /*info:DOWN_CAST_IMPLICIT*/lOfAs; |
3300 checkFile(''' | 2760 } |
3301 dynamic x; | 2761 } |
3302 | 2762 '''); |
3303 bar1() sync* { yield x; } | 2763 } |
3304 Iterable bar2() sync* { yield x; } | 2764 |
3305 Iterable<int> bar3() sync* { yield /*info:DYNAMIC_CAST*/x; } | 2765 void test_setterOverride_fuzzyArrows() { |
3306 Iterable<int> bar4() sync* { yield /*warning:YIELD_OF_INVALID_TYPE*/bar3
(); } | 2766 checkFile(''' |
3307 | 2767 typedef void ToVoid<T>(T x); |
3308 baz1() sync* { yield* /*info:DYNAMIC_CAST*/x; } | 2768 class F { |
3309 Iterable baz2() sync* { yield* /*info:DYNAMIC_CAST*/x; } | 2769 void set f(ToVoid<dynamic> x) {} |
3310 Iterable<int> baz3() sync* { yield* /*warning:DOWN_CAST_COMPOSITE*/x; } | 2770 void set g(ToVoid<int> x) {} |
3311 Iterable<int> baz4() sync* { yield* bar3(); } | 2771 void set h(dynamic x) {} |
3312 Iterable<int> baz5() sync* { yield* /*info:INFERRED_TYPE_ALLOCATION*/new
List(); } | 2772 void set i(int x) {} |
3313 '''); | 2773 } |
3314 }); | 2774 |
3315 }); | 2775 class G extends F { |
3316 } | 2776 /*severe:INVALID_METHOD_OVERRIDE*/void set f(ToVoid<int> x) {} |
| 2777 void set g(ToVoid<dynamic> x) {} |
| 2778 void set h(int x) {} |
| 2779 /*severe:INVALID_METHOD_OVERRIDE*/void set i(dynamic x) {} |
| 2780 } |
| 2781 |
| 2782 class H implements F { |
| 2783 /*severe:INVALID_METHOD_OVERRIDE*/void set f(ToVoid<int> x) {} |
| 2784 void set g(ToVoid<dynamic> x) {} |
| 2785 void set h(int x) {} |
| 2786 /*severe:INVALID_METHOD_OVERRIDE*/void set i(dynamic x) {} |
| 2787 } |
| 2788 '''); |
| 2789 } |
| 2790 |
| 2791 void test_setterReturnTypes() { |
| 2792 checkFile(''' |
| 2793 void voidFn() => null; |
| 2794 class A { |
| 2795 set a(y) => 4; |
| 2796 set b(y) => voidFn(); |
| 2797 void set c(y) => /*warning:RETURN_OF_INVALID_TYPE*/4; |
| 2798 void set d(y) => voidFn(); |
| 2799 /*warning:NON_VOID_RETURN_FOR_SETTER*/int set e(y) => 4; |
| 2800 /*warning:NON_VOID_RETURN_FOR_SETTER*/int set f(y) => |
| 2801 /*warning:RETURN_OF_INVALID_TYPE*/voidFn(); |
| 2802 set g(y) {return /*warning:RETURN_OF_INVALID_TYPE*/4;} |
| 2803 void set h(y) {return /*warning:RETURN_OF_INVALID_TYPE*/4;} |
| 2804 /*warning:NON_VOID_RETURN_FOR_SETTER*/int set i(y) {return 4;} |
| 2805 } |
| 2806 '''); |
| 2807 } |
| 2808 |
| 2809 void test_setterSetterOverride() { |
| 2810 checkFile(''' |
| 2811 class A {} |
| 2812 class B extends A {} |
| 2813 class C extends B {} |
| 2814 |
| 2815 abstract class Base { |
| 2816 void set f1(B value); |
| 2817 void set f2(B value); |
| 2818 void set f3(B value); |
| 2819 void set f4(B value); |
| 2820 void set f5(B value); |
| 2821 } |
| 2822 |
| 2823 class Child extends Base { |
| 2824 void set f1(A value) {} |
| 2825 /*severe:INVALID_METHOD_OVERRIDE*/void set f2(C value) {} |
| 2826 void set f3(value) {} |
| 2827 /*severe:INVALID_METHOD_OVERRIDE*/void set f4(dynamic value) {} |
| 2828 set f5(B value) {} |
| 2829 } |
| 2830 '''); |
| 2831 } |
| 2832 |
| 2833 void test_superCallPlacement() { |
| 2834 checkFile(''' |
| 2835 class Base { |
| 2836 var x; |
| 2837 Base() : x = print('Base.1') { print('Base.2'); } |
| 2838 } |
| 2839 |
| 2840 class Derived extends Base { |
| 2841 var y, z; |
| 2842 Derived() |
| 2843 : y = print('Derived.1'), |
| 2844 /*severe:INVALID_SUPER_INVOCATION*/super(), |
| 2845 z = print('Derived.2') { |
| 2846 print('Derived.3'); |
| 2847 } |
| 2848 } |
| 2849 |
| 2850 class Valid extends Base { |
| 2851 var y, z; |
| 2852 Valid() |
| 2853 : y = print('Valid.1'), |
| 2854 z = print('Valid.2'), |
| 2855 super() { |
| 2856 print('Valid.3'); |
| 2857 } |
| 2858 } |
| 2859 |
| 2860 class AlsoValid extends Base { |
| 2861 AlsoValid() : super(); |
| 2862 } |
| 2863 |
| 2864 main() => new Derived(); |
| 2865 '''); |
| 2866 } |
| 2867 |
| 2868 void test_superclassOverrideOfGrandInterface_interfaceOfAbstractSuperclass() { |
| 2869 checkFile(''' |
| 2870 class A {} |
| 2871 class B {} |
| 2872 |
| 2873 abstract class I1 { |
| 2874 m(A a); |
| 2875 } |
| 2876 |
| 2877 abstract class Base implements I1 { |
| 2878 /*severe:INVALID_METHOD_OVERRIDE*/m( |
| 2879 /*warning:INVALID_METHOD_OVERRIDE_NORMAL_PARAM_TYPE*/B a) {} |
| 2880 } |
| 2881 |
| 2882 class T1 extends Base { |
| 2883 // we consider the base class incomplete because it is |
| 2884 // abstract, so we report the error here too. |
| 2885 // TODO(sigmund): consider tracking overrides in a fine-grain |
| 2886 // manner, then this and the double-overrides would not be |
| 2887 // reported. |
| 2888 /*severe:INVALID_METHOD_OVERRIDE*/m(B a) {} |
| 2889 } |
| 2890 '''); |
| 2891 } |
| 2892 |
| 2893 void test_superclassOverrideOfGrandInterface_interfaceOfConcreteSuperclass() { |
| 2894 checkFile(''' |
| 2895 class A {} |
| 2896 class B {} |
| 2897 |
| 2898 abstract class I1 { |
| 2899 m(A a); |
| 2900 } |
| 2901 |
| 2902 class Base implements I1 { |
| 2903 /*severe:INVALID_METHOD_OVERRIDE*/m( |
| 2904 /*warning:INVALID_METHOD_OVERRIDE_NORMAL_PARAM_TYPE*/B a) {} |
| 2905 } |
| 2906 |
| 2907 class T1 extends Base { |
| 2908 m(B a) {} |
| 2909 } |
| 2910 '''); |
| 2911 } |
| 2912 |
| 2913 void test_superclassOverrideOfGrandInterface_interfaceOfInterfaceOfChild() { |
| 2914 checkFile(''' |
| 2915 class A {} |
| 2916 class B {} |
| 2917 |
| 2918 abstract class I1 { |
| 2919 m(A a); |
| 2920 } |
| 2921 abstract class I2 implements I1 {} |
| 2922 |
| 2923 class Base { |
| 2924 m(B a) {} |
| 2925 } |
| 2926 |
| 2927 class /*warning:INCONSISTENT_METHOD_INHERITANCE*/T1 |
| 2928 /*severe:INVALID_METHOD_OVERRIDE*/extends Base implements I2 {} |
| 2929 '''); |
| 2930 } |
| 2931 |
| 2932 void test_superclassOverrideOfGrandInterface_mixinOfInterfaceOfChild() { |
| 2933 checkFile(''' |
| 2934 class A {} |
| 2935 class B {} |
| 2936 |
| 2937 abstract class M1 { |
| 2938 m(A a); |
| 2939 } |
| 2940 abstract class I2 extends Object with M1 {} |
| 2941 |
| 2942 class Base { |
| 2943 m(B a) {} |
| 2944 } |
| 2945 |
| 2946 class /*warning:INCONSISTENT_METHOD_INHERITANCE*/T1 |
| 2947 /*severe:INVALID_METHOD_OVERRIDE*/extends Base |
| 2948 implements I2 {} |
| 2949 '''); |
| 2950 } |
| 2951 |
| 2952 void test_superclassOverrideOfGrandInterface_superclassOfInterfaceOfChild() { |
| 2953 checkFile(''' |
| 2954 class A {} |
| 2955 class B {} |
| 2956 |
| 2957 abstract class I1 { |
| 2958 m(A a); |
| 2959 } |
| 2960 abstract class I2 extends I1 {} |
| 2961 |
| 2962 class Base { |
| 2963 m(B a) {} |
| 2964 } |
| 2965 |
| 2966 class /*warning:INCONSISTENT_METHOD_INHERITANCE*/T1 |
| 2967 /*severe:INVALID_METHOD_OVERRIDE*/extends Base |
| 2968 implements I2 {} |
| 2969 '''); |
| 2970 } |
| 2971 |
| 2972 void test_superConstructor() { |
| 2973 checkFile(''' |
| 2974 class A { A(A x) {} } |
| 2975 class B extends A { |
| 2976 B() : super(/*warning:ARGUMENT_TYPE_NOT_ASSIGNABLE*/3); |
| 2977 } |
| 2978 '''); |
| 2979 } |
| 2980 |
| 2981 void test_ternaryOperator() { |
| 2982 checkFile(''' |
| 2983 abstract class Comparable<T> { |
| 2984 int compareTo(T other); |
| 2985 static int compare(Comparable a, Comparable b) => a.compareTo(b); |
| 2986 } |
| 2987 typedef int Comparator<T>(T a, T b); |
| 2988 |
| 2989 typedef bool _Predicate<T>(T value); |
| 2990 |
| 2991 class SplayTreeMap<K, V> { |
| 2992 Comparator<K> _comparator; |
| 2993 _Predicate _validKey; |
| 2994 |
| 2995 // The warning on assigning to _comparator is legitimate. Since K has |
| 2996 // no bound, all we know is that it's object. _comparator's function |
| 2997 // type is effectively: (Object, Object) -> int |
| 2998 // We are assigning it a fn of type: (Comparable, Comparable) -> int |
| 2999 // There's no telling if that will work. For example, consider: |
| 3000 // |
| 3001 // new SplayTreeMap<Uri>(); |
| 3002 // |
| 3003 // This would end up calling .compareTo() on a Uri, which doesn't |
| 3004 // define that since it doesn't implement Comparable. |
| 3005 SplayTreeMap([int compare(K key1, K key2), |
| 3006 bool isValidKey(potentialKey)]) |
| 3007 : _comparator = /*warning:DOWN_CAST_COMPOSITE*/(compare == null) ? Comparabl
e.compare : compare, |
| 3008 _validKey = (isValidKey != null) ? isValidKey : ((v) => true) { |
| 3009 _Predicate<Object> v = (isValidKey != null) |
| 3010 ? isValidKey : (/*info:INFERRED_TYPE_CLOSURE*/(_) => true); |
| 3011 |
| 3012 v = (isValidKey != null) |
| 3013 ? v : (/*info:INFERRED_TYPE_CLOSURE*/(_) => true); |
| 3014 } |
| 3015 } |
| 3016 void main() { |
| 3017 Object obj = 42; |
| 3018 dynamic dyn = 42; |
| 3019 int i = 42; |
| 3020 |
| 3021 // Check the boolean conversion of the condition. |
| 3022 print(/*warning:NON_BOOL_CONDITION*/i ? false : true); |
| 3023 print((/*info:DOWN_CAST_IMPLICIT*/obj) ? false : true); |
| 3024 print((/*info:DYNAMIC_CAST*/dyn) ? false : true); |
| 3025 } |
| 3026 '''); |
| 3027 } |
| 3028 |
| 3029 void test_typeCheckingLiterals() { |
| 3030 checkFile(''' |
| 3031 test() { |
| 3032 num n = 3; |
| 3033 int i = 3; |
| 3034 String s = "hello"; |
| 3035 { |
| 3036 List<int> l = <int>[i]; |
| 3037 l = <int>[/*warning:LIST_ELEMENT_TYPE_NOT_ASSIGNABLE*/s]; |
| 3038 l = <int>[/*info:DOWN_CAST_IMPLICIT*/n]; |
| 3039 l = <int>[i, /*info:DOWN_CAST_IMPLICIT*/n, /*warning:LIST_ELEMENT_TYPE_NOT_
ASSIGNABLE*/s]; |
| 3040 } |
| 3041 { |
| 3042 List l = /*info:INFERRED_TYPE_LITERAL*/[i]; |
| 3043 l = /*info:INFERRED_TYPE_LITERAL*/[s]; |
| 3044 l = /*info:INFERRED_TYPE_LITERAL*/[n]; |
| 3045 l = /*info:INFERRED_TYPE_LITERAL*/[i, n, s]; |
| 3046 } |
| 3047 { |
| 3048 Map<String, int> m = <String, int>{s: i}; |
| 3049 m = <String, int>{s: /*warning:MAP_VALUE_TYPE_NOT_ASSIGNABLE*/s}; |
| 3050 m = <String, int>{s: /*info:DOWN_CAST_IMPLICIT*/n}; |
| 3051 m = <String, int>{s: i, |
| 3052 s: /*info:DOWN_CAST_IMPLICIT*/n, |
| 3053 s: /*warning:MAP_VALUE_TYPE_NOT_ASSIGNABLE*/s}; |
| 3054 } |
| 3055 // TODO(leafp): We can't currently test for key errors since the |
| 3056 // error marker binds to the entire entry. |
| 3057 { |
| 3058 Map m = /*info:INFERRED_TYPE_LITERAL*/{s: i}; |
| 3059 m = /*info:INFERRED_TYPE_LITERAL*/{s: s}; |
| 3060 m = /*info:INFERRED_TYPE_LITERAL*/{s: n}; |
| 3061 m = /*info:INFERRED_TYPE_LITERAL*/ |
| 3062 {s: i, |
| 3063 s: n, |
| 3064 s: s}; |
| 3065 m = /*info:INFERRED_TYPE_LITERAL*/ |
| 3066 {i: s, |
| 3067 n: s, |
| 3068 s: s}; |
| 3069 } |
| 3070 } |
| 3071 '''); |
| 3072 } |
| 3073 |
| 3074 void test_typePromotionFromDynamic() { |
| 3075 checkFile(r''' |
| 3076 f() { |
| 3077 dynamic x; |
| 3078 if (x is int) { |
| 3079 int y = x; |
| 3080 String z = /*warning:INVALID_ASSIGNMENT*/x; |
| 3081 } |
| 3082 } |
| 3083 g() { |
| 3084 Object x; |
| 3085 if (x is int) { |
| 3086 int y = x; |
| 3087 String z = /*warning:INVALID_ASSIGNMENT*/x; |
| 3088 } |
| 3089 } |
| 3090 '''); |
| 3091 } |
| 3092 |
| 3093 void test_typeSubtyping_assigningClass() { |
| 3094 checkFile(''' |
| 3095 class A {} |
| 3096 class B extends A {} |
| 3097 |
| 3098 void main() { |
| 3099 dynamic y; |
| 3100 Object o; |
| 3101 int i = 0; |
| 3102 double d = 0.0; |
| 3103 num n; |
| 3104 A a; |
| 3105 B b; |
| 3106 y = a; |
| 3107 o = a; |
| 3108 i = /*warning:INVALID_ASSIGNMENT*/a; |
| 3109 d = /*warning:INVALID_ASSIGNMENT*/a; |
| 3110 n = /*warning:INVALID_ASSIGNMENT*/a; |
| 3111 a = a; |
| 3112 b = /*info:DOWN_CAST_IMPLICIT*/a; |
| 3113 } |
| 3114 '''); |
| 3115 } |
| 3116 |
| 3117 void test_typeSubtyping_assigningSubclass() { |
| 3118 checkFile(''' |
| 3119 class A {} |
| 3120 class B extends A {} |
| 3121 class C extends A {} |
| 3122 |
| 3123 void main() { |
| 3124 dynamic y; |
| 3125 Object o; |
| 3126 int i = 0; |
| 3127 double d = 0.0; |
| 3128 num n; |
| 3129 A a; |
| 3130 B b; |
| 3131 C c; |
| 3132 y = b; |
| 3133 o = b; |
| 3134 i = /*warning:INVALID_ASSIGNMENT*/b; |
| 3135 d = /*warning:INVALID_ASSIGNMENT*/b; |
| 3136 n = /*warning:INVALID_ASSIGNMENT*/b; |
| 3137 a = b; |
| 3138 b = b; |
| 3139 c = /*warning:INVALID_ASSIGNMENT*/b; |
| 3140 } |
| 3141 '''); |
| 3142 } |
| 3143 |
| 3144 void test_typeSubtyping_dynamicDowncasts() { |
| 3145 checkFile(''' |
| 3146 class A {} |
| 3147 class B extends A {} |
| 3148 |
| 3149 void main() { |
| 3150 dynamic y; |
| 3151 Object o; |
| 3152 int i = 0; |
| 3153 double d = 0.0; |
| 3154 num n; |
| 3155 A a; |
| 3156 B b; |
| 3157 o = y; |
| 3158 i = /*info:DYNAMIC_CAST*/y; |
| 3159 d = /*info:DYNAMIC_CAST*/y; |
| 3160 n = /*info:DYNAMIC_CAST*/y; |
| 3161 a = /*info:DYNAMIC_CAST*/y; |
| 3162 b = /*info:DYNAMIC_CAST*/y; |
| 3163 } |
| 3164 '''); |
| 3165 } |
| 3166 |
| 3167 void test_typeSubtyping_dynamicIsTop() { |
| 3168 checkFile(''' |
| 3169 class A {} |
| 3170 class B extends A {} |
| 3171 |
| 3172 void main() { |
| 3173 dynamic y; |
| 3174 Object o; |
| 3175 int i = 0; |
| 3176 double d = 0.0; |
| 3177 num n; |
| 3178 A a; |
| 3179 B b; |
| 3180 y = o; |
| 3181 y = i; |
| 3182 y = d; |
| 3183 y = n; |
| 3184 y = a; |
| 3185 y = b; |
| 3186 } |
| 3187 '''); |
| 3188 } |
| 3189 |
| 3190 void test_typeSubtyping_interfaces() { |
| 3191 checkFile(''' |
| 3192 class A {} |
| 3193 class B extends A {} |
| 3194 class C extends A {} |
| 3195 class D extends B implements C {} |
| 3196 |
| 3197 void main() { |
| 3198 A top; |
| 3199 B left; |
| 3200 C right; |
| 3201 D bot; |
| 3202 { |
| 3203 top = top; |
| 3204 top = left; |
| 3205 top = right; |
| 3206 top = bot; |
| 3207 } |
| 3208 { |
| 3209 left = /*info:DOWN_CAST_IMPLICIT*/top; |
| 3210 left = left; |
| 3211 left = /*warning:INVALID_ASSIGNMENT*/right; |
| 3212 left = bot; |
| 3213 } |
| 3214 { |
| 3215 right = /*info:DOWN_CAST_IMPLICIT*/top; |
| 3216 right = /*warning:INVALID_ASSIGNMENT*/left; |
| 3217 right = right; |
| 3218 right = bot; |
| 3219 } |
| 3220 { |
| 3221 bot = /*info:DOWN_CAST_IMPLICIT*/top; |
| 3222 bot = /*info:DOWN_CAST_IMPLICIT*/left; |
| 3223 bot = /*info:DOWN_CAST_IMPLICIT*/right; |
| 3224 bot = bot; |
| 3225 } |
| 3226 } |
| 3227 '''); |
| 3228 } |
| 3229 |
| 3230 void test_unaryOperators() { |
| 3231 checkFile(''' |
| 3232 class A { |
| 3233 A operator ~() => null; |
| 3234 A operator +(int x) => null; |
| 3235 A operator -(int x) => null; |
| 3236 A operator -() => null; |
| 3237 } |
| 3238 |
| 3239 foo() => new A(); |
| 3240 |
| 3241 test() { |
| 3242 A a = new A(); |
| 3243 var c = foo(); |
| 3244 dynamic d; |
| 3245 |
| 3246 ~a; |
| 3247 (/*info:DYNAMIC_INVOKE*/~d); |
| 3248 |
| 3249 !/*warning:NON_BOOL_NEGATION_EXPRESSION*/a; |
| 3250 !/*info:DYNAMIC_CAST*/d; |
| 3251 |
| 3252 -a; |
| 3253 (/*info:DYNAMIC_INVOKE*/-d); |
| 3254 |
| 3255 ++a; |
| 3256 --a; |
| 3257 (/*info:DYNAMIC_INVOKE*/++d); |
| 3258 (/*info:DYNAMIC_INVOKE*/--d); |
| 3259 |
| 3260 a++; |
| 3261 a--; |
| 3262 (/*info:DYNAMIC_INVOKE*/d++); |
| 3263 (/*info:DYNAMIC_INVOKE*/d--); |
| 3264 }'''); |
| 3265 } |
| 3266 |
| 3267 void test_unboundRedirectingConstructor() { |
| 3268 // This is a regression test for https://github.com/dart-lang/sdk/issues/250
71 |
| 3269 checkFile(''' |
| 3270 class Foo { |
| 3271 Foo() : /*severe:REDIRECT_GENERATIVE_TO_MISSING_CONSTRUCTOR*/this.init(); |
| 3272 } |
| 3273 '''); |
| 3274 } |
| 3275 |
| 3276 void test_unboundTypeName() { |
| 3277 checkFile(''' |
| 3278 void main() { |
| 3279 /*warning:UNDEFINED_CLASS should be error*/AToB y; |
| 3280 } |
| 3281 '''); |
| 3282 } |
| 3283 |
| 3284 void test_unboundVariable() { |
| 3285 checkFile(''' |
| 3286 void main() { |
| 3287 dynamic y = /*warning:UNDEFINED_IDENTIFIER should be error*/unboundVariable; |
| 3288 } |
| 3289 '''); |
| 3290 } |
| 3291 |
| 3292 void test_voidSubtyping() { |
| 3293 // Regression test for https://github.com/dart-lang/sdk/issues/25069 |
| 3294 checkFile(''' |
| 3295 typedef int Foo(); |
| 3296 void foo() {} |
| 3297 void main () { |
| 3298 Foo x = /*warning:INVALID_ASSIGNMENT,info:USE_OF_VOID_RESULT*/foo(); |
| 3299 } |
| 3300 '''); |
| 3301 } |
| 3302 } |
OLD | NEW |