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 |