Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(78)

Side by Side Diff: pkg/compiler/lib/src/dart_types.dart

Issue 1976213002: Adjusts dart2js backend to handle method type arguments. (Closed) Base URL: https://github.com/dart-lang/sdk.git@master
Patch Set: Made MethodTypeVariableType malformed, eliminated malformMethodTypeVariableType Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
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
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
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
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
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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698