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