OLD | NEW |
---|---|
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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 dart_types; | 5 library dart_types; |
6 | 6 |
7 import 'dart:math' show min; | 7 import 'dart:math' show min; |
8 | 8 |
9 import 'common/resolution.dart' show Resolution; | 9 import 'common/resolution.dart' show Resolution; |
10 import 'common.dart'; | 10 import 'common.dart'; |
11 import 'core_types.dart'; | 11 import 'core_types.dart'; |
12 import 'elements/elements.dart'; | 12 import 'elements/elements.dart'; |
13 import 'elements/modelx.dart' show TypeDeclarationElementX; | 13 import 'elements/modelx.dart' show TypeDeclarationElementX, ErroneousElementX; |
14 import 'ordered_typeset.dart' show OrderedTypeSet; | 14 import 'ordered_typeset.dart' show OrderedTypeSet; |
15 import 'util/util.dart' show equalElements; | 15 import 'util/util.dart' show equalElements; |
16 | 16 |
17 enum TypeKind { | 17 enum TypeKind { |
18 FUNCTION, | 18 FUNCTION, |
19 INTERFACE, | 19 INTERFACE, |
20 STATEMENT, | 20 STATEMENT, |
21 TYPEDEF, | 21 TYPEDEF, |
22 TYPE_VARIABLE, | 22 TYPE_VARIABLE, |
23 MALFORMED_TYPE, | 23 MALFORMED_TYPE, |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
117 /// Is [: true :] if this type is a typedef. | 117 /// Is [: true :] if this type is a typedef. |
118 bool get isTypedef => kind == TypeKind.TYPEDEF; | 118 bool get isTypedef => kind == TypeKind.TYPEDEF; |
119 | 119 |
120 /// Is [: true :] if this type is a function type. | 120 /// Is [: true :] if this type is a function type. |
121 bool get isFunctionType => kind == TypeKind.FUNCTION; | 121 bool get isFunctionType => kind == TypeKind.FUNCTION; |
122 | 122 |
123 /// Is [: true :] if this type is a type variable. | 123 /// Is [: true :] if this type is a type variable. |
124 bool get isTypeVariable => kind == TypeKind.TYPE_VARIABLE; | 124 bool get isTypeVariable => kind == TypeKind.TYPE_VARIABLE; |
125 | 125 |
126 /// Is [: true :] if this type is a malformed type. | 126 /// Is [: true :] if this type is a malformed type. |
127 bool get isMalformed => kind == TypeKind.MALFORMED_TYPE; | 127 bool get isMalformed => false; |
128 | 128 |
129 /// Is `true` if this type is declared by an enum. | 129 /// Is `true` if this type is declared by an enum. |
130 bool get isEnumType => false; | 130 bool get isEnumType => false; |
131 | 131 |
132 /// Returns an occurrence of a type variable within this type, if any. | 132 /// Returns an occurrence of a type variable within this type, if any. |
133 TypeVariableType get typeVariableOccurrence => null; | 133 TypeVariableType get typeVariableOccurrence => null; |
134 | 134 |
135 /// Applies [f] to each occurence of a [TypeVariableType] within this type. | 135 /// Applies [f] to each occurence of a [TypeVariableType] within this type. |
136 void forEachTypeVariable(f(TypeVariableType variable)) {} | 136 void forEachTypeVariable(f(TypeVariableType variable)) {} |
137 | 137 |
(...skipping 19 matching lines...) Expand all Loading... | |
157 accept(DartTypeVisitor visitor, var argument); | 157 accept(DartTypeVisitor visitor, var argument); |
158 | 158 |
159 void visitChildren(DartTypeVisitor visitor, var argument) {} | 159 void visitChildren(DartTypeVisitor visitor, var argument) {} |
160 | 160 |
161 static void visitList( | 161 static void visitList( |
162 List<DartType> types, DartTypeVisitor visitor, var argument) { | 162 List<DartType> types, DartTypeVisitor visitor, var argument) { |
163 for (DartType type in types) { | 163 for (DartType type in types) { |
164 type.accept(visitor, argument); | 164 type.accept(visitor, argument); |
165 } | 165 } |
166 } | 166 } |
167 | |
168 /// Returns a [DartType] which corresponds to [this] except that each | |
169 /// contained [MethodTypeVariableType] is replaced by a [DynamicType]. | |
170 /// GENERIC_METHODS: Temporary, only used with '--generic-method-syntax'. | |
171 DartType get dynamifyMethodTypeVariableType => this; | |
172 | |
173 /// Returns true iff [this] is or contains a [MethodTypeVariableType]. | |
174 /// GENERIC_METHODS: Temporary, only used with '--generic-method-syntax' | |
175 bool get containsMethodTypeVariableType => false; | |
167 } | 176 } |
168 | 177 |
169 /** | 178 /** |
170 * Represents a type variable, that is the type parameters of a class type. | 179 * Represents a type variable, that is the type parameters of a class type. |
171 * | 180 * |
172 * For example, in [: class Array<E> { ... } :], E is a type variable. | 181 * For example, in [: class Array<E> { ... } :], E is a type variable. |
173 * | 182 * |
174 * Each class should have its own unique type variables, one for each type | 183 * Each class should have its own unique type variables, one for each type |
175 * parameter. A class with type parameters is said to be parameterized or | 184 * parameter. A class with type parameters is said to be parameterized or |
176 * generic. | 185 * generic. |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
227 int get hashCode => 17 * element.hashCode; | 236 int get hashCode => 17 * element.hashCode; |
228 | 237 |
229 bool operator ==(other) { | 238 bool operator ==(other) { |
230 if (other is! TypeVariableType) return false; | 239 if (other is! TypeVariableType) return false; |
231 return identical(other.element, element); | 240 return identical(other.element, element); |
232 } | 241 } |
233 | 242 |
234 String toString() => name; | 243 String toString() => name; |
235 } | 244 } |
236 | 245 |
246 /// Provides a thin model of method type variables: They are treated as if | |
247 /// their value were `dynamic` when used in a type annotation, and as a | |
248 /// malformed type when used in an `as` or `is` expression. | |
249 class MethodTypeVariableType extends TypeVariableType { | |
250 MethodTypeVariableType(TypeVariableElement element) : super(element); | |
251 | |
252 @override | |
253 bool get treatAsDynamic => true; | |
254 | |
255 @override | |
256 bool get isMalformed => true; | |
257 | |
258 @override | |
259 DartType get dynamifyMethodTypeVariableType => const DynamicType(); | |
260 | |
261 @override | |
262 get containsMethodTypeVariableType => true; | |
263 | |
264 ErroneousElement get toMalformedElement => | |
Johnni Winther
2016/05/23 12:50:41
Remove this (unused)
eernst
2016/05/23 14:30:24
(OK, unused after fixing constructor.dart:739), do
| |
265 new ErroneousElementX( | |
266 MessageKind.TYPE_VARIABLE_FROM_METHOD_NOT_REIFIED, | |
267 const {}, | |
268 element.name, | |
269 element.typeDeclaration); | |
270 } | |
271 | |
237 /// Internal type representing the result of analyzing a statement. | 272 /// Internal type representing the result of analyzing a statement. |
238 class StatementType extends DartType { | 273 class StatementType extends DartType { |
239 Element get element => null; | 274 Element get element => null; |
240 | 275 |
241 TypeKind get kind => TypeKind.STATEMENT; | 276 TypeKind get kind => TypeKind.STATEMENT; |
242 | 277 |
243 String get name => 'statement'; | 278 String get name => 'statement'; |
244 | 279 |
245 const StatementType(); | 280 const StatementType(); |
246 | 281 |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
306 String get name => element.name; | 341 String get name => element.name; |
307 | 342 |
308 DartType subst(List<DartType> arguments, List<DartType> parameters) { | 343 DartType subst(List<DartType> arguments, List<DartType> parameters) { |
309 // Malformed types are not substitutable. | 344 // Malformed types are not substitutable. |
310 return this; | 345 return this; |
311 } | 346 } |
312 | 347 |
313 // Malformed types are treated as dynamic. | 348 // Malformed types are treated as dynamic. |
314 bool get treatAsDynamic => true; | 349 bool get treatAsDynamic => true; |
315 | 350 |
351 @override | |
352 bool get isMalformed => true; | |
353 | |
316 accept(DartTypeVisitor visitor, var argument) { | 354 accept(DartTypeVisitor visitor, var argument) { |
317 return visitor.visitMalformedType(this, argument); | 355 return visitor.visitMalformedType(this, argument); |
318 } | 356 } |
319 | 357 |
320 String toString() { | 358 String toString() { |
321 var sb = new StringBuffer(); | 359 var sb = new StringBuffer(); |
322 if (typeArguments != null) { | 360 if (typeArguments != null) { |
323 if (userProvidedBadType != null) { | 361 if (userProvidedBadType != null) { |
324 sb.write(userProvidedBadType.name); | 362 sb.write(userProvidedBadType.name); |
325 } else { | 363 } else { |
326 sb.write(element.name); | 364 sb.write(element.name); |
327 } | 365 } |
328 if (!typeArguments.isEmpty) { | 366 if (!typeArguments.isEmpty) { |
329 sb.write('<'); | 367 sb.write('<'); |
330 sb.write(typeArguments.join(', ')); | 368 sb.write(typeArguments.join(', ')); |
331 sb.write('>'); | 369 sb.write('>'); |
332 } | 370 } |
333 } else { | 371 } else { |
334 sb.write(userProvidedBadType.toString()); | 372 sb.write(userProvidedBadType.toString()); |
335 } | 373 } |
336 return sb.toString(); | 374 return sb.toString(); |
337 } | 375 } |
338 } | 376 } |
339 | 377 |
340 abstract class GenericType extends DartType { | 378 abstract class GenericType extends DartType { |
341 final TypeDeclarationElement element; | 379 final TypeDeclarationElement element; |
342 final List<DartType> typeArguments; | 380 final List<DartType> typeArguments; |
343 | 381 |
344 GenericType(TypeDeclarationElement element, this.typeArguments, | 382 GenericType(TypeDeclarationElement element, List<DartType> typeArguments, |
345 {bool checkTypeArgumentCount: true}) | 383 {bool checkTypeArgumentCount: true}) |
346 : this.element = element { | 384 : this.element = element, |
385 this.typeArguments = typeArguments, | |
386 this.containsMethodTypeVariableType = | |
387 typeArguments.any(_typeContainsMethodTypeVariableType) | |
388 { | |
347 assert(invariant(CURRENT_ELEMENT_SPANNABLE, element != null, | 389 assert(invariant(CURRENT_ELEMENT_SPANNABLE, element != null, |
348 message: "Missing element for generic type.")); | 390 message: "Missing element for generic type.")); |
349 assert(invariant(element, () { | 391 assert(invariant(element, () { |
350 if (!checkTypeArgumentCount) return true; | 392 if (!checkTypeArgumentCount) return true; |
351 if (element is TypeDeclarationElementX) { | 393 if (element is TypeDeclarationElementX) { |
352 return element.thisTypeCache == null || | 394 return element.thisTypeCache == null || |
353 typeArguments.length == element.typeVariables.length; | 395 typeArguments.length == element.typeVariables.length; |
354 } | 396 } |
355 return true; | 397 return true; |
356 }, | 398 }, |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
398 StringBuffer sb = new StringBuffer(); | 440 StringBuffer sb = new StringBuffer(); |
399 sb.write(name); | 441 sb.write(name); |
400 if (!isRaw) { | 442 if (!isRaw) { |
401 sb.write('<'); | 443 sb.write('<'); |
402 sb.write(typeArguments.join(', ')); | 444 sb.write(typeArguments.join(', ')); |
403 sb.write('>'); | 445 sb.write('>'); |
404 } | 446 } |
405 return sb.toString(); | 447 return sb.toString(); |
406 } | 448 } |
407 | 449 |
450 @override | |
451 final bool containsMethodTypeVariableType; | |
452 | |
453 @override | |
454 DartType get dynamifyMethodTypeVariableType { | |
455 if (!containsMethodTypeVariableType) return this; | |
456 List<DartType> newTypeArguments = typeArguments.map( | |
457 (DartType type) => type.dynamifyMethodTypeVariableType).toList(); | |
458 return createInstantiation(newTypeArguments); | |
459 } | |
460 | |
408 int get hashCode { | 461 int get hashCode { |
409 int hash = element.hashCode; | 462 int hash = element.hashCode; |
410 for (DartType argument in typeArguments) { | 463 for (DartType argument in typeArguments) { |
411 int argumentHash = argument != null ? argument.hashCode : 0; | 464 int argumentHash = argument != null ? argument.hashCode : 0; |
412 hash = 17 * hash + 3 * argumentHash; | 465 hash = 17 * hash + 3 * argumentHash; |
413 } | 466 } |
414 return hash; | 467 return hash; |
415 } | 468 } |
416 | 469 |
417 bool operator ==(other) { | 470 bool operator ==(other) { |
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
579 [DartType returnType = const DynamicType(), | 632 [DartType returnType = const DynamicType(), |
580 List<DartType> parameterTypes = const <DartType>[], | 633 List<DartType> parameterTypes = const <DartType>[], |
581 List<DartType> optionalParameterTypes = const <DartType>[], | 634 List<DartType> optionalParameterTypes = const <DartType>[], |
582 List<String> namedParameters = const <String>[], | 635 List<String> namedParameters = const <String>[], |
583 List<DartType> namedParameterTypes = const <DartType>[]]) { | 636 List<DartType> namedParameterTypes = const <DartType>[]]) { |
584 return new FunctionType.internal(null, returnType, parameterTypes, | 637 return new FunctionType.internal(null, returnType, parameterTypes, |
585 optionalParameterTypes, namedParameters, namedParameterTypes); | 638 optionalParameterTypes, namedParameters, namedParameterTypes); |
586 } | 639 } |
587 | 640 |
588 FunctionType.internal(FunctionTypedElement this.element, | 641 FunctionType.internal(FunctionTypedElement this.element, |
589 [DartType this.returnType = const DynamicType(), | 642 [DartType returnType = const DynamicType(), |
590 this.parameterTypes = const <DartType>[], | 643 List<DartType> parameterTypes = const <DartType>[], |
591 this.optionalParameterTypes = const <DartType>[], | 644 List<DartType> optionalParameterTypes = const <DartType>[], |
592 this.namedParameters = const <String>[], | 645 List<String> namedParameters = const <String>[], |
593 this.namedParameterTypes = const <DartType>[]]) { | 646 List<DartType> namedParameterTypes = const <DartType>[]]) |
647 : this.returnType = returnType, | |
648 this.parameterTypes = parameterTypes, | |
649 this.optionalParameterTypes = optionalParameterTypes, | |
650 this.namedParameters = namedParameters, | |
651 this.namedParameterTypes = namedParameterTypes, | |
652 this.containsMethodTypeVariableType = | |
653 returnType.containsMethodTypeVariableType || | |
654 parameterTypes.any(_typeContainsMethodTypeVariableType) || | |
655 optionalParameterTypes.any(_typeContainsMethodTypeVariableType) || | |
656 namedParameterTypes.any(_typeContainsMethodTypeVariableType) { | |
594 assert(invariant( | 657 assert(invariant( |
595 CURRENT_ELEMENT_SPANNABLE, element == null || element.isDeclaration)); | 658 CURRENT_ELEMENT_SPANNABLE, element == null || element.isDeclaration)); |
596 // Assert that optional and named parameters are not used at the same time. | 659 // Assert that optional and named parameters are not used at the same time. |
597 assert(optionalParameterTypes.isEmpty || namedParameterTypes.isEmpty); | 660 assert(optionalParameterTypes.isEmpty || namedParameterTypes.isEmpty); |
598 assert(namedParameters.length == namedParameterTypes.length); | 661 assert(namedParameters.length == namedParameterTypes.length); |
599 } | 662 } |
600 | 663 |
601 TypeKind get kind => TypeKind.FUNCTION; | 664 TypeKind get kind => TypeKind.FUNCTION; |
602 | 665 |
603 DartType getNamedParameterType(String name) { | 666 DartType getNamedParameterType(String name) { |
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
711 sb.write('}'); | 774 sb.write('}'); |
712 } | 775 } |
713 sb.write(') -> ${returnType}'); | 776 sb.write(') -> ${returnType}'); |
714 return sb.toString(); | 777 return sb.toString(); |
715 } | 778 } |
716 | 779 |
717 String get name => 'Function'; | 780 String get name => 'Function'; |
718 | 781 |
719 int computeArity() => parameterTypes.length; | 782 int computeArity() => parameterTypes.length; |
720 | 783 |
784 @override | |
785 DartType get dynamifyMethodTypeVariableType { | |
786 if (!containsMethodTypeVariableType) return this; | |
787 DartType eraseIt(DartType type) => type.dynamifyMethodTypeVariableType; | |
788 DartType newReturnType = returnType.dynamifyMethodTypeVariableType; | |
789 List<DartType> newParameterTypes = parameterTypes.map(eraseIt).toList(); | |
790 List<DartType> newOptionalParameterTypes = | |
791 optionalParameterTypes.map(eraseIt).toList(); | |
792 List<DartType> newNamedParameterTypes = | |
793 namedParameterTypes.map(eraseIt).toList(); | |
794 return new FunctionType.internal( | |
795 element, | |
796 newReturnType, | |
797 newParameterTypes, | |
798 newOptionalParameterTypes, | |
799 namedParameters, | |
800 newNamedParameterTypes); | |
801 } | |
802 | |
803 @override | |
804 final bool containsMethodTypeVariableType; | |
805 | |
721 int get hashCode { | 806 int get hashCode { |
722 int hash = 3 * returnType.hashCode; | 807 int hash = 3 * returnType.hashCode; |
723 for (DartType parameter in parameterTypes) { | 808 for (DartType parameter in parameterTypes) { |
724 hash = 17 * hash + 5 * parameter.hashCode; | 809 hash = 17 * hash + 5 * parameter.hashCode; |
725 } | 810 } |
726 for (DartType parameter in optionalParameterTypes) { | 811 for (DartType parameter in optionalParameterTypes) { |
727 hash = 19 * hash + 7 * parameter.hashCode; | 812 hash = 19 * hash + 7 * parameter.hashCode; |
728 } | 813 } |
729 for (String name in namedParameters) { | 814 for (String name in namedParameters) { |
730 hash = 23 * hash + 11 * name.hashCode; | 815 hash = 23 * hash + 11 * name.hashCode; |
731 } | 816 } |
732 for (DartType parameter in namedParameterTypes) { | 817 for (DartType parameter in namedParameterTypes) { |
733 hash = 29 * hash + 13 * parameter.hashCode; | 818 hash = 29 * hash + 13 * parameter.hashCode; |
734 } | 819 } |
735 return hash; | 820 return hash; |
736 } | 821 } |
737 | 822 |
738 bool operator ==(other) { | 823 bool operator ==(other) { |
739 if (other is! FunctionType) return false; | 824 if (other is! FunctionType) return false; |
740 return returnType == other.returnType && | 825 return returnType == other.returnType && |
741 equalElements(parameterTypes, other.parameterTypes) && | 826 equalElements(parameterTypes, other.parameterTypes) && |
742 equalElements(optionalParameterTypes, other.optionalParameterTypes) && | 827 equalElements(optionalParameterTypes, other.optionalParameterTypes) && |
743 equalElements(namedParameters, other.namedParameters) && | 828 equalElements(namedParameters, other.namedParameters) && |
744 equalElements(namedParameterTypes, other.namedParameterTypes); | 829 equalElements(namedParameterTypes, other.namedParameterTypes); |
745 } | 830 } |
746 } | 831 } |
747 | 832 |
833 bool _typeContainsMethodTypeVariableType(DartType type) => | |
834 type.containsMethodTypeVariableType; | |
835 | |
748 class TypedefType extends GenericType { | 836 class TypedefType extends GenericType { |
749 DartType _unaliased; | 837 DartType _unaliased; |
750 | 838 |
751 TypedefType(TypedefElement element, | 839 TypedefType(TypedefElement element, |
752 [List<DartType> typeArguments = const <DartType>[]]) | 840 [List<DartType> typeArguments = const <DartType>[]]) |
753 : super(element, typeArguments); | 841 : super(element, typeArguments); |
754 | 842 |
755 TypedefType.forUserProvidedBadType(TypedefElement element, | 843 TypedefType.forUserProvidedBadType(TypedefElement element, |
756 [List<DartType> typeArguments = const <DartType>[]]) | 844 [List<DartType> typeArguments = const <DartType>[]]) |
757 : super(element, typeArguments, checkTypeArgumentCount: false); | 845 : super(element, typeArguments, checkTypeArgumentCount: false); |
(...skipping 582 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1340 return changed ? result : types; | 1428 return changed ? result : types; |
1341 } | 1429 } |
1342 | 1430 |
1343 /** | 1431 /** |
1344 * Returns the [ClassElement] which declares the type variables occurring in | 1432 * Returns the [ClassElement] which declares the type variables occurring in |
1345 * [type], or [:null:] if [type] does not contain type variables. | 1433 * [type], or [:null:] if [type] does not contain type variables. |
1346 */ | 1434 */ |
1347 static ClassElement getClassContext(DartType type) { | 1435 static ClassElement getClassContext(DartType type) { |
1348 TypeVariableType typeVariable = type.typeVariableOccurrence; | 1436 TypeVariableType typeVariable = type.typeVariableOccurrence; |
1349 if (typeVariable == null) return null; | 1437 if (typeVariable == null) return null; |
1438 // GENERIC_METHODS: When generic method support is complete enough to | |
1439 // include a runtime value for method type variables this must be updated. | |
1440 // For full support the global assumption that all type variables are | |
1441 // declared by the same enclosing class will not hold: Both an enclosing | |
1442 // method and an enclosing class may define type variables, so the return | |
1443 // type cannot be [ClassElement] and the caller must be prepared to look in | |
1444 // two locations, not one. Currently we ignore method type variables by | |
1445 // returning in the next statement. | |
1446 if (typeVariable.element.typeDeclaration is! ClassElement) return null; | |
1350 return typeVariable.element.typeDeclaration; | 1447 return typeVariable.element.typeDeclaration; |
1351 } | 1448 } |
1352 | 1449 |
1353 /** | 1450 /** |
1354 * A `compareTo` function that globally orders types using | 1451 * A `compareTo` function that globally orders types using |
1355 * [Elements.compareByPosition] to order types defined by a declaration. | 1452 * [Elements.compareByPosition] to order types defined by a declaration. |
1356 * | 1453 * |
1357 * The order is: | 1454 * The order is: |
1358 * * void | 1455 * * void |
1359 * * dynamic | 1456 * * dynamic |
(...skipping 561 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1921 sb.write(', '); | 2018 sb.write(', '); |
1922 } | 2019 } |
1923 namedParameterTypes[index].accept(this, namedParameters[index]); | 2020 namedParameterTypes[index].accept(this, namedParameters[index]); |
1924 needsComma = true; | 2021 needsComma = true; |
1925 } | 2022 } |
1926 sb.write('}'); | 2023 sb.write('}'); |
1927 } | 2024 } |
1928 sb.write(')'); | 2025 sb.write(')'); |
1929 } | 2026 } |
1930 } | 2027 } |
OLD | NEW |