| 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 was ported from package:dev_compiler, and needs to be | 5 // TODO(jmesserly): this was ported from package:dev_compiler, and needs to be |
| 6 // refactored to fit into analyzer. | 6 // refactored to fit into analyzer. |
| 7 library analyzer.src.task.strong.checker; | 7 library analyzer.src.task.strong.checker; |
| 8 | 8 |
| 9 import 'package:analyzer/analyzer.dart'; | 9 import 'package:analyzer/analyzer.dart'; |
| 10 import 'package:analyzer/dart/ast/ast.dart'; | 10 import 'package:analyzer/dart/ast/ast.dart'; |
| (...skipping 709 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 720 if (from == null) { | 720 if (from == null) { |
| 721 from = _getStaticType(expr); | 721 from = _getStaticType(expr); |
| 722 } | 722 } |
| 723 | 723 |
| 724 // We can use anything as void. | 724 // We can use anything as void. |
| 725 if (to.isVoid) return; | 725 if (to.isVoid) return; |
| 726 | 726 |
| 727 // fromT <: toT, no coercion needed. | 727 // fromT <: toT, no coercion needed. |
| 728 if (rules.isSubtypeOf(from, to)) return; | 728 if (rules.isSubtypeOf(from, to)) return; |
| 729 | 729 |
| 730 // TODO(vsm): We can get rid of the second clause if we disallow | |
| 731 // all sideways casts - see TODO below. | |
| 732 // ------- | |
| 733 // Note: a function type is never assignable to a class per the Dart | 730 // Note: a function type is never assignable to a class per the Dart |
| 734 // spec - even if it has a compatible call method. We disallow as | 731 // spec - even if it has a compatible call method. We disallow as |
| 735 // well for consistency. | 732 // well for consistency. |
| 736 if ((from is FunctionType && rules.getCallMethodType(to) != null) || | 733 if (from is FunctionType && rules.getCallMethodType(to) != null) { |
| 737 (to is FunctionType && rules.getCallMethodType(from) != null)) { | |
| 738 return; | 734 return; |
| 739 } | 735 } |
| 740 | 736 |
| 741 // Downcast if toT <: fromT | 737 // Downcast if toT <: fromT |
| 742 if (rules.isSubtypeOf(to, from)) { | 738 if (rules.isSubtypeOf(to, from)) { |
| 743 _recordImplicitCast(expr, from, to); | 739 _recordImplicitCast(expr, from, to); |
| 744 return; | 740 return; |
| 745 } | 741 } |
| 746 | 742 |
| 747 // TODO(vsm): Once we have generic methods, we should delete this | 743 // Anything else is an illegal sideways cast. |
| 748 // workaround. These sideways casts are always ones we warn about | 744 // However, these will have been reported already in error_verifier, so we |
| 749 // - i.e., we think they are likely to fail at runtime. | 745 // don't need to report them again. |
| 750 // ------- | |
| 751 // Downcast if toT <===> fromT | |
| 752 // The intention here is to allow casts that are sideways in the restricted | |
| 753 // type system, but allowed in the regular dart type system, since these | |
| 754 // are likely to succeed. The canonical example is List<dynamic> and | |
| 755 // Iterable<T> for some concrete T (e.g. Object). These are unrelated | |
| 756 // in the restricted system, but List<dynamic> <: Iterable<T> in dart. | |
| 757 if (from.isAssignableTo(to)) { | |
| 758 _recordImplicitCast(expr, from, to); | |
| 759 } | |
| 760 } | 746 } |
| 761 | 747 |
| 762 void _checkFieldAccess(AstNode node, AstNode target, SimpleIdentifier field) { | 748 void _checkFieldAccess(AstNode node, AstNode target, SimpleIdentifier field) { |
| 763 if (field.staticElement == null && !_isObjectProperty(target, field)) { | 749 if (field.staticElement == null && !_isObjectProperty(target, field)) { |
| 764 _recordDynamicInvoke(node, target); | 750 _recordDynamicInvoke(node, target); |
| 765 } | 751 } |
| 766 node.visitChildren(this); | 752 node.visitChildren(this); |
| 767 } | 753 } |
| 768 | 754 |
| 769 /** | 755 /** |
| (...skipping 274 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1044 | 1030 |
| 1045 /// Records an implicit cast for the [expression] from [fromType] to [toType]. | 1031 /// Records an implicit cast for the [expression] from [fromType] to [toType]. |
| 1046 /// | 1032 /// |
| 1047 /// This will emit the appropriate error/warning/hint message as well as mark | 1033 /// This will emit the appropriate error/warning/hint message as well as mark |
| 1048 /// the AST node. | 1034 /// the AST node. |
| 1049 void _recordImplicitCast( | 1035 void _recordImplicitCast( |
| 1050 Expression expression, DartType fromType, DartType toType) { | 1036 Expression expression, DartType fromType, DartType toType) { |
| 1051 // toT <:_R fromT => to <: fromT | 1037 // toT <:_R fromT => to <: fromT |
| 1052 // NB: classes with call methods are subtypes of function | 1038 // NB: classes with call methods are subtypes of function |
| 1053 // types, but the function type is not assignable to the class | 1039 // types, but the function type is not assignable to the class |
| 1054 assert(toType.isSubtypeOf(fromType) || fromType.isAssignableTo(toType)); | 1040 assert(toType.isSubtypeOf(fromType)); |
| 1055 | 1041 |
| 1056 // Inference "casts": | 1042 // Inference "casts": |
| 1057 if (expression is Literal || expression is FunctionExpression) { | 1043 if (expression is Literal || expression is FunctionExpression) { |
| 1058 // fromT should be an exact type - this will almost certainly fail at | 1044 // fromT should be an exact type - this will almost certainly fail at |
| 1059 // runtime. | 1045 // runtime. |
| 1060 _recordMessage(expression, StrongModeCode.STATIC_TYPE_ERROR, | 1046 _recordMessage(expression, StrongModeCode.STATIC_TYPE_ERROR, |
| 1061 [expression, fromType, toType]); | 1047 [expression, fromType, toType]); |
| 1062 return; | 1048 return; |
| 1063 } | 1049 } |
| 1064 | 1050 |
| (...skipping 433 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1498 var visited = new Set<InterfaceType>(); | 1484 var visited = new Set<InterfaceType>(); |
| 1499 do { | 1485 do { |
| 1500 visited.add(current); | 1486 visited.add(current); |
| 1501 current.mixins.reversed.forEach( | 1487 current.mixins.reversed.forEach( |
| 1502 (m) => _checkIndividualOverridesFromClass(node, m, seen, true)); | 1488 (m) => _checkIndividualOverridesFromClass(node, m, seen, true)); |
| 1503 _checkIndividualOverridesFromClass(node, current.superclass, seen, true); | 1489 _checkIndividualOverridesFromClass(node, current.superclass, seen, true); |
| 1504 current = current.superclass; | 1490 current = current.superclass; |
| 1505 } while (!current.isObject && !visited.contains(current)); | 1491 } while (!current.isObject && !visited.contains(current)); |
| 1506 } | 1492 } |
| 1507 } | 1493 } |
| OLD | NEW |