| 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 /// Tests for type inference. | 5 /// Tests for type inference. |
| 6 library dev_compiler.test.inferred_type_test; | 6 library dev_compiler.test.inferred_type_test; |
| 7 | 7 |
| 8 import 'package:test/test.dart'; | 8 import 'package:test/test.dart'; |
| 9 | 9 |
| 10 import '../testing.dart'; | 10 import '../testing.dart'; |
| 11 | 11 |
| 12 void main() { | 12 void main() { |
| 13 test('infer type on var', () { | 13 // Error also expected when declared type is `int`. |
| 14 // Error also expected when declared type is `int`. | 14 testChecker('infer type on var', { |
| 15 testChecker({ | 15 '/main.dart': ''' |
| 16 '/main.dart': ''' | |
| 17 test1() { | 16 test1() { |
| 18 int x = 3; | 17 int x = 3; |
| 19 x = /*severe:StaticTypeError*/"hi"; | 18 x = /*severe:StaticTypeError*/"hi"; |
| 20 } | 19 } |
| 21 ''' | 20 ''' |
| 22 }); | 21 }); |
| 23 | 22 |
| 24 // If inferred type is `int`, error is also reported | 23 // If inferred type is `int`, error is also reported |
| 25 testChecker({ | 24 testChecker('infer type on var 2', { |
| 26 '/main.dart': ''' | 25 '/main.dart': ''' |
| 27 test2() { | 26 test2() { |
| 28 var x = 3; | 27 var x = 3; |
| 29 x = /*severe:StaticTypeError*/"hi"; | 28 x = /*severe:StaticTypeError*/"hi"; |
| 30 } | 29 } |
| 31 ''' | 30 ''' |
| 32 }); | |
| 33 }); | 31 }); |
| 34 | 32 |
| 35 test('Error when declared type is `int` and assigned null.', () { | 33 testChecker('Error when declared type is `int` and assigned null.', { |
| 36 testChecker({ | 34 '/main.dart': ''' |
| 37 '/main.dart': ''' | |
| 38 test1() { | 35 test1() { |
| 39 int x = 3; | 36 int x = 3; |
| 40 x = /*severe:StaticTypeError*/null; | 37 x = /*severe:StaticTypeError*/null; |
| 41 } | 38 } |
| 42 ''' | 39 ''' |
| 43 }, nonnullableTypes: <String>[ | 40 }, nonnullableTypes: <String>[ |
| 44 'int', | 41 'int', |
| 45 'double' | 42 'double' |
| 46 ]); | 43 ]); |
| 47 }); | |
| 48 | 44 |
| 49 test('Error when inferred type is `int` and assigned null.', () { | 45 testChecker('Error when inferred type is `int` and assigned null.', { |
| 50 testChecker({ | 46 '/main.dart': ''' |
| 51 '/main.dart': ''' | |
| 52 test1() { | 47 test1() { |
| 53 var x = 3; | 48 var x = 3; |
| 54 x = /*severe:StaticTypeError*/null; | 49 x = /*severe:StaticTypeError*/null; |
| 55 } | 50 } |
| 56 ''' | 51 ''' |
| 57 }, nonnullableTypes: <String>[ | 52 }, nonnullableTypes: <String>[ |
| 58 'int', | 53 'int', |
| 59 'double' | 54 'double' |
| 60 ]); | 55 ]); |
| 61 }); | |
| 62 | 56 |
| 63 test('No error when declared type is `num` and assigned null.', () { | 57 testChecker('No error when declared type is `num` and assigned null.', { |
| 64 testChecker({ | 58 '/main.dart': ''' |
| 65 '/main.dart': ''' | |
| 66 test1() { | 59 test1() { |
| 67 num x = 3; | 60 num x = 3; |
| 68 x = null; | 61 x = null; |
| 69 } | 62 } |
| 70 ''' | 63 ''' |
| 71 }); | |
| 72 }); | 64 }); |
| 73 | 65 |
| 74 test('do not infer type on dynamic', () { | 66 testChecker('do not infer type on dynamic', { |
| 75 testChecker({ | 67 '/main.dart': ''' |
| 76 '/main.dart': ''' | |
| 77 test() { | 68 test() { |
| 78 dynamic x = 3; | 69 dynamic x = 3; |
| 79 x = "hi"; | 70 x = "hi"; |
| 80 } | 71 } |
| 81 ''' | 72 ''' |
| 82 }); | |
| 83 }); | 73 }); |
| 84 | 74 |
| 85 test('do not infer type when initializer is null', () { | 75 testChecker('do not infer type when initializer is null', { |
| 86 testChecker({ | 76 '/main.dart': ''' |
| 87 '/main.dart': ''' | |
| 88 test() { | 77 test() { |
| 89 var x = null; | 78 var x = null; |
| 90 x = "hi"; | 79 x = "hi"; |
| 91 x = 3; | 80 x = 3; |
| 92 } | 81 } |
| 93 ''' | 82 ''' |
| 94 }); | |
| 95 }); | 83 }); |
| 96 | 84 |
| 97 test('infer type on var from field', () { | 85 testChecker('infer type on var from field', { |
| 98 testChecker({ | 86 '/main.dart': ''' |
| 99 '/main.dart': ''' | |
| 100 class A { | 87 class A { |
| 101 int x = 0; | 88 int x = 0; |
| 102 | 89 |
| 103 test1() { | 90 test1() { |
| 104 var a = x; | 91 var a = x; |
| 105 a = /*severe:StaticTypeError*/"hi"; | 92 a = /*severe:StaticTypeError*/"hi"; |
| 106 a = 3; | 93 a = 3; |
| 107 var b = y; | 94 var b = y; |
| 108 b = /*severe:StaticTypeError*/"hi"; | 95 b = /*severe:StaticTypeError*/"hi"; |
| 109 b = 4; | 96 b = 4; |
| 110 var c = z; | 97 var c = z; |
| 111 c = /*severe:StaticTypeError*/"hi"; | 98 c = /*severe:StaticTypeError*/"hi"; |
| 112 c = 4; | 99 c = 4; |
| 113 } | 100 } |
| 114 | 101 |
| 115 int y; // field def after use | 102 int y; // field def after use |
| 116 final z = 42; // should infer `int` | 103 final z = 42; // should infer `int` |
| 117 } | 104 } |
| 118 ''' | 105 ''' |
| 119 }); | |
| 120 }); | 106 }); |
| 121 | 107 |
| 122 test('infer type on var from top-level', () { | 108 testChecker('infer type on var from top-level', { |
| 123 testChecker({ | 109 '/main.dart': ''' |
| 124 '/main.dart': ''' | |
| 125 int x = 0; | 110 int x = 0; |
| 126 | 111 |
| 127 test1() { | 112 test1() { |
| 128 var a = x; | 113 var a = x; |
| 129 a = /*severe:StaticTypeError*/"hi"; | 114 a = /*severe:StaticTypeError*/"hi"; |
| 130 a = 3; | 115 a = 3; |
| 131 var b = y; | 116 var b = y; |
| 132 b = /*severe:StaticTypeError*/"hi"; | 117 b = /*severe:StaticTypeError*/"hi"; |
| 133 b = 4; | 118 b = 4; |
| 134 var c = z; | 119 var c = z; |
| 135 c = /*severe:StaticTypeError*/"hi"; | 120 c = /*severe:StaticTypeError*/"hi"; |
| 136 c = 4; | 121 c = 4; |
| 137 } | 122 } |
| 138 | 123 |
| 139 int y = 0; // field def after use | 124 int y = 0; // field def after use |
| 140 final z = 42; // should infer `int` | 125 final z = 42; // should infer `int` |
| 141 ''' | 126 ''' |
| 142 }); | |
| 143 }); | 127 }); |
| 144 | 128 |
| 145 test('do not infer field type when initializer is null', () { | 129 testChecker('do not infer field type when initializer is null', { |
| 146 testChecker({ | 130 '/main.dart': ''' |
| 147 '/main.dart': ''' | |
| 148 var x = null; | 131 var x = null; |
| 149 var y = 3; | 132 var y = 3; |
| 150 class A { | 133 class A { |
| 151 static var x = null; | 134 static var x = null; |
| 152 static var y = 3; | 135 static var y = 3; |
| 153 | 136 |
| 154 var x2 = null; | 137 var x2 = null; |
| 155 var y2 = 3; | 138 var y2 = 3; |
| 156 } | 139 } |
| 157 | 140 |
| 158 test() { | 141 test() { |
| 159 x = "hi"; | 142 x = "hi"; |
| 160 y = /*severe:StaticTypeError*/"hi"; | 143 y = /*severe:StaticTypeError*/"hi"; |
| 161 A.x = "hi"; | 144 A.x = "hi"; |
| 162 A.y = /*severe:StaticTypeError*/"hi"; | 145 A.y = /*severe:StaticTypeError*/"hi"; |
| 163 new A().x2 = "hi"; | 146 new A().x2 = "hi"; |
| 164 new A().y2 = /*severe:StaticTypeError*/"hi"; | 147 new A().y2 = /*severe:StaticTypeError*/"hi"; |
| 165 } | 148 } |
| 166 ''' | 149 ''' |
| 167 }); | |
| 168 }); | 150 }); |
| 169 | 151 |
| 170 test('do not infer from variables if flag is off', () { | 152 testChecker( |
| 171 testChecker({ | 153 'do not infer from variables if flag is off', |
| 172 '/main.dart': ''' | 154 { |
| 155 '/main.dart': ''' |
| 173 var x = 2; | 156 var x = 2; |
| 174 var y = x; | 157 var y = x; |
| 175 | 158 |
| 176 test1() { | 159 test1() { |
| 177 x = /*severe:StaticTypeError*/"hi"; | 160 x = /*severe:StaticTypeError*/"hi"; |
| 178 y = "hi"; | 161 y = "hi"; |
| 179 } | 162 } |
| 180 ''' | 163 ''' |
| 181 }, inferTransitively: false); | 164 }, |
| 165 inferTransitively: false); |
| 182 | 166 |
| 183 testChecker({ | 167 testChecker( |
| 184 '/main.dart': ''' | 168 'do not infer from variables if flag is off 2', |
| 169 { |
| 170 '/main.dart': ''' |
| 185 class A { | 171 class A { |
| 186 static var x = 2; | 172 static var x = 2; |
| 187 static var y = A.x; | 173 static var y = A.x; |
| 188 } | 174 } |
| 189 | 175 |
| 190 test1() { | 176 test1() { |
| 191 A.x = /*severe:StaticTypeError*/"hi"; | 177 A.x = /*severe:StaticTypeError*/"hi"; |
| 192 A.y = "hi"; | 178 A.y = "hi"; |
| 193 } | 179 } |
| 194 ''' | 180 ''' |
| 195 }, inferTransitively: false); | 181 }, |
| 196 }); | 182 inferTransitively: false); |
| 197 | 183 |
| 198 test('do not infer from variables in non-cycle imports if flag is off', () { | 184 testChecker( |
| 199 testChecker({ | 185 'do not infer from variables in non-cycle imports if flag is off', |
| 200 '/a.dart': ''' | 186 { |
| 187 '/a.dart': ''' |
| 201 var x = 2; | 188 var x = 2; |
| 202 ''', | 189 ''', |
| 203 '/main.dart': ''' | 190 '/main.dart': ''' |
| 204 import 'a.dart'; | 191 import 'a.dart'; |
| 205 var y = x; | 192 var y = x; |
| 206 | 193 |
| 207 test1() { | 194 test1() { |
| 208 x = /*severe:StaticTypeError*/"hi"; | 195 x = /*severe:StaticTypeError*/"hi"; |
| 209 y = "hi"; | 196 y = "hi"; |
| 210 } | 197 } |
| 211 ''' | 198 ''' |
| 212 }, inferTransitively: false); | 199 }, |
| 200 inferTransitively: false); |
| 213 | 201 |
| 214 testChecker({ | 202 testChecker( |
| 215 '/a.dart': ''' | 203 'do not infer from variables in non-cycle imports if flag is off 2', |
| 204 { |
| 205 '/a.dart': ''' |
| 216 class A { static var x = 2; } | 206 class A { static var x = 2; } |
| 217 ''', | 207 ''', |
| 218 '/main.dart': ''' | 208 '/main.dart': ''' |
| 219 import 'a.dart'; | 209 import 'a.dart'; |
| 220 class B { static var y = A.x; } | 210 class B { static var y = A.x; } |
| 221 | 211 |
| 222 test1() { | 212 test1() { |
| 223 A.x = /*severe:StaticTypeError*/"hi"; | 213 A.x = /*severe:StaticTypeError*/"hi"; |
| 224 B.y = "hi"; | 214 B.y = "hi"; |
| 225 } | 215 } |
| 226 ''' | 216 ''' |
| 227 }, inferTransitively: false); | 217 }, |
| 228 }); | 218 inferTransitively: false); |
| 229 | 219 |
| 230 test('infer from variables in non-cycle imports with flag', () { | 220 testChecker( |
| 231 testChecker({ | 221 'infer from variables in non-cycle imports with flag', |
| 232 '/a.dart': ''' | 222 { |
| 223 '/a.dart': ''' |
| 233 var x = 2; | 224 var x = 2; |
| 234 ''', | 225 ''', |
| 235 '/main.dart': ''' | 226 '/main.dart': ''' |
| 236 import 'a.dart'; | 227 import 'a.dart'; |
| 237 var y = x; | 228 var y = x; |
| 238 | 229 |
| 239 test1() { | 230 test1() { |
| 240 x = /*severe:StaticTypeError*/"hi"; | 231 x = /*severe:StaticTypeError*/"hi"; |
| 241 y = /*severe:StaticTypeError*/"hi"; | 232 y = /*severe:StaticTypeError*/"hi"; |
| 242 } | 233 } |
| 243 ''' | 234 ''' |
| 244 }, inferTransitively: true); | 235 }, |
| 236 inferTransitively: true); |
| 245 | 237 |
| 246 testChecker({ | 238 testChecker( |
| 247 '/a.dart': ''' | 239 'infer from variables in non-cycle imports with flag 2', |
| 240 { |
| 241 '/a.dart': ''' |
| 248 class A { static var x = 2; } | 242 class A { static var x = 2; } |
| 249 ''', | 243 ''', |
| 250 '/main.dart': ''' | 244 '/main.dart': ''' |
| 251 import 'a.dart'; | 245 import 'a.dart'; |
| 252 class B { static var y = A.x; } | 246 class B { static var y = A.x; } |
| 253 | 247 |
| 254 test1() { | 248 test1() { |
| 255 A.x = /*severe:StaticTypeError*/"hi"; | 249 A.x = /*severe:StaticTypeError*/"hi"; |
| 256 B.y = /*severe:StaticTypeError*/"hi"; | 250 B.y = /*severe:StaticTypeError*/"hi"; |
| 257 } | 251 } |
| 258 ''' | 252 ''' |
| 259 }, inferTransitively: true); | 253 }, |
| 260 }); | 254 inferTransitively: true); |
| 261 | 255 |
| 262 test('do not infer from variables in cycle libs when flag is off', () { | 256 testChecker( |
| 263 testChecker({ | 257 'do not infer from variables in cycle libs when flag is off', |
| 264 '/a.dart': ''' | 258 { |
| 259 '/a.dart': ''' |
| 265 import 'main.dart'; | 260 import 'main.dart'; |
| 266 var x = 2; // ok to infer | 261 var x = 2; // ok to infer |
| 267 ''', | 262 ''', |
| 268 '/main.dart': ''' | 263 '/main.dart': ''' |
| 269 import 'a.dart'; | 264 import 'a.dart'; |
| 270 var y = x; // not ok to infer yet | 265 var y = x; // not ok to infer yet |
| 271 | 266 |
| 272 test1() { | 267 test1() { |
| 273 int t = 3; | 268 int t = 3; |
| 274 t = x; | 269 t = x; |
| 275 t = /*info:DynamicCast*/y; | 270 t = /*info:DynamicCast*/y; |
| 276 } | 271 } |
| 277 ''' | 272 ''' |
| 278 }, inferTransitively: false); | 273 }, |
| 274 inferTransitively: false); |
| 279 | 275 |
| 280 testChecker({ | 276 testChecker( |
| 281 '/a.dart': ''' | 277 'do not infer from variables in cycle libs when flag is off 2', |
| 278 { |
| 279 '/a.dart': ''' |
| 282 import 'main.dart'; | 280 import 'main.dart'; |
| 283 class A { static var x = 2; } | 281 class A { static var x = 2; } |
| 284 ''', | 282 ''', |
| 285 '/main.dart': ''' | 283 '/main.dart': ''' |
| 286 import 'a.dart'; | 284 import 'a.dart'; |
| 287 class B { static var y = A.x; } | 285 class B { static var y = A.x; } |
| 288 | 286 |
| 289 test1() { | 287 test1() { |
| 290 int t = 3; | 288 int t = 3; |
| 291 t = A.x; | 289 t = A.x; |
| 292 t = /*info:DynamicCast*/B.y; | 290 t = /*info:DynamicCast*/B.y; |
| 293 } | 291 } |
| 294 ''' | 292 ''' |
| 295 }, inferTransitively: false); | 293 }, |
| 296 }); | 294 inferTransitively: false); |
| 297 | 295 |
| 298 test('infer from variables in cycle libs when flag is on', () { | 296 testChecker( |
| 299 testChecker({ | 297 'infer from variables in cycle libs when flag is on', |
| 300 '/a.dart': ''' | 298 { |
| 299 '/a.dart': ''' |
| 301 import 'main.dart'; | 300 import 'main.dart'; |
| 302 var x = 2; // ok to infer | 301 var x = 2; // ok to infer |
| 303 ''', | 302 ''', |
| 304 '/main.dart': ''' | 303 '/main.dart': ''' |
| 305 import 'a.dart'; | 304 import 'a.dart'; |
| 306 var y = x; // now ok :) | 305 var y = x; // now ok :) |
| 307 | 306 |
| 308 test1() { | 307 test1() { |
| 309 int t = 3; | 308 int t = 3; |
| 310 t = x; | 309 t = x; |
| 311 t = y; | 310 t = y; |
| 312 } | 311 } |
| 313 ''' | 312 ''' |
| 314 }, inferTransitively: true); | 313 }, |
| 314 inferTransitively: true); |
| 315 | 315 |
| 316 testChecker({ | 316 testChecker( |
| 317 '/a.dart': ''' | 317 'infer from variables in cycle libs when flag is on 2', |
| 318 { |
| 319 '/a.dart': ''' |
| 318 import 'main.dart'; | 320 import 'main.dart'; |
| 319 class A { static var x = 2; } | 321 class A { static var x = 2; } |
| 320 ''', | 322 ''', |
| 321 '/main.dart': ''' | 323 '/main.dart': ''' |
| 322 import 'a.dart'; | 324 import 'a.dart'; |
| 323 class B { static var y = A.x; } | 325 class B { static var y = A.x; } |
| 324 | 326 |
| 325 test1() { | 327 test1() { |
| 326 int t = 3; | 328 int t = 3; |
| 327 t = A.x; | 329 t = A.x; |
| 328 t = B.y; | 330 t = B.y; |
| 329 } | 331 } |
| 330 ''' | 332 ''' |
| 331 }, inferTransitively: true); | 333 }, |
| 332 }); | 334 inferTransitively: true); |
| 333 | 335 |
| 334 test('do not infer from static and instance fields when flag is off', () { | 336 testChecker( |
| 335 testChecker({ | 337 'do not infer from static and instance fields when flag is off', |
| 336 '/a.dart': ''' | 338 { |
| 339 '/a.dart': ''' |
| 337 import 'b.dart'; | 340 import 'b.dart'; |
| 338 class A { | 341 class A { |
| 339 static final a1 = B.b1; | 342 static final a1 = B.b1; |
| 340 final a2 = new B().b2; | 343 final a2 = new B().b2; |
| 341 } | 344 } |
| 342 ''', | 345 ''', |
| 343 '/b.dart': ''' | 346 '/b.dart': ''' |
| 344 class B { | 347 class B { |
| 345 static final b1 = 1; | 348 static final b1 = 1; |
| 346 final b2 = 1; | 349 final b2 = 1; |
| 347 } | 350 } |
| 348 ''', | 351 ''', |
| 349 '/main.dart': ''' | 352 '/main.dart': ''' |
| 350 import "a.dart"; | 353 import "a.dart"; |
| 351 | 354 |
| 352 test1() { | 355 test1() { |
| 353 int x = 0; | 356 int x = 0; |
| 354 // inference in A disabled (flag is off) | 357 // inference in A disabled (flag is off) |
| 355 x = /*info:DynamicCast*/A.a1; | 358 x = /*info:DynamicCast*/A.a1; |
| 356 x = /*info:DynamicCast*/new A().a2; | 359 x = /*info:DynamicCast*/new A().a2; |
| 357 } | 360 } |
| 358 ''' | 361 ''' |
| 359 }, inferTransitively: false); | 362 }, |
| 360 }); | 363 inferTransitively: false); |
| 361 | 364 |
| 362 test('can infer also from static and instance fields (flag on)', () { | 365 testChecker( |
| 363 testChecker({ | 366 'can infer also from static and instance fields (flag on)', |
| 364 '/a.dart': ''' | 367 { |
| 368 '/a.dart': ''' |
| 365 import 'b.dart'; | 369 import 'b.dart'; |
| 366 class A { | 370 class A { |
| 367 static final a1 = B.b1; | 371 static final a1 = B.b1; |
| 368 final a2 = new B().b2; | 372 final a2 = new B().b2; |
| 369 } | 373 } |
| 370 ''', | 374 ''', |
| 371 '/b.dart': ''' | 375 '/b.dart': ''' |
| 372 class B { | 376 class B { |
| 373 static final b1 = 1; | 377 static final b1 = 1; |
| 374 final b2 = 1; | 378 final b2 = 1; |
| 375 } | 379 } |
| 376 ''', | 380 ''', |
| 377 '/main.dart': ''' | 381 '/main.dart': ''' |
| 378 import "a.dart"; | 382 import "a.dart"; |
| 379 | 383 |
| 380 test1() { | 384 test1() { |
| 381 int x = 0; | 385 int x = 0; |
| 382 // inference in A now works. | 386 // inference in A now works. |
| 383 x = A.a1; | 387 x = A.a1; |
| 384 x = new A().a2; | 388 x = new A().a2; |
| 385 } | 389 } |
| 386 ''' | 390 ''' |
| 387 }, inferTransitively: true); | 391 }, |
| 388 }); | 392 inferTransitively: true); |
| 389 | 393 |
| 390 test('inference in cycles is deterministic', () { | 394 testChecker( |
| 391 testChecker({ | 395 'inference in cycles is deterministic', |
| 392 '/a.dart': ''' | 396 { |
| 397 '/a.dart': ''' |
| 393 import 'b.dart'; | 398 import 'b.dart'; |
| 394 class A { | 399 class A { |
| 395 static final a1 = B.b1; | 400 static final a1 = B.b1; |
| 396 final a2 = new B().b2; | 401 final a2 = new B().b2; |
| 397 } | 402 } |
| 398 ''', | 403 ''', |
| 399 '/b.dart': ''' | 404 '/b.dart': ''' |
| 400 class B { | 405 class B { |
| 401 static final b1 = 1; | 406 static final b1 = 1; |
| 402 final b2 = 1; | 407 final b2 = 1; |
| 403 } | 408 } |
| 404 ''', | 409 ''', |
| 405 '/c.dart': ''' | 410 '/c.dart': ''' |
| 406 import "main.dart"; // creates a cycle | 411 import "main.dart"; // creates a cycle |
| 407 | 412 |
| 408 class C { | 413 class C { |
| 409 static final c1 = 1; | 414 static final c1 = 1; |
| 410 final c2 = 1; | 415 final c2 = 1; |
| 411 } | 416 } |
| 412 ''', | 417 ''', |
| 413 '/e.dart': ''' | 418 '/e.dart': ''' |
| 414 import 'a.dart'; | 419 import 'a.dart'; |
| 415 part 'e2.dart'; | 420 part 'e2.dart'; |
| 416 | 421 |
| 417 class E { | 422 class E { |
| 418 static final e1 = 1; | 423 static final e1 = 1; |
| 419 static final e2 = F.f1; | 424 static final e2 = F.f1; |
| 420 static final e3 = A.a1; | 425 static final e3 = A.a1; |
| 421 final e4 = 1; | 426 final e4 = 1; |
| 422 final e5 = new F().f2; | 427 final e5 = new F().f2; |
| 423 final e6 = new A().a2; | 428 final e6 = new A().a2; |
| 424 } | 429 } |
| 425 ''', | 430 ''', |
| 426 '/f.dart': ''' | 431 '/f.dart': ''' |
| 427 part 'f2.dart'; | 432 part 'f2.dart'; |
| 428 ''', | 433 ''', |
| 429 '/e2.dart': ''' | 434 '/e2.dart': ''' |
| 430 class F { | 435 class F { |
| 431 static final f1 = 1; | 436 static final f1 = 1; |
| 432 final f2 = 1; | 437 final f2 = 1; |
| 433 } | 438 } |
| 434 ''', | 439 ''', |
| 435 '/main.dart': ''' | 440 '/main.dart': ''' |
| 436 import "a.dart"; | 441 import "a.dart"; |
| 437 import "c.dart"; | 442 import "c.dart"; |
| 438 import "e.dart"; | 443 import "e.dart"; |
| 439 | 444 |
| 440 class D { | 445 class D { |
| 441 static final d1 = A.a1 + 1; | 446 static final d1 = A.a1 + 1; |
| 442 static final d2 = C.c1 + 1; | 447 static final d2 = C.c1 + 1; |
| 443 final d3 = new A().a2; | 448 final d3 = new A().a2; |
| 444 final d4 = new C().c2; | 449 final d4 = new C().c2; |
| 445 } | 450 } |
| (...skipping 18 matching lines...) Expand all Loading... |
| 464 x = E.e1; | 469 x = E.e1; |
| 465 x = E.e2; | 470 x = E.e2; |
| 466 x = E.e3; | 471 x = E.e3; |
| 467 x = new E().e4; | 472 x = new E().e4; |
| 468 x = /*info:DynamicCast*/new E().e5; | 473 x = /*info:DynamicCast*/new E().e5; |
| 469 x = new E().e6; | 474 x = new E().e6; |
| 470 x = F.f1; | 475 x = F.f1; |
| 471 x = new F().f2; | 476 x = new F().f2; |
| 472 } | 477 } |
| 473 ''' | 478 ''' |
| 474 }, inferTransitively: true); | 479 }, |
| 475 }); | 480 inferTransitively: true); |
| 476 | 481 |
| 477 test('infer from complex expressions if the outer-most value is precise', () { | 482 testChecker( |
| 478 testChecker({ | 483 'infer from complex expressions if the outer-most value is precise', { |
| 479 '/main.dart': ''' | 484 '/main.dart': ''' |
| 480 class A { int x; B operator+(other) {} } | 485 class A { int x; B operator+(other) {} } |
| 481 class B extends A { B(ignore); } | 486 class B extends A { B(ignore); } |
| 482 var a = new A(); | 487 var a = new A(); |
| 483 // Note: it doesn't matter that some of these refer to 'x'. | 488 // Note: it doesn't matter that some of these refer to 'x'. |
| 484 var b = new B(x); // allocations | 489 var b = new B(x); // allocations |
| 485 var c1 = [x]; // list literals | 490 var c1 = [x]; // list literals |
| 486 var c2 = const []; | 491 var c2 = const []; |
| 487 var d = {'a': 'b'}; // map literals | 492 var d = {'a': 'b'}; // map literals |
| 488 var e = new A()..x = 3; // cascades | 493 var e = new A()..x = 3; // cascades |
| 489 var f = 2 + 3; // binary expressions are OK if the left operand | 494 var f = 2 + 3; // binary expressions are OK if the left operand |
| (...skipping 22 matching lines...) Expand all Loading... |
| 512 g = 1; | 517 g = 1; |
| 513 g = /*severe:StaticTypeError*/false; | 518 g = /*severe:StaticTypeError*/false; |
| 514 h = /*severe:StaticTypeError*/false; | 519 h = /*severe:StaticTypeError*/false; |
| 515 h = new B(); | 520 h = new B(); |
| 516 i = false; | 521 i = false; |
| 517 j = new B(); | 522 j = new B(); |
| 518 j = /*severe:StaticTypeError*/false; | 523 j = /*severe:StaticTypeError*/false; |
| 519 j = /*severe:StaticTypeError*/[]; | 524 j = /*severe:StaticTypeError*/[]; |
| 520 } | 525 } |
| 521 ''' | 526 ''' |
| 522 }); | |
| 523 }); | 527 }); |
| 524 | 528 |
| 525 test('do not infer if complex expressions read possibly inferred field', () { | 529 testChecker( |
| 526 testChecker({ | 530 'do not infer if complex expressions read possibly inferred field', |
| 527 '/a.dart': ''' | 531 { |
| 532 '/a.dart': ''' |
| 528 class A { | 533 class A { |
| 529 var x = 3; | 534 var x = 3; |
| 530 } | 535 } |
| 531 ''', | 536 ''', |
| 532 '/main.dart': ''' | 537 '/main.dart': ''' |
| 533 import 'a.dart'; | 538 import 'a.dart'; |
| 534 class B { | 539 class B { |
| 535 var y = 3; | 540 var y = 3; |
| 536 } | 541 } |
| 537 final t1 = new A(); | 542 final t1 = new A(); |
| 538 final t2 = new A().x; | 543 final t2 = new A().x; |
| 539 final t3 = new B(); | 544 final t3 = new B(); |
| 540 final t4 = new B().y; | 545 final t4 = new B().y; |
| 541 | 546 |
| 542 test1() { | 547 test1() { |
| 543 int i = 0; | 548 int i = 0; |
| 544 A a; | 549 A a; |
| 545 B b; | 550 B b; |
| 546 a = t1; | 551 a = t1; |
| 547 i = /*info:DynamicCast*/t2; | 552 i = /*info:DynamicCast*/t2; |
| 548 b = t3; | 553 b = t3; |
| 549 i = /*info:DynamicCast*/t4; | 554 i = /*info:DynamicCast*/t4; |
| 550 i = new B().y; // B.y was inferred though | 555 i = new B().y; // B.y was inferred though |
| 551 } | 556 } |
| 552 ''' | 557 ''' |
| 553 }, inferTransitively: false); | 558 }, |
| 559 inferTransitively: false); |
| 554 | 560 |
| 555 // but flags can enable this behavior. | 561 // but flags can enable this behavior. |
| 556 testChecker({ | 562 testChecker( |
| 557 '/a.dart': ''' | 563 'infer if complex expressions read possibly inferred field', |
| 564 { |
| 565 '/a.dart': ''' |
| 558 class A { | 566 class A { |
| 559 var x = 3; | 567 var x = 3; |
| 560 } | 568 } |
| 561 ''', | 569 ''', |
| 562 '/main.dart': ''' | 570 '/main.dart': ''' |
| 563 import 'a.dart'; | 571 import 'a.dart'; |
| 564 class B { | 572 class B { |
| 565 var y = 3; | 573 var y = 3; |
| 566 } | 574 } |
| 567 final t1 = new A(); | 575 final t1 = new A(); |
| 568 final t2 = new A().x; | 576 final t2 = new A().x; |
| 569 final t3 = new B(); | 577 final t3 = new B(); |
| 570 final t4 = new B().y; | 578 final t4 = new B().y; |
| 571 | 579 |
| 572 test1() { | 580 test1() { |
| 573 int i = 0; | 581 int i = 0; |
| 574 A a; | 582 A a; |
| 575 B b; | 583 B b; |
| 576 a = t1; | 584 a = t1; |
| 577 i = t2; | 585 i = t2; |
| 578 b = t3; | 586 b = t3; |
| 579 i = /*info:DynamicCast*/t4; | 587 i = /*info:DynamicCast*/t4; |
| 580 i = new B().y; // B.y was inferred though | 588 i = new B().y; // B.y was inferred though |
| 581 } | 589 } |
| 582 ''' | 590 ''' |
| 583 }, inferTransitively: true); | 591 }, |
| 584 }); | 592 inferTransitively: true); |
| 585 | 593 |
| 586 test('infer types on loop indices', () { | 594 group('infer types on loop indices', () { |
| 587 // foreach loop | 595 testChecker('foreach loop', { |
| 588 testChecker({ | |
| 589 '/main.dart': ''' | 596 '/main.dart': ''' |
| 590 class Foo { | 597 class Foo { |
| 591 int bar = 42; | 598 int bar = 42; |
| 592 } | 599 } |
| 593 | 600 |
| 594 test() { | 601 test() { |
| 595 var list = <Foo>[]; | 602 var list = <Foo>[]; |
| 596 for (var x in list) { | 603 for (var x in list) { |
| 597 String y = /*severe:StaticTypeError*/x; | 604 String y = /*severe:StaticTypeError*/x; |
| 598 } | 605 } |
| (...skipping 29 matching lines...) Expand all Loading... |
| 628 | 635 |
| 629 // We're not properly inferring that map.keys is an Iterable<String> | 636 // We're not properly inferring that map.keys is an Iterable<String> |
| 630 // and that x is a String. | 637 // and that x is a String. |
| 631 for (var x in map.keys) { | 638 for (var x in map.keys) { |
| 632 String y = x; | 639 String y = x; |
| 633 } | 640 } |
| 634 } | 641 } |
| 635 ''' | 642 ''' |
| 636 }); | 643 }); |
| 637 | 644 |
| 638 // for loop, with inference | 645 testChecker('for loop, with inference', { |
| 639 testChecker({ | |
| 640 '/main.dart': ''' | 646 '/main.dart': ''' |
| 641 test() { | 647 test() { |
| 642 for (var i = 0; i < 10; i++) { | 648 for (var i = 0; i < 10; i++) { |
| 643 int j = i + 1; | 649 int j = i + 1; |
| 644 } | 650 } |
| 645 } | 651 } |
| 646 ''' | 652 ''' |
| 647 }); | 653 }); |
| 648 }); | 654 }); |
| 649 | 655 |
| 650 test('propagate inference to field in class', () { | 656 testChecker('propagate inference to field in class', { |
| 651 testChecker({ | 657 '/main.dart': ''' |
| 652 '/main.dart': ''' | |
| 653 class A { | 658 class A { |
| 654 int x = 2; | 659 int x = 2; |
| 655 } | 660 } |
| 656 | 661 |
| 657 test() { | 662 test() { |
| 658 var a = new A(); | 663 var a = new A(); |
| 659 A b = a; // doesn't require down cast | 664 A b = a; // doesn't require down cast |
| 660 print(a.x); // doesn't require dynamic invoke | 665 print(a.x); // doesn't require dynamic invoke |
| 661 print(a.x + 2); // ok to use in bigger expression | 666 print(a.x + 2); // ok to use in bigger expression |
| 662 } | 667 } |
| 663 ''' | 668 ''' |
| 664 }); | 669 }); |
| 665 | 670 |
| 666 // Same code with dynamic yields warnings | 671 testChecker('propagate inference to field in class dynamic warnings', { |
| 667 testChecker({ | 672 '/main.dart': ''' |
| 668 '/main.dart': ''' | |
| 669 class A { | 673 class A { |
| 670 int x = 2; | 674 int x = 2; |
| 671 } | 675 } |
| 672 | 676 |
| 673 test() { | 677 test() { |
| 674 dynamic a = new A(); | 678 dynamic a = new A(); |
| 675 A b = /*info:DynamicCast*/a; | 679 A b = /*info:DynamicCast*/a; |
| 676 print(/*info:DynamicInvoke*/a.x); | 680 print(/*info:DynamicInvoke*/a.x); |
| 677 print(/*info:DynamicInvoke*/(/*info:DynamicInvoke*/a.x) + 2); | 681 print(/*info:DynamicInvoke*/(/*info:DynamicInvoke*/a.x) + 2); |
| 678 } | 682 } |
| 679 ''' | 683 ''' |
| 680 }); | |
| 681 }); | 684 }); |
| 682 | 685 |
| 683 test('propagate inference transitively ', () { | 686 testChecker('propagate inference transitively', { |
| 684 testChecker({ | 687 '/main.dart': ''' |
| 685 '/main.dart': ''' | |
| 686 class A { | 688 class A { |
| 687 int x = 2; | 689 int x = 2; |
| 688 } | 690 } |
| 689 | 691 |
| 690 test5() { | 692 test5() { |
| 691 var a1 = new A(); | 693 var a1 = new A(); |
| 692 a1.x = /*severe:StaticTypeError*/"hi"; | 694 a1.x = /*severe:StaticTypeError*/"hi"; |
| 693 | 695 |
| 694 A a2 = new A(); | 696 A a2 = new A(); |
| 695 a2.x = /*severe:StaticTypeError*/"hi"; | 697 a2.x = /*severe:StaticTypeError*/"hi"; |
| 696 } | 698 } |
| 697 ''' | 699 ''' |
| 698 }); | 700 }); |
| 699 | 701 |
| 700 testChecker({ | 702 testChecker('propagate inference transitively 2', { |
| 701 '/main.dart': ''' | 703 '/main.dart': ''' |
| 702 class A { | 704 class A { |
| 703 int x = 42; | 705 int x = 42; |
| 704 } | 706 } |
| 705 | 707 |
| 706 class B { | 708 class B { |
| 707 A a = new A(); | 709 A a = new A(); |
| 708 } | 710 } |
| 709 | 711 |
| 710 class C { | 712 class C { |
| 711 B b = new B(); | 713 B b = new B(); |
| 712 } | 714 } |
| 713 | 715 |
| 714 class D { | 716 class D { |
| 715 C c = new C(); | 717 C c = new C(); |
| 716 } | 718 } |
| 717 | 719 |
| 718 void main() { | 720 void main() { |
| 719 var d1 = new D(); | 721 var d1 = new D(); |
| 720 print(d1.c.b.a.x); | 722 print(d1.c.b.a.x); |
| 721 | 723 |
| 722 D d2 = new D(); | 724 D d2 = new D(); |
| 723 print(d2.c.b.a.x); | 725 print(d2.c.b.a.x); |
| 724 } | 726 } |
| 725 ''' | 727 ''' |
| 726 }); | |
| 727 }); | 728 }); |
| 728 | 729 |
| 729 test('infer type on overridden fields', () { | 730 group('infer type on overridden fields', () { |
| 730 testChecker({ | 731 testChecker( |
| 731 '/main.dart': ''' | 732 '1', |
| 733 { |
| 734 '/main.dart': ''' |
| 732 class A { | 735 class A { |
| 733 int x = 2; | 736 int x = 2; |
| 734 } | 737 } |
| 735 | 738 |
| 736 class B extends A { | 739 class B extends A { |
| 737 /*severe:InferableOverride*/get x => 3; | 740 /*severe:InferableOverride*/get x => 3; |
| 738 } | 741 } |
| 739 | 742 |
| 740 foo() { | 743 foo() { |
| 741 String y = /*info:DynamicCast*/new B().x; | 744 String y = /*info:DynamicCast*/new B().x; |
| 742 int z = /*info:DynamicCast*/new B().x; | 745 int z = /*info:DynamicCast*/new B().x; |
| 743 } | 746 } |
| 744 ''' | 747 ''' |
| 745 }, inferFromOverrides: false); | 748 }, |
| 749 inferFromOverrides: false); |
| 746 | 750 |
| 747 testChecker({ | 751 testChecker( |
| 748 '/main.dart': ''' | 752 '2', |
| 753 { |
| 754 '/main.dart': ''' |
| 749 class A { | 755 class A { |
| 750 int x = 2; | 756 int x = 2; |
| 751 } | 757 } |
| 752 | 758 |
| 753 class B extends A { | 759 class B extends A { |
| 754 get x => 3; | 760 get x => 3; |
| 755 } | 761 } |
| 756 | 762 |
| 757 foo() { | 763 foo() { |
| 758 String y = /*severe:StaticTypeError*/new B().x; | 764 String y = /*severe:StaticTypeError*/new B().x; |
| 759 int z = new B().x; | 765 int z = new B().x; |
| 760 } | 766 } |
| 761 ''' | 767 ''' |
| 762 }, inferFromOverrides: true); | 768 }, |
| 769 inferFromOverrides: true); |
| 763 | 770 |
| 764 testChecker({ | 771 testChecker( |
| 765 '/main.dart': ''' | 772 '3', |
| 773 { |
| 774 '/main.dart': ''' |
| 766 class A { | 775 class A { |
| 767 int x = 2; | 776 int x = 2; |
| 768 } | 777 } |
| 769 | 778 |
| 770 class B implements A { | 779 class B implements A { |
| 771 /*severe:InferableOverride*/get x => 3; | 780 /*severe:InferableOverride*/get x => 3; |
| 772 } | 781 } |
| 773 | 782 |
| 774 foo() { | 783 foo() { |
| 775 String y = /*info:DynamicCast*/new B().x; | 784 String y = /*info:DynamicCast*/new B().x; |
| 776 int z = /*info:DynamicCast*/new B().x; | 785 int z = /*info:DynamicCast*/new B().x; |
| 777 } | 786 } |
| 778 ''' | 787 ''' |
| 779 }, inferFromOverrides: false); | 788 }, |
| 789 inferFromOverrides: false); |
| 780 | 790 |
| 781 testChecker({ | 791 testChecker( |
| 782 '/main.dart': ''' | 792 '4', |
| 793 { |
| 794 '/main.dart': ''' |
| 783 class A { | 795 class A { |
| 784 int x = 2; | 796 int x = 2; |
| 785 } | 797 } |
| 786 | 798 |
| 787 class B implements A { | 799 class B implements A { |
| 788 get x => 3; | 800 get x => 3; |
| 789 } | 801 } |
| 790 | 802 |
| 791 foo() { | 803 foo() { |
| 792 String y = /*severe:StaticTypeError*/new B().x; | 804 String y = /*severe:StaticTypeError*/new B().x; |
| 793 int z = new B().x; | 805 int z = new B().x; |
| 794 } | 806 } |
| 795 ''' | 807 ''' |
| 796 }, inferFromOverrides: true); | 808 }, |
| 809 inferFromOverrides: true); |
| 797 }); | 810 }); |
| 798 | 811 |
| 799 test('infer types on generic instantiations', () { | 812 group('infer types on generic instantiations', () { |
| 800 for (bool infer in [true, false]) { | 813 for (bool infer in [true, false]) { |
| 801 testChecker({ | 814 testChecker( |
| 802 '/main.dart': ''' | 815 'infer: $infer', |
| 816 { |
| 817 '/main.dart': ''' |
| 803 class A<T> { | 818 class A<T> { |
| 804 T x; | 819 T x; |
| 805 } | 820 } |
| 806 | 821 |
| 807 class B implements A<int> { | 822 class B implements A<int> { |
| 808 /*severe:InvalidMethodOverride*/dynamic get x => 3; | 823 /*severe:InvalidMethodOverride*/dynamic get x => 3; |
| 809 } | 824 } |
| 810 | 825 |
| 811 foo() { | 826 foo() { |
| 812 String y = /*info:DynamicCast*/new B().x; | 827 String y = /*info:DynamicCast*/new B().x; |
| 813 int z = /*info:DynamicCast*/new B().x; | 828 int z = /*info:DynamicCast*/new B().x; |
| 814 } | 829 } |
| 815 ''' | 830 ''' |
| 816 }, inferFromOverrides: infer); | 831 }, |
| 832 inferFromOverrides: infer); |
| 817 } | 833 } |
| 818 | 834 |
| 819 testChecker({ | 835 testChecker( |
| 820 '/main.dart': ''' | 836 '2', |
| 837 { |
| 838 '/main.dart': ''' |
| 821 class A<T> { | 839 class A<T> { |
| 822 T x; | 840 T x; |
| 823 } | 841 } |
| 824 | 842 |
| 825 class B implements A<int> { | 843 class B implements A<int> { |
| 826 /*severe:InferableOverride*/get x => 3; | 844 /*severe:InferableOverride*/get x => 3; |
| 827 } | 845 } |
| 828 | 846 |
| 829 foo() { | 847 foo() { |
| 830 String y = /*info:DynamicCast*/new B().x; | 848 String y = /*info:DynamicCast*/new B().x; |
| 831 int z = /*info:DynamicCast*/new B().x; | 849 int z = /*info:DynamicCast*/new B().x; |
| 832 } | 850 } |
| 833 ''' | 851 ''' |
| 834 }, inferFromOverrides: false); | 852 }, |
| 835 testChecker({ | 853 inferFromOverrides: false); |
| 836 '/main.dart': ''' | 854 |
| 855 testChecker( |
| 856 '3', |
| 857 { |
| 858 '/main.dart': ''' |
| 837 class A<T> { | 859 class A<T> { |
| 838 T x; | 860 T x; |
| 839 T w; | 861 T w; |
| 840 } | 862 } |
| 841 | 863 |
| 842 class B implements A<int> { | 864 class B implements A<int> { |
| 843 get x => 3; | 865 get x => 3; |
| 844 get w => /*severe:StaticTypeError*/"hello"; | 866 get w => /*severe:StaticTypeError*/"hello"; |
| 845 } | 867 } |
| 846 | 868 |
| 847 foo() { | 869 foo() { |
| 848 String y = /*severe:StaticTypeError*/new B().x; | 870 String y = /*severe:StaticTypeError*/new B().x; |
| 849 int z = new B().x; | 871 int z = new B().x; |
| 850 } | 872 } |
| 851 ''' | 873 ''' |
| 852 }, inferFromOverrides: true); | 874 }, |
| 875 inferFromOverrides: true); |
| 853 | 876 |
| 854 testChecker({ | 877 testChecker( |
| 855 '/main.dart': ''' | 878 '4', |
| 879 { |
| 880 '/main.dart': ''' |
| 856 class A<T> { | 881 class A<T> { |
| 857 T x; | 882 T x; |
| 858 } | 883 } |
| 859 | 884 |
| 860 class B<E> extends A<E> { | 885 class B<E> extends A<E> { |
| 861 E y; | 886 E y; |
| 862 get x => y; | 887 get x => y; |
| 863 } | 888 } |
| 864 | 889 |
| 865 foo() { | 890 foo() { |
| 866 int y = /*severe:StaticTypeError*/new B<String>().x; | 891 int y = /*severe:StaticTypeError*/new B<String>().x; |
| 867 String z = new B<String>().x; | 892 String z = new B<String>().x; |
| 868 } | 893 } |
| 869 ''' | 894 ''' |
| 870 }, inferFromOverrides: true); | 895 }, |
| 896 inferFromOverrides: true); |
| 871 | 897 |
| 872 testChecker({ | 898 testChecker( |
| 873 '/main.dart': ''' | 899 '5', |
| 900 { |
| 901 '/main.dart': ''' |
| 874 abstract class I<E> { | 902 abstract class I<E> { |
| 875 String m(a, String f(v, T e)); | 903 String m(a, String f(v, T e)); |
| 876 } | 904 } |
| 877 | 905 |
| 878 abstract class A<E> implements I<E> { | 906 abstract class A<E> implements I<E> { |
| 879 const A(); | 907 const A(); |
| 880 String m(a, String f(v, T e)); | 908 String m(a, String f(v, T e)); |
| 881 } | 909 } |
| 882 | 910 |
| 883 abstract class M { | 911 abstract class M { |
| 884 int y; | 912 int y; |
| 885 } | 913 } |
| 886 | 914 |
| 887 class B<E> extends A<E> implements M { | 915 class B<E> extends A<E> implements M { |
| 888 const B(); | 916 const B(); |
| 889 int get y => 0; | 917 int get y => 0; |
| 890 | 918 |
| 891 m(a, f(v, T e)) {} | 919 m(a, f(v, T e)) {} |
| 892 } | 920 } |
| 893 | 921 |
| 894 foo () { | 922 foo () { |
| 895 int y = /*severe:StaticTypeError*/new B().m(null, null); | 923 int y = /*severe:StaticTypeError*/new B().m(null, null); |
| 896 String z = new B().m(null, null); | 924 String z = new B().m(null, null); |
| 897 } | 925 } |
| 898 ''' | 926 ''' |
| 899 }, inferFromOverrides: true); | 927 }, |
| 928 inferFromOverrides: true); |
| 900 }); | 929 }); |
| 901 | 930 |
| 902 test('infer type regardless of declaration order or cycles', () { | 931 testChecker( |
| 903 testChecker({ | 932 'infer type regardless of declaration order or cycles', |
| 904 '/b.dart': ''' | 933 { |
| 934 '/b.dart': ''' |
| 905 import 'main.dart'; | 935 import 'main.dart'; |
| 906 | 936 |
| 907 class B extends A { } | 937 class B extends A { } |
| 908 ''', | 938 ''', |
| 909 '/main.dart': ''' | 939 '/main.dart': ''' |
| 910 import 'b.dart'; | 940 import 'b.dart'; |
| 911 class C extends B { | 941 class C extends B { |
| 912 get x; | 942 get x; |
| 913 } | 943 } |
| 914 class A { | 944 class A { |
| 915 int get x; | 945 int get x; |
| 916 } | 946 } |
| 917 foo () { | 947 foo () { |
| 918 int y = new C().x; | 948 int y = new C().x; |
| 919 String y = /*severe:StaticTypeError*/new C().x; | 949 String y = /*severe:StaticTypeError*/new C().x; |
| 920 } | 950 } |
| 921 ''' | 951 ''' |
| 922 }, inferFromOverrides: true); | 952 }, |
| 923 }); | 953 inferFromOverrides: true); |
| 924 | 954 |
| 925 // Note: this is a regression test for a non-deterministic behavior we used to | 955 // Note: this is a regression test for a non-deterministic behavior we used to |
| 926 // have with inference in library cycles. If you see this test flake out, | 956 // have with inference in library cycles. If you see this test flake out, |
| 927 // change `test` to `skip_test` and reopen bug #48. | 957 // change `test` to `skip_test` and reopen bug #48. |
| 928 test('infer types on generic instantiations in library cycle', () { | 958 testChecker( |
| 929 testChecker({ | 959 'infer types on generic instantiations in library cycle', |
| 930 '/a.dart': ''' | 960 { |
| 961 '/a.dart': ''' |
| 931 import 'main.dart'; | 962 import 'main.dart'; |
| 932 abstract class I<E> { | 963 abstract class I<E> { |
| 933 A<E> m(a, String f(v, T e)); | 964 A<E> m(a, String f(v, T e)); |
| 934 } | 965 } |
| 935 ''', | 966 ''', |
| 936 '/main.dart': ''' | 967 '/main.dart': ''' |
| 937 import 'a.dart'; | 968 import 'a.dart'; |
| 938 | 969 |
| 939 abstract class A<E> implements I<E> { | 970 abstract class A<E> implements I<E> { |
| 940 const A(); | 971 const A(); |
| 941 | 972 |
| 942 E value; | 973 E value; |
| 943 } | 974 } |
| 944 | 975 |
| 945 abstract class M { | 976 abstract class M { |
| 946 int y; | 977 int y; |
| 947 } | 978 } |
| 948 | 979 |
| 949 class B<E> extends A<E> implements M { | 980 class B<E> extends A<E> implements M { |
| 950 const B(); | 981 const B(); |
| 951 int get y => 0; | 982 int get y => 0; |
| 952 | 983 |
| 953 m(a, f(v, T e)) {} | 984 m(a, f(v, T e)) {} |
| 954 } | 985 } |
| 955 | 986 |
| 956 foo () { | 987 foo () { |
| 957 int y = /*severe:StaticTypeError*/new B<String>().m(null, null).value; | 988 int y = /*severe:StaticTypeError*/new B<String>().m(null, null).value; |
| 958 String z = new B<String>().m(null, null).value; | 989 String z = new B<String>().m(null, null).value; |
| 959 } | 990 } |
| 960 ''' | 991 ''' |
| 961 }, inferFromOverrides: true); | 992 }, |
| 962 }); | 993 inferFromOverrides: true); |
| 963 | 994 |
| 964 test('do not infer overridden fields that explicitly say dynamic', () { | 995 group('do not infer overridden fields that explicitly say dynamic', () { |
| 965 for (bool infer in [true, false]) { | 996 for (bool infer in [true, false]) { |
| 966 testChecker({ | 997 testChecker( |
| 967 '/main.dart': ''' | 998 'infer: $infer', |
| 999 { |
| 1000 '/main.dart': ''' |
| 968 class A { | 1001 class A { |
| 969 int x = 2; | 1002 int x = 2; |
| 970 } | 1003 } |
| 971 | 1004 |
| 972 class B implements A { | 1005 class B implements A { |
| 973 /*severe:InvalidMethodOverride*/dynamic get x => 3; | 1006 /*severe:InvalidMethodOverride*/dynamic get x => 3; |
| 974 } | 1007 } |
| 975 | 1008 |
| 976 foo() { | 1009 foo() { |
| 977 String y = /*info:DynamicCast*/new B().x; | 1010 String y = /*info:DynamicCast*/new B().x; |
| 978 int z = /*info:DynamicCast*/new B().x; | 1011 int z = /*info:DynamicCast*/new B().x; |
| 979 } | 1012 } |
| 980 ''' | 1013 ''' |
| 981 }, inferFromOverrides: infer); | 1014 }, |
| 1015 inferFromOverrides: infer); |
| 982 } | 1016 } |
| 983 }); | 1017 }); |
| 984 | 1018 |
| 985 test('conflicts can happen', () { | 1019 testChecker( |
| 986 testChecker({ | 1020 'conflicts can happen', |
| 987 '/main.dart': ''' | 1021 { |
| 1022 '/main.dart': ''' |
| 988 class I1 { | 1023 class I1 { |
| 989 int x; | 1024 int x; |
| 990 } | 1025 } |
| 991 class I2 extends I1 { | 1026 class I2 extends I1 { |
| 992 int y; | 1027 int y; |
| 993 } | 1028 } |
| 994 | 1029 |
| 995 class A { | 1030 class A { |
| 996 final I1 a; | 1031 final I1 a; |
| 997 } | 1032 } |
| 998 | 1033 |
| 999 class B { | 1034 class B { |
| 1000 final I2 a; | 1035 final I2 a; |
| 1001 } | 1036 } |
| 1002 | 1037 |
| 1003 class C1 extends A implements B { | 1038 class C1 extends A implements B { |
| 1004 /*severe:InvalidMethodOverride*/get a => null; | 1039 /*severe:InvalidMethodOverride*/get a => null; |
| 1005 } | 1040 } |
| 1006 | 1041 |
| 1007 // Here we infer from B, which is more precise. | 1042 // Here we infer from B, which is more precise. |
| 1008 class C2 extends B implements A { | 1043 class C2 extends B implements A { |
| 1009 get a => null; | 1044 get a => null; |
| 1010 } | 1045 } |
| 1011 ''' | 1046 ''' |
| 1012 }, inferFromOverrides: true); | 1047 }, |
| 1048 inferFromOverrides: true); |
| 1013 | 1049 |
| 1014 testChecker({ | 1050 testChecker( |
| 1015 '/main.dart': ''' | 1051 'conflicts can happen 2', |
| 1052 { |
| 1053 '/main.dart': ''' |
| 1016 class I1 { | 1054 class I1 { |
| 1017 int x; | 1055 int x; |
| 1018 } | 1056 } |
| 1019 class I2 { | 1057 class I2 { |
| 1020 int y; | 1058 int y; |
| 1021 } | 1059 } |
| 1022 | 1060 |
| 1023 class I3 implements I1, I2 { | 1061 class I3 implements I1, I2 { |
| 1024 int x; | 1062 int x; |
| 1025 int y; | 1063 int y; |
| 1026 } | 1064 } |
| 1027 | 1065 |
| 1028 class A { | 1066 class A { |
| 1029 final I1 a; | 1067 final I1 a; |
| 1030 } | 1068 } |
| 1031 | 1069 |
| 1032 class B { | 1070 class B { |
| 1033 final I2 a; | 1071 final I2 a; |
| 1034 } | 1072 } |
| 1035 | 1073 |
| 1036 class C1 extends A implements B { | 1074 class C1 extends A implements B { |
| 1037 I3 get a => null; | 1075 I3 get a => null; |
| 1038 } | 1076 } |
| 1039 | 1077 |
| 1040 class C2 extends A implements B { | 1078 class C2 extends A implements B { |
| 1041 /*severe:InvalidMethodOverride*/get a => null; | 1079 /*severe:InvalidMethodOverride*/get a => null; |
| 1042 } | 1080 } |
| 1043 ''' | 1081 ''' |
| 1044 }, inferFromOverrides: true); | 1082 }, |
| 1045 }); | 1083 inferFromOverrides: true); |
| 1046 | 1084 |
| 1047 test('infer from RHS only if it wont conflict with overridden fields', () { | 1085 testChecker( |
| 1048 testChecker({ | 1086 'infer from RHS only if it wont conflict with overridden fields', |
| 1049 '/main.dart': ''' | 1087 { |
| 1088 '/main.dart': ''' |
| 1050 class A { | 1089 class A { |
| 1051 var x; | 1090 var x; |
| 1052 } | 1091 } |
| 1053 | 1092 |
| 1054 class B extends A { | 1093 class B extends A { |
| 1055 var x = 2; | 1094 var x = 2; |
| 1056 } | 1095 } |
| 1057 | 1096 |
| 1058 foo() { | 1097 foo() { |
| 1059 String y = /*info:DynamicCast*/new B().x; | 1098 String y = /*info:DynamicCast*/new B().x; |
| 1060 int z = /*info:DynamicCast*/new B().x; | 1099 int z = /*info:DynamicCast*/new B().x; |
| 1061 } | 1100 } |
| 1062 ''' | 1101 ''' |
| 1063 }, inferFromOverrides: true); | 1102 }, |
| 1103 inferFromOverrides: true); |
| 1064 | 1104 |
| 1065 testChecker({ | 1105 testChecker( |
| 1066 '/main.dart': ''' | 1106 'infer from RHS only if it wont conflict with overridden fields 2', |
| 1107 { |
| 1108 '/main.dart': ''' |
| 1067 class A { | 1109 class A { |
| 1068 final x; | 1110 final x; |
| 1069 } | 1111 } |
| 1070 | 1112 |
| 1071 class B extends A { | 1113 class B extends A { |
| 1072 final x = 2; | 1114 final x = 2; |
| 1073 } | 1115 } |
| 1074 | 1116 |
| 1075 foo() { | 1117 foo() { |
| 1076 String y = /*severe:StaticTypeError*/new B().x; | 1118 String y = /*severe:StaticTypeError*/new B().x; |
| 1077 int z = new B().x; | 1119 int z = new B().x; |
| 1078 } | 1120 } |
| 1079 ''' | 1121 ''' |
| 1080 }, inferFromOverrides: true); | 1122 }, |
| 1081 }); | 1123 inferFromOverrides: true); |
| 1082 | 1124 |
| 1083 test('infer correctly on multiple variables declared together', () { | 1125 testChecker( |
| 1084 testChecker({ | 1126 'infer correctly on multiple variables declared together', |
| 1085 '/main.dart': ''' | 1127 { |
| 1128 '/main.dart': ''' |
| 1086 class A { | 1129 class A { |
| 1087 var x, y = 2, z = "hi"; | 1130 var x, y = 2, z = "hi"; |
| 1088 } | 1131 } |
| 1089 | 1132 |
| 1090 class B extends A { | 1133 class B extends A { |
| 1091 var x = 2, y = 3, z, w = 2; | 1134 var x = 2, y = 3, z, w = 2; |
| 1092 } | 1135 } |
| 1093 | 1136 |
| 1094 foo() { | 1137 foo() { |
| 1095 String s; | 1138 String s; |
| 1096 int i; | 1139 int i; |
| 1097 | 1140 |
| 1098 s = /*info:DynamicCast*/new B().x; | 1141 s = /*info:DynamicCast*/new B().x; |
| 1099 s = /*severe:StaticTypeError*/new B().y; | 1142 s = /*severe:StaticTypeError*/new B().y; |
| 1100 s = new B().z; | 1143 s = new B().z; |
| 1101 s = /*severe:StaticTypeError*/new B().w; | 1144 s = /*severe:StaticTypeError*/new B().w; |
| 1102 | 1145 |
| 1103 i = /*info:DynamicCast*/new B().x; | 1146 i = /*info:DynamicCast*/new B().x; |
| 1104 i = new B().y; | 1147 i = new B().y; |
| 1105 i = /*severe:StaticTypeError*/new B().z; | 1148 i = /*severe:StaticTypeError*/new B().z; |
| 1106 i = new B().w; | 1149 i = new B().w; |
| 1107 } | 1150 } |
| 1108 ''' | 1151 ''' |
| 1109 }, inferFromOverrides: true); | 1152 }, |
| 1110 }); | 1153 inferFromOverrides: true); |
| 1111 | 1154 |
| 1112 test('infer consts transitively', () { | 1155 testChecker( |
| 1113 testChecker({ | 1156 'infer consts transitively', |
| 1114 '/b.dart': ''' | 1157 { |
| 1158 '/b.dart': ''' |
| 1115 const b1 = 2; | 1159 const b1 = 2; |
| 1116 ''', | 1160 ''', |
| 1117 '/a.dart': ''' | 1161 '/a.dart': ''' |
| 1118 import 'main.dart'; | 1162 import 'main.dart'; |
| 1119 import 'b.dart'; | 1163 import 'b.dart'; |
| 1120 const a1 = m2; | 1164 const a1 = m2; |
| 1121 const a2 = b1; | 1165 const a2 = b1; |
| 1122 ''', | 1166 ''', |
| 1123 '/main.dart': ''' | 1167 '/main.dart': ''' |
| 1124 import 'a.dart'; | 1168 import 'a.dart'; |
| 1125 const m1 = a1; | 1169 const m1 = a1; |
| 1126 const m2 = a2; | 1170 const m2 = a2; |
| 1127 | 1171 |
| 1128 foo() { | 1172 foo() { |
| 1129 int i; | 1173 int i; |
| 1130 i = m1; | 1174 i = m1; |
| 1131 } | 1175 } |
| 1132 ''' | 1176 ''' |
| 1133 }, inferFromOverrides: true, inferTransitively: true); | 1177 }, |
| 1134 }); | 1178 inferFromOverrides: true, |
| 1179 inferTransitively: true); |
| 1135 | 1180 |
| 1136 test('infer statics transitively', () { | 1181 testChecker( |
| 1137 testChecker({ | 1182 'infer statics transitively', |
| 1138 '/b.dart': ''' | 1183 { |
| 1184 '/b.dart': ''' |
| 1139 final b1 = 2; | 1185 final b1 = 2; |
| 1140 ''', | 1186 ''', |
| 1141 '/a.dart': ''' | 1187 '/a.dart': ''' |
| 1142 import 'main.dart'; | 1188 import 'main.dart'; |
| 1143 import 'b.dart'; | 1189 import 'b.dart'; |
| 1144 final a1 = m2; | 1190 final a1 = m2; |
| 1145 class A { | 1191 class A { |
| 1146 static final a2 = b1; | 1192 static final a2 = b1; |
| 1147 } | 1193 } |
| 1148 ''', | 1194 ''', |
| 1149 '/main.dart': ''' | 1195 '/main.dart': ''' |
| 1150 import 'a.dart'; | 1196 import 'a.dart'; |
| 1151 final m1 = a1; | 1197 final m1 = a1; |
| 1152 final m2 = A.a2; | 1198 final m2 = A.a2; |
| 1153 | 1199 |
| 1154 foo() { | 1200 foo() { |
| 1155 int i; | 1201 int i; |
| 1156 i = m1; | 1202 i = m1; |
| 1157 } | 1203 } |
| 1158 ''' | 1204 ''' |
| 1159 }, inferFromOverrides: true, inferTransitively: true); | 1205 }, |
| 1206 inferFromOverrides: true, |
| 1207 inferTransitively: true); |
| 1160 | 1208 |
| 1161 testChecker({ | 1209 testChecker( |
| 1162 '/main.dart': ''' | 1210 'infer statics transitively 2', |
| 1211 { |
| 1212 '/main.dart': ''' |
| 1163 const x1 = 1; | 1213 const x1 = 1; |
| 1164 final x2 = 1; | 1214 final x2 = 1; |
| 1165 final y1 = x1; | 1215 final y1 = x1; |
| 1166 final y2 = x2; | 1216 final y2 = x2; |
| 1167 | 1217 |
| 1168 foo() { | 1218 foo() { |
| 1169 int i; | 1219 int i; |
| 1170 i = y1; | 1220 i = y1; |
| 1171 i = y2; | 1221 i = y2; |
| 1172 } | 1222 } |
| 1173 ''' | 1223 ''' |
| 1174 }, inferFromOverrides: true, inferTransitively: true); | 1224 }, |
| 1225 inferFromOverrides: true, |
| 1226 inferTransitively: true); |
| 1175 | 1227 |
| 1176 testChecker({ | 1228 testChecker( |
| 1177 '/a.dart': ''' | 1229 'infer statics transitively 3', |
| 1230 { |
| 1231 '/a.dart': ''' |
| 1178 const a1 = 3; | 1232 const a1 = 3; |
| 1179 const a2 = 4; | 1233 const a2 = 4; |
| 1180 class A { | 1234 class A { |
| 1181 a3; | 1235 a3; |
| 1182 } | 1236 } |
| 1183 ''', | 1237 ''', |
| 1184 '/main.dart': ''' | 1238 '/main.dart': ''' |
| 1185 import 'a.dart' show a1, A; | 1239 import 'a.dart' show a1, A; |
| 1186 import 'a.dart' as p show a2, A; | 1240 import 'a.dart' as p show a2, A; |
| 1187 const t1 = 1; | 1241 const t1 = 1; |
| 1188 const t2 = t1; | 1242 const t2 = t1; |
| 1189 const t3 = a1; | 1243 const t3 = a1; |
| 1190 const t4 = p.a2; | 1244 const t4 = p.a2; |
| 1191 const t5 = A.a3; | 1245 const t5 = A.a3; |
| 1192 const t6 = p.A.a3; | 1246 const t6 = p.A.a3; |
| 1193 | 1247 |
| 1194 foo() { | 1248 foo() { |
| 1195 int i; | 1249 int i; |
| 1196 i = t1; | 1250 i = t1; |
| 1197 i = t2; | 1251 i = t2; |
| 1198 i = t3; | 1252 i = t3; |
| 1199 i = t4; | 1253 i = t4; |
| 1200 } | 1254 } |
| 1201 ''' | 1255 ''' |
| 1202 }, inferFromOverrides: true, inferTransitively: true); | 1256 }, |
| 1203 }); | 1257 inferFromOverrides: true, |
| 1258 inferTransitively: true); |
| 1204 | 1259 |
| 1205 test('infer statics with method invocations', () { | 1260 testChecker( |
| 1206 testChecker({ | 1261 'infer statics with method invocations', |
| 1207 '/a.dart': ''' | 1262 { |
| 1263 '/a.dart': ''' |
| 1208 m3(String a, String b, [a1,a2]) {} | 1264 m3(String a, String b, [a1,a2]) {} |
| 1209 ''', | 1265 ''', |
| 1210 '/main.dart': ''' | 1266 '/main.dart': ''' |
| 1211 import 'a.dart'; | 1267 import 'a.dart'; |
| 1212 class T { | 1268 class T { |
| 1213 static final T foo = m1(m2(m3('', ''))); | 1269 static final T foo = m1(m2(m3('', ''))); |
| 1214 static T m1(String m) { return null; } | 1270 static T m1(String m) { return null; } |
| 1215 static String m2(e) { return ''; } | 1271 static String m2(e) { return ''; } |
| 1216 } | 1272 } |
| 1217 | 1273 |
| 1218 | 1274 |
| 1219 ''' | 1275 ''' |
| 1220 }, inferFromOverrides: true, inferTransitively: true); | 1276 }, |
| 1221 }); | 1277 inferFromOverrides: true, |
| 1278 inferTransitively: true); |
| 1222 | 1279 |
| 1223 test('downwards inference: miscellaneous', () { | 1280 testChecker( |
| 1224 testChecker({ | 1281 'downwards inference: miscellaneous', |
| 1225 '/main.dart': ''' | 1282 { |
| 1283 '/main.dart': ''' |
| 1226 typedef (T x); | 1284 typedef (T x); |
| 1227 class A<T> { | 1285 class A<T> { |
| 1228 Function2<T> x; | 1286 Function2<T> x; |
| 1229 A(this.x); | 1287 A(this.x); |
| 1230 } | 1288 } |
| 1231 void main() { | 1289 void main() { |
| 1232 { // Variables, nested literals | 1290 { // Variables, nested literals |
| 1233 var x = "hello"; | 1291 var x = "hello"; |
| 1234 var y = 3; | 1292 var y = 3; |
| 1235 void f(List<Map<int, String>> l) {}; | 1293 void f(List<Map<int, String>> l) {}; |
| 1236 f(/*info:InferredTypeLiteral*/[{y: x}]); | 1294 f(/*info:InferredTypeLiteral*/[{y: x}]); |
| 1237 } | 1295 } |
| 1238 { | 1296 { |
| 1239 int f(int x) {}; | 1297 int f(int x) {}; |
| 1240 A<int> a = /*info:InferredTypeAllocation*/new A(f); | 1298 A<int> a = /*info:InferredTypeAllocation*/new A(f); |
| 1241 } | 1299 } |
| 1242 } | 1300 } |
| 1243 ''' | 1301 ''' |
| 1244 }, inferDownwards: true); | 1302 }, |
| 1245 }); | 1303 inferDownwards: true); |
| 1246 | 1304 |
| 1247 test('downwards inference on instance creations', () { | 1305 group('downwards inference on instance creations', () { |
| 1248 String mk(String info) => ''' | 1306 String mk(String info) => ''' |
| 1249 class A<S, T> { | 1307 class A<S, T> { |
| 1250 S x; | 1308 S x; |
| 1251 T y; | 1309 T y; |
| 1252 A(this.x, this.y); | 1310 A(this.x, this.y); |
| 1253 A.named(this.x, this.y); | 1311 A.named(this.x, this.y); |
| 1254 } | 1312 } |
| 1255 | 1313 |
| 1256 class B<S, T> extends A<T, S> { | 1314 class B<S, T> extends A<T, S> { |
| 1257 B(S y, T x) : super(x, y); | 1315 B(S y, T x) : super(x, y); |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1332 { // Check named and optional arguments | 1390 { // Check named and optional arguments |
| 1333 A<int, String> a0 = /*$info*/new F(3, "hello", a: [3], b: ["hello"]); | 1391 A<int, String> a0 = /*$info*/new F(3, "hello", a: [3], b: ["hello"]); |
| 1334 A<int, String> a1 = /*severe:StaticTypeError*/new F(3, "hello", a: ["h
ello"], b:[3]); | 1392 A<int, String> a1 = /*severe:StaticTypeError*/new F(3, "hello", a: ["h
ello"], b:[3]); |
| 1335 A<int, String> a2 = /*$info*/new F.named(3, "hello", 3, "hello"); | 1393 A<int, String> a2 = /*$info*/new F.named(3, "hello", 3, "hello"); |
| 1336 A<int, String> a3 = /*$info*/new F.named(3, "hello"); | 1394 A<int, String> a3 = /*$info*/new F.named(3, "hello"); |
| 1337 A<int, String> a4 = /*severe:StaticTypeError*/new F.named(3, "hello",
"hello", 3); | 1395 A<int, String> a4 = /*severe:StaticTypeError*/new F.named(3, "hello",
"hello", 3); |
| 1338 A<int, String> a5 = /*severe:StaticTypeError*/new F.named(3, "hello",
"hello"); | 1396 A<int, String> a5 = /*severe:StaticTypeError*/new F.named(3, "hello",
"hello"); |
| 1339 } | 1397 } |
| 1340 } | 1398 } |
| 1341 '''; | 1399 '''; |
| 1342 testChecker({'/main.dart': mk("info:InferredTypeAllocation")}, | 1400 testChecker( |
| 1401 'infer downwards', {'/main.dart': mk("info:InferredTypeAllocation")}, |
| 1343 inferDownwards: true); | 1402 inferDownwards: true); |
| 1344 testChecker({'/main.dart': mk("severe:StaticTypeError")}, | 1403 testChecker( |
| 1404 'no infer downwards', {'/main.dart': mk("severe:StaticTypeError")}, |
| 1345 inferDownwards: false); | 1405 inferDownwards: false); |
| 1346 }); | 1406 }); |
| 1347 | 1407 |
| 1348 test('downwards inference on list literals', () { | 1408 group('downwards inference on list literals', () { |
| 1349 String mk(String info) => ''' | 1409 String mk(String info) => ''' |
| 1350 void foo([List<String> list1 = /*$info*/const [], | 1410 void foo([List<String> list1 = /*$info*/const [], |
| 1351 List<String> list2 = /*severe:StaticTypeError*/const [42]]) { | 1411 List<String> list2 = /*severe:StaticTypeError*/const [42]]) { |
| 1352 } | 1412 } |
| 1353 | 1413 |
| 1354 void main() { | 1414 void main() { |
| 1355 { | 1415 { |
| 1356 List<int> l0 = /*$info*/[]; | 1416 List<int> l0 = /*$info*/[]; |
| 1357 List<int> l1 = /*$info*/[3]; | 1417 List<int> l1 = /*$info*/[3]; |
| 1358 List<int> l2 = /*severe:StaticTypeError*/["hello"]; | 1418 List<int> l2 = /*severe:StaticTypeError*/["hello"]; |
| (...skipping 18 matching lines...) Expand all Loading... |
| 1377 Iterable<int> i3 = /*severe:StaticTypeError*/["hello", 3]; | 1437 Iterable<int> i3 = /*severe:StaticTypeError*/["hello", 3]; |
| 1378 } | 1438 } |
| 1379 { | 1439 { |
| 1380 const List<int> c0 = /*$info*/const []; | 1440 const List<int> c0 = /*$info*/const []; |
| 1381 const List<int> c1 = /*$info*/const [3]; | 1441 const List<int> c1 = /*$info*/const [3]; |
| 1382 const List<int> c2 = /*severe:StaticTypeError*/const ["hello"]; | 1442 const List<int> c2 = /*severe:StaticTypeError*/const ["hello"]; |
| 1383 const List<int> c3 = /*severe:StaticTypeError*/const ["hello", 3]; | 1443 const List<int> c3 = /*severe:StaticTypeError*/const ["hello", 3]; |
| 1384 } | 1444 } |
| 1385 } | 1445 } |
| 1386 '''; | 1446 '''; |
| 1387 testChecker({'/main.dart': mk("info:InferredTypeLiteral")}, | 1447 testChecker( |
| 1448 'infer downwards', {'/main.dart': mk("info:InferredTypeLiteral")}, |
| 1388 inferDownwards: true); | 1449 inferDownwards: true); |
| 1389 testChecker({'/main.dart': mk("severe:StaticTypeError")}, | 1450 testChecker( |
| 1451 'no infer downwards', {'/main.dart': mk("severe:StaticTypeError")}, |
| 1390 inferDownwards: false); | 1452 inferDownwards: false); |
| 1391 }); | 1453 }); |
| 1392 | 1454 |
| 1393 test('downwards inference on function arguments', () { | 1455 group('downwards inference on function arguments', () { |
| 1394 String mk(String info) => ''' | 1456 String mk(String info) => ''' |
| 1395 void f0(List<int> a) {}; | 1457 void f0(List<int> a) {}; |
| 1396 void f1({List<int> a}) {}; | 1458 void f1({List<int> a}) {}; |
| 1397 void f2(Iterable<int> a) {}; | 1459 void f2(Iterable<int> a) {}; |
| 1398 void f3(Iterable<Iterable<int>> a) {}; | 1460 void f3(Iterable<Iterable<int>> a) {}; |
| 1399 void f4({Iterable<Iterable<int>> a}) {}; | 1461 void f4({Iterable<Iterable<int>> a}) {}; |
| 1400 void main() { | 1462 void main() { |
| 1401 f0(/*$info*/[]); | 1463 f0(/*$info*/[]); |
| 1402 f0(/*$info*/[3]); | 1464 f0(/*$info*/[3]); |
| 1403 f0(/*severe:StaticTypeError*/["hello"]); | 1465 f0(/*severe:StaticTypeError*/["hello"]); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 1417 f3(/*$info*/[[3]]); | 1479 f3(/*$info*/[[3]]); |
| 1418 f3(/*severe:StaticTypeError*/[["hello"]]); | 1480 f3(/*severe:StaticTypeError*/[["hello"]]); |
| 1419 f3(/*severe:StaticTypeError*/[["hello"], [3]]); | 1481 f3(/*severe:StaticTypeError*/[["hello"], [3]]); |
| 1420 | 1482 |
| 1421 f4(a: /*$info*/[]); | 1483 f4(a: /*$info*/[]); |
| 1422 f4(a: /*$info*/[[3]]); | 1484 f4(a: /*$info*/[[3]]); |
| 1423 f4(a: /*severe:StaticTypeError*/[["hello"]]); | 1485 f4(a: /*severe:StaticTypeError*/[["hello"]]); |
| 1424 f4(a: /*severe:StaticTypeError*/[["hello"], [3]]); | 1486 f4(a: /*severe:StaticTypeError*/[["hello"], [3]]); |
| 1425 } | 1487 } |
| 1426 '''; | 1488 '''; |
| 1427 testChecker({'/main.dart': mk("info:InferredTypeLiteral")}, | 1489 testChecker( |
| 1490 'infer downwards', {'/main.dart': mk("info:InferredTypeLiteral")}, |
| 1428 inferDownwards: true); | 1491 inferDownwards: true); |
| 1429 testChecker({'/main.dart': mk("severe:StaticTypeError")}, | 1492 testChecker( |
| 1493 'no infer downwards', {'/main.dart': mk("severe:StaticTypeError")}, |
| 1430 inferDownwards: false); | 1494 inferDownwards: false); |
| 1431 }); | 1495 }); |
| 1432 | 1496 |
| 1433 test('downwards inference on map literals', () { | 1497 group('downwards inference on map literals', () { |
| 1434 String mk(String info) => ''' | 1498 String mk(String info) => ''' |
| 1435 void foo([Map<int, String> m1 = /*$info*/const {1: "hello"}, | 1499 void foo([Map<int, String> m1 = /*$info*/const {1: "hello"}, |
| 1436 Map<int, String> m1 = /*severe:StaticTypeError*/const {"hello":
"world"}]) { | 1500 Map<int, String> m1 = /*severe:StaticTypeError*/const {"hello":
"world"}]) { |
| 1437 } | 1501 } |
| 1438 void main() { | 1502 void main() { |
| 1439 { | 1503 { |
| 1440 Map<int, String> l0 = /*$info*/{}; | 1504 Map<int, String> l0 = /*$info*/{}; |
| 1441 Map<int, String> l1 = /*$info*/{3: "hello"}; | 1505 Map<int, String> l1 = /*$info*/{3: "hello"}; |
| 1442 Map<int, String> l2 = /*severe:StaticTypeError*/{"hello": "hello"}; | 1506 Map<int, String> l2 = /*severe:StaticTypeError*/{"hello": "hello"}; |
| 1443 Map<int, String> l3 = /*severe:StaticTypeError*/{3: 3}; | 1507 Map<int, String> l3 = /*severe:StaticTypeError*/{3: 3}; |
| (...skipping 27 matching lines...) Expand all Loading... |
| 1471 } | 1535 } |
| 1472 { | 1536 { |
| 1473 const Map<int, String> l0 = /*$info*/const {}; | 1537 const Map<int, String> l0 = /*$info*/const {}; |
| 1474 const Map<int, String> l1 = /*$info*/const {3: "hello"}; | 1538 const Map<int, String> l1 = /*$info*/const {3: "hello"}; |
| 1475 const Map<int, String> l2 = /*severe:StaticTypeError*/const {"hello":
"hello"}; | 1539 const Map<int, String> l2 = /*severe:StaticTypeError*/const {"hello":
"hello"}; |
| 1476 const Map<int, String> l3 = /*severe:StaticTypeError*/const {3: 3}; | 1540 const Map<int, String> l3 = /*severe:StaticTypeError*/const {3: 3}; |
| 1477 const Map<int, String> l4 = /*severe:StaticTypeError*/const {3:"hello"
, "hello": 3}; | 1541 const Map<int, String> l4 = /*severe:StaticTypeError*/const {3:"hello"
, "hello": 3}; |
| 1478 } | 1542 } |
| 1479 } | 1543 } |
| 1480 '''; | 1544 '''; |
| 1481 testChecker({'/main.dart': mk("info:InferredTypeLiteral")}, | 1545 testChecker( |
| 1546 'infer downwards', {'/main.dart': mk("info:InferredTypeLiteral")}, |
| 1482 inferDownwards: true); | 1547 inferDownwards: true); |
| 1483 testChecker({'/main.dart': mk("severe:StaticTypeError")}, | 1548 testChecker( |
| 1549 'no infer downwards', {'/main.dart': mk("severe:StaticTypeError")}, |
| 1484 inferDownwards: false); | 1550 inferDownwards: false); |
| 1485 }); | 1551 }); |
| 1486 | 1552 |
| 1487 test('downwards inference on function expressions', () { | 1553 testChecker( |
| 1488 testChecker({ | 1554 'downwards inference on function expressions', |
| 1489 '/main.dart': ''' | 1555 { |
| 1556 '/main.dart': ''' |
| 1490 typedef T Function2<S, T>(S x); | 1557 typedef T Function2<S, T>(S x); |
| 1491 | 1558 |
| 1492 void main () { | 1559 void main () { |
| 1493 { | 1560 { |
| 1494 Function2<int, String> l0 = (int x) => null; | 1561 Function2<int, String> l0 = (int x) => null; |
| 1495 Function2<int, String> l1 = (int x) => "hello"; | 1562 Function2<int, String> l1 = (int x) => "hello"; |
| 1496 Function2<int, String> l2 = /*severe:StaticTypeError*/(String x) => "h
ello"; | 1563 Function2<int, String> l2 = /*severe:StaticTypeError*/(String x) => "h
ello"; |
| 1497 Function2<int, String> l3 = /*severe:StaticTypeError*/(int x) => 3; | 1564 Function2<int, String> l3 = /*severe:StaticTypeError*/(int x) => 3; |
| 1498 Function2<int, String> l4 = /*warning:UninferredClosure should be seve
re:StaticTypeError*/(int x) {return 3}; | 1565 Function2<int, String> l4 = /*warning:UninferredClosure should be seve
re:StaticTypeError*/(int x) {return 3}; |
| 1499 } | 1566 } |
| (...skipping 12 matching lines...) Expand all Loading... |
| 1512 } | 1579 } |
| 1513 { | 1580 { |
| 1514 Function2<int, int> l0 = /*info:InferredTypeClosure*/(x) => x; | 1581 Function2<int, int> l0 = /*info:InferredTypeClosure*/(x) => x; |
| 1515 Function2<int, int> l1 = /*info:InferredTypeClosure*/(x) => /*info:Dyn
amicInvoke should be pass*/x+1; | 1582 Function2<int, int> l1 = /*info:InferredTypeClosure*/(x) => /*info:Dyn
amicInvoke should be pass*/x+1; |
| 1516 Function2<int, String> l2 = /*info:InferredTypeClosure should be sever
e:StaticTypeError*/(x) => x; | 1583 Function2<int, String> l2 = /*info:InferredTypeClosure should be sever
e:StaticTypeError*/(x) => x; |
| 1517 Function2<int, String> l3 = /*info:InferredTypeClosure should be sever
e:StaticTypeError*/(x) => /*info:DynamicInvoke should be pass*/x.substring(3); | 1584 Function2<int, String> l3 = /*info:InferredTypeClosure should be sever
e:StaticTypeError*/(x) => /*info:DynamicInvoke should be pass*/x.substring(3); |
| 1518 Function2<String, String> l4 = /*info:InferredTypeClosure*/(x) => /*in
fo:DynamicInvoke should be pass*/x.substring(3); | 1585 Function2<String, String> l4 = /*info:InferredTypeClosure*/(x) => /*in
fo:DynamicInvoke should be pass*/x.substring(3); |
| 1519 } | 1586 } |
| 1520 } | 1587 } |
| 1521 ''' | 1588 ''' |
| 1522 }, inferDownwards: true); | 1589 }, |
| 1523 }); | 1590 inferDownwards: true); |
| 1524 | 1591 |
| 1525 test( | 1592 testChecker('inferred initializing formal checks default value', { |
| 1526 'inferred initializing formal checks default value', | 1593 '/main.dart': ''' |
| 1527 () => testChecker({ | |
| 1528 '/main.dart': ''' | |
| 1529 class Foo { | 1594 class Foo { |
| 1530 var x = 1; | 1595 var x = 1; |
| 1531 Foo([this.x = /*severe:StaticTypeError*/"1"]); | 1596 Foo([this.x = /*severe:StaticTypeError*/"1"]); |
| 1532 }''' | 1597 }''' |
| 1533 })); | 1598 }); |
| 1534 } | 1599 } |
| OLD | NEW |