| OLD | NEW |
| 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2016, 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 library kernel.type_environment; | 4 library kernel.type_environment; |
| 5 | 5 |
| 6 import 'ast.dart'; | 6 import 'ast.dart'; |
| 7 import 'class_hierarchy.dart'; | 7 import 'class_hierarchy.dart'; |
| 8 import 'core_types.dart'; | 8 import 'core_types.dart'; |
| 9 import 'type_algebra.dart'; | 9 import 'type_algebra.dart'; |
| 10 | 10 |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 88 | 88 |
| 89 /// True if [member] is a binary operator that returns an `int` if both | 89 /// True if [member] is a binary operator that returns an `int` if both |
| 90 /// operands are `int`, and otherwise returns `double`. | 90 /// operands are `int`, and otherwise returns `double`. |
| 91 /// | 91 /// |
| 92 /// This is a case of type-based overloading, which in Dart is only supported | 92 /// This is a case of type-based overloading, which in Dart is only supported |
| 93 /// by giving special treatment to certain arithmetic operators. | 93 /// by giving special treatment to certain arithmetic operators. |
| 94 bool isOverloadedArithmeticOperator(Procedure member) { | 94 bool isOverloadedArithmeticOperator(Procedure member) { |
| 95 Class class_ = member.enclosingClass; | 95 Class class_ = member.enclosingClass; |
| 96 if (class_ == coreTypes.intClass || class_ == coreTypes.numClass) { | 96 if (class_ == coreTypes.intClass || class_ == coreTypes.numClass) { |
| 97 String name = member.name.name; | 97 String name = member.name.name; |
| 98 return name == '+' || name == '-' || name == '*' || name == 'remainder'; | 98 return name == '+' || |
| 99 name == '-' || |
| 100 name == '*' || |
| 101 name == 'remainder' || |
| 102 name == '%'; |
| 99 } | 103 } |
| 100 return false; | 104 return false; |
| 101 } | 105 } |
| 102 | 106 |
| 103 /// Returns the static return type of an overloaded arithmetic operator | 107 /// Returns the static return type of an overloaded arithmetic operator |
| 104 /// (see [isOverloadedArithmeticOperator]) given the static type of the | 108 /// (see [isOverloadedArithmeticOperator]) given the static type of the |
| 105 /// operands. | 109 /// operands. |
| 106 /// | 110 /// |
| 107 /// If both types are `int`, the returned type is `int`. | 111 /// If both types are `int`, the returned type is `int`. |
| 108 /// If either type is `double`, the returned type is `double`. | 112 /// If either type is `double`, the returned type is `double`. |
| (...skipping 12 matching lines...) Expand all Loading... |
| 121 /// This lives in a separate class so it can be tested independently of the SDK. | 125 /// This lives in a separate class so it can be tested independently of the SDK. |
| 122 abstract class SubtypeTester { | 126 abstract class SubtypeTester { |
| 123 InterfaceType get objectType; | 127 InterfaceType get objectType; |
| 124 InterfaceType get rawFunctionType; | 128 InterfaceType get rawFunctionType; |
| 125 ClassHierarchy get hierarchy; | 129 ClassHierarchy get hierarchy; |
| 126 | 130 |
| 127 /// Returns true if [subtype] is a subtype of [supertype]. | 131 /// Returns true if [subtype] is a subtype of [supertype]. |
| 128 bool isSubtypeOf(DartType subtype, DartType supertype) { | 132 bool isSubtypeOf(DartType subtype, DartType supertype) { |
| 129 if (identical(subtype, supertype)) return true; | 133 if (identical(subtype, supertype)) return true; |
| 130 if (subtype is BottomType) return true; | 134 if (subtype is BottomType) return true; |
| 131 if (supertype is DynamicType || supertype == objectType) { | 135 if (supertype is DynamicType || |
| 136 supertype is VoidType || |
| 137 supertype == objectType) { |
| 132 return true; | 138 return true; |
| 133 } | 139 } |
| 134 if (subtype is InterfaceType && supertype is InterfaceType) { | 140 if (subtype is InterfaceType && supertype is InterfaceType) { |
| 135 var upcastType = | 141 var upcastType = |
| 136 hierarchy.getTypeAsInstanceOf(subtype, supertype.classNode); | 142 hierarchy.getTypeAsInstanceOf(subtype, supertype.classNode); |
| 137 if (upcastType == null) return false; | 143 if (upcastType == null) return false; |
| 138 for (int i = 0; i < upcastType.typeArguments.length; ++i) { | 144 for (int i = 0; i < upcastType.typeArguments.length; ++i) { |
| 139 // Termination: the 'supertype' parameter decreases in size. | 145 // Termination: the 'supertype' parameter decreases in size. |
| 140 if (!isSubtypeOf( | 146 if (!isSubtypeOf( |
| 141 upcastType.typeArguments[i], supertype.typeArguments[i])) { | 147 upcastType.typeArguments[i], supertype.typeArguments[i])) { |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 187 var subBound = substitute(subParameter.bound, substitution); | 193 var subBound = substitute(subParameter.bound, substitution); |
| 188 // Termination: if there are no cyclically bound type parameters, this | 194 // Termination: if there are no cyclically bound type parameters, this |
| 189 // recursive call can only occur a finite number of times before | 195 // recursive call can only occur a finite number of times before |
| 190 // reaching a shrinking recursive call (or terminating). | 196 // reaching a shrinking recursive call (or terminating). |
| 191 if (!isSubtypeOf(superParameter.bound, subBound)) { | 197 if (!isSubtypeOf(superParameter.bound, subBound)) { |
| 192 return false; | 198 return false; |
| 193 } | 199 } |
| 194 } | 200 } |
| 195 subtype = substitute(subtype.withoutTypeParameters, substitution); | 201 subtype = substitute(subtype.withoutTypeParameters, substitution); |
| 196 } | 202 } |
| 197 if (supertype.returnType is! VoidType && | 203 if (!isSubtypeOf(subtype.returnType, supertype.returnType)) { |
| 198 !isSubtypeOf(subtype.returnType, supertype.returnType)) { | |
| 199 return false; | 204 return false; |
| 200 } | 205 } |
| 201 for (int i = 0; i < supertype.positionalParameters.length; ++i) { | 206 for (int i = 0; i < supertype.positionalParameters.length; ++i) { |
| 202 var supertypeParameter = supertype.positionalParameters[i]; | 207 var supertypeParameter = supertype.positionalParameters[i]; |
| 203 var subtypeParameter = subtype.positionalParameters[i]; | 208 var subtypeParameter = subtype.positionalParameters[i]; |
| 204 // Termination: Both types shrink in size. | 209 // Termination: Both types shrink in size. |
| 205 if (!isSubtypeOf(supertypeParameter, subtypeParameter)) { | 210 if (!isSubtypeOf(supertypeParameter, subtypeParameter)) { |
| 206 return false; | 211 return false; |
| 207 } | 212 } |
| 208 } | 213 } |
| 209 int subtypeNameIndex = 0; | 214 int subtypeNameIndex = 0; |
| 210 for (NamedType supertypeParameter in supertype.namedParameters) { | 215 for (NamedType supertypeParameter in supertype.namedParameters) { |
| 211 while (subtypeNameIndex < subtype.namedParameters.length && | 216 while (subtypeNameIndex < subtype.namedParameters.length && |
| 212 subtype.namedParameters[subtypeNameIndex].name != | 217 subtype.namedParameters[subtypeNameIndex].name != |
| 213 supertypeParameter.name) { | 218 supertypeParameter.name) { |
| 214 ++subtypeNameIndex; | 219 ++subtypeNameIndex; |
| 215 } | 220 } |
| 216 if (subtypeNameIndex == subtype.namedParameters.length) return false; | 221 if (subtypeNameIndex == subtype.namedParameters.length) return false; |
| 217 NamedType subtypeParameter = subtype.namedParameters[subtypeNameIndex]; | 222 NamedType subtypeParameter = subtype.namedParameters[subtypeNameIndex]; |
| 218 // Termination: Both types shrink in size. | 223 // Termination: Both types shrink in size. |
| 219 if (!isSubtypeOf(supertypeParameter.type, subtypeParameter.type)) { | 224 if (!isSubtypeOf(supertypeParameter.type, subtypeParameter.type)) { |
| 220 return false; | 225 return false; |
| 221 } | 226 } |
| 222 } | 227 } |
| 223 return true; | 228 return true; |
| 224 } | 229 } |
| 225 } | 230 } |
| OLD | NEW |