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

Side by Side Diff: pkg/analyzer/test/src/task/strong/checker_test.dart

Issue 2024433002: Rewrite checker_test using reflective tests. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 // 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 }
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698