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 library analyzer.src.task.strong_mode; | 5 library analyzer.src.task.strong_mode; |
6 | 6 |
7 import 'dart:collection'; | 7 import 'dart:collection'; |
8 | 8 |
9 import 'package:analyzer/src/generated/ast.dart'; | 9 import 'package:analyzer/src/generated/ast.dart'; |
10 import 'package:analyzer/src/generated/element.dart'; | 10 import 'package:analyzer/src/generated/element.dart'; |
(...skipping 276 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
287 if (overriddenGetters.isNotEmpty && _onlyGetters(overriddenGetters)) { | 287 if (overriddenGetters.isNotEmpty && _onlyGetters(overriddenGetters)) { |
288 newType = _computeReturnType(overriddenGetters); | 288 newType = _computeReturnType(overriddenGetters); |
289 List<ExecutableElement> overriddenSetters = inheritanceManager | 289 List<ExecutableElement> overriddenSetters = inheritanceManager |
290 .lookupOverrides( | 290 .lookupOverrides( |
291 fieldElement.enclosingElement, fieldElement.name + '='); | 291 fieldElement.enclosingElement, fieldElement.name + '='); |
292 if (!_isCompatible(newType, overriddenSetters)) { | 292 if (!_isCompatible(newType, overriddenSetters)) { |
293 newType = null; | 293 newType = null; |
294 } | 294 } |
295 } | 295 } |
296 // | 296 // |
297 // Then, if none was found, infer the type from the initialization | 297 // If there is no overridden getter or if the overridden getter's type is |
298 // expression. | 298 // dynamic, then we can infer the type from the initialization expression |
| 299 // without breaking subtype rules. We could potentially infer a consistent |
| 300 // return type even if the overridden getter's type was not dynamic, but |
| 301 // choose not to for simplicity. The field is required to be final to |
| 302 // prevent choosing a type that is inconsistent with assignments we cannot |
| 303 // analyze. |
299 // | 304 // |
300 if (newType == null) { | 305 if (newType == null || newType.isDynamic) { |
301 if (fieldElement.initializer != null && | 306 if (fieldElement.initializer != null && |
302 (fieldElement.isFinal || overriddenGetters.isEmpty)) { | 307 (fieldElement.isFinal || overriddenGetters.isEmpty)) { |
303 newType = fieldElement.initializer.returnType; | 308 newType = fieldElement.initializer.returnType; |
304 } | 309 } |
305 } | 310 } |
306 if (newType == null || newType.isBottom) { | 311 if (newType == null || newType.isBottom) { |
307 newType = typeProvider.dynamicType; | 312 newType = typeProvider.dynamicType; |
308 } | 313 } |
309 (fieldElement as FieldElementImpl).type = newType; | 314 (fieldElement as FieldElementImpl).type = newType; |
310 setReturnType(fieldElement.getter, newType); | 315 setReturnType(fieldElement.getter, newType); |
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
472 results.add(element); | 477 results.add(element); |
473 } | 478 } |
474 } | 479 } |
475 } | 480 } |
476 } | 481 } |
477 | 482 |
478 /** | 483 /** |
479 * A class of exception that is not used anywhere else. | 484 * A class of exception that is not used anywhere else. |
480 */ | 485 */ |
481 class _CycleException implements Exception {} | 486 class _CycleException implements Exception {} |
OLD | NEW |