| 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 /// Defines static information collected by the type checker and used later by | 5 /// Defines static information collected by the type checker and used later by |
| 6 /// emitters to generate code. | 6 /// emitters to generate code. |
| 7 // TODO(jmesserly): this was ported from package:dev_compiler, and needs to be | 7 // TODO(jmesserly): this was ported from package:dev_compiler, and needs to be |
| 8 // refactored to fit into analyzer. | 8 // refactored to fit into analyzer. |
| 9 library analyzer.src.task.strong.info; | 9 library analyzer.src.task.strong.info; |
| 10 | 10 |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 100 | 100 |
| 101 Cast get cast => _cast; | 101 Cast get cast => _cast; |
| 102 | 102 |
| 103 DartType get convertedType => _cast.toType; | 103 DartType get convertedType => _cast.toType; |
| 104 | 104 |
| 105 @override | 105 @override |
| 106 String get message => 'Unsound implicit cast from {0} to {1}'; | 106 String get message => 'Unsound implicit cast from {0} to {1}'; |
| 107 | 107 |
| 108 // Factory to create correct DownCast variant. | 108 // Factory to create correct DownCast variant. |
| 109 static StaticInfo create( | 109 static StaticInfo create( |
| 110 StrongTypeSystemImpl rules, Expression expression, Cast cast, | 110 StrongTypeSystemImpl rules, Expression expression, Cast cast) { |
| 111 {String reason}) { | |
| 112 final fromT = cast.fromType; | 111 final fromT = cast.fromType; |
| 113 final toT = cast.toType; | 112 final toT = cast.toType; |
| 114 | 113 |
| 115 // toT <:_R fromT => to <: fromT | 114 // toT <:_R fromT => to <: fromT |
| 116 // NB: classes with call methods are subtypes of function | 115 // NB: classes with call methods are subtypes of function |
| 117 // types, but the function type is not assignable to the class | 116 // types, but the function type is not assignable to the class |
| 118 assert(toT.isSubtypeOf(fromT) || fromT.isAssignableTo(toT)); | 117 assert(toT.isSubtypeOf(fromT) || fromT.isAssignableTo(toT)); |
| 119 | 118 |
| 120 // Handle null call specially. | 119 // Handle null call specially. |
| 121 if (expression is NullLiteral) { | 120 if (expression is NullLiteral) { |
| 122 // TODO(vsm): Create a NullCast for this once we revisit nonnullability. | 121 // TODO(vsm): Create a NullCast for this once we revisit nonnullability. |
| 123 return new DownCastImplicit(rules, expression, cast); | 122 return new DownCastImplicit(rules, expression, cast); |
| 124 } | 123 } |
| 125 | 124 |
| 126 // Inference "casts": | 125 // Inference "casts": |
| 127 if (expression is Literal || expression is FunctionExpression) { | 126 if (expression is Literal || expression is FunctionExpression) { |
| 128 // fromT should be an exact type - this will almost certainly fail at | 127 // fromT should be an exact type - this will almost certainly fail at |
| 129 // runtime. | 128 // runtime. |
| 130 return new StaticTypeError(rules, expression, toT, reason: reason); | 129 return new StaticTypeError(rules, expression, toT); |
| 131 } | 130 } |
| 131 |
| 132 if (expression is InstanceCreationExpression) { | 132 if (expression is InstanceCreationExpression) { |
| 133 ConstructorElement e = expression.staticElement; | 133 ConstructorElement e = expression.staticElement; |
| 134 if (e == null || !e.isFactory) { | 134 if (e == null || !e.isFactory) { |
| 135 // fromT should be an exact type - this will almost certainly fail at | 135 // fromT should be an exact type - this will almost certainly fail at |
| 136 // runtime. | 136 // runtime. |
| 137 return new StaticTypeError(rules, expression, toT, reason: reason); | 137 return new StaticTypeError(rules, expression, toT); |
| 138 } | 138 } |
| 139 } | 139 } |
| 140 | 140 |
| 141 Element element = null; | 141 Element element = null; |
| 142 if (expression is PropertyAccess) { | 142 if (expression is PropertyAccess) { |
| 143 element = expression.propertyName.staticElement; | 143 element = expression.propertyName.staticElement; |
| 144 } else if (expression is Identifier) { | 144 } else if (expression is Identifier) { |
| 145 element = expression.staticElement; | 145 element = expression.staticElement; |
| 146 } | 146 } |
| 147 // First class functions and static methods, where we know the original | 147 // First class functions and static methods, where we know the original |
| 148 // declaration, will have an exact type, so we know a downcast will fail. | 148 // declaration, will have an exact type, so we know a downcast will fail. |
| 149 if (element is FunctionElement || | 149 if (element is FunctionElement || |
| 150 element is MethodElement && element.isStatic) { | 150 element is MethodElement && element.isStatic) { |
| 151 return new StaticTypeError(rules, expression, toT, reason: reason); | 151 return new StaticTypeError(rules, expression, toT); |
| 152 } | 152 } |
| 153 | 153 |
| 154 // TODO(vsm): Change this to an assert when we have generic methods and | 154 // TODO(vsm): Change this to an assert when we have generic methods and |
| 155 // fix TypeRules._coerceTo to disallow implicit sideways casts. | 155 // fix TypeRules._coerceTo to disallow implicit sideways casts. |
| 156 if (!rules.isSubtypeOf(toT, fromT)) { | 156 if (!rules.isSubtypeOf(toT, fromT)) { |
| 157 assert(toT.isSubtypeOf(fromT) || fromT.isAssignableTo(toT)); | 157 assert(toT.isSubtypeOf(fromT) || fromT.isAssignableTo(toT)); |
| 158 return new DownCastComposite(rules, expression, cast); | 158 return new DownCastComposite(rules, expression, cast); |
| 159 } | 159 } |
| 160 | 160 |
| 161 // Composite cast: these are more likely to fail. | 161 // Composite cast: these are more likely to fail. |
| (...skipping 387 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 549 } | 549 } |
| 550 | 550 |
| 551 // TODO(jmesserly): review the usage of error codes. We probably want our own, | 551 // TODO(jmesserly): review the usage of error codes. We probably want our own, |
| 552 // as well as some DDC specific [ErrorType]s. | 552 // as well as some DDC specific [ErrorType]s. |
| 553 ErrorCode toErrorCode(); | 553 ErrorCode toErrorCode(); |
| 554 } | 554 } |
| 555 | 555 |
| 556 class StaticTypeError extends StaticError { | 556 class StaticTypeError extends StaticError { |
| 557 final DartType baseType; | 557 final DartType baseType; |
| 558 final DartType expectedType; | 558 final DartType expectedType; |
| 559 String reason = null; | |
| 560 | 559 |
| 561 StaticTypeError(TypeSystem rules, Expression expression, this.expectedType, | 560 StaticTypeError(TypeSystem rules, Expression expression, this.expectedType) |
| 562 {this.reason}) | |
| 563 : baseType = expression.staticType ?? DynamicTypeImpl.instance, | 561 : baseType = expression.staticType ?? DynamicTypeImpl.instance, |
| 564 super(expression); | 562 super(expression); |
| 565 | 563 |
| 566 @override | 564 @override |
| 567 List<Object> get arguments => [node, baseType, expectedType]; | 565 List<Object> get arguments => [node, baseType, expectedType]; |
| 568 @override | 566 @override |
| 569 String get message => | 567 String get message => 'Type check failed: {0} ({1}) is not of type {2}'; |
| 570 'Type check failed: {0} ({1}) is not of type {2}' + | |
| 571 ((reason == null) ? '' : ' because $reason'); | |
| 572 | 568 |
| 573 @override | 569 @override |
| 574 String get name => 'STRONG_MODE_STATIC_TYPE_ERROR'; | 570 String get name => 'STRONG_MODE_STATIC_TYPE_ERROR'; |
| 575 } | 571 } |
| OLD | NEW |