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

Side by Side Diff: sdk/lib/_internal/compiler/implementation/dart_types.dart

Issue 694353007: Move dart2js from sdk/lib/_internal/compiler to pkg/compiler (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 1 month 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 | Annotate | Revision Log
OLDNEW
(Empty)
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
3 // BSD-style license that can be found in the LICENSE file.
4
5 library dart_types;
6
7 import 'dart:math' show min;
8
9 import 'dart2jslib.dart' show Compiler, invariant, Script, Message;
10 import 'elements/modelx.dart'
11 show VoidElementX,
12 LibraryElementX,
13 BaseClassElementX,
14 TypeDeclarationElementX,
15 TypedefElementX;
16 import 'elements/elements.dart';
17 import 'helpers/helpers.dart'; // Included for debug helpers.
18 import 'ordered_typeset.dart' show OrderedTypeSet;
19 import 'util/util.dart' show CURRENT_ELEMENT_SPANNABLE, equalElements;
20
21 class TypeKind {
22 final String id;
23
24 const TypeKind(String this.id);
25
26 static const TypeKind FUNCTION = const TypeKind('function');
27 static const TypeKind INTERFACE = const TypeKind('interface');
28 static const TypeKind STATEMENT = const TypeKind('statement');
29 static const TypeKind TYPEDEF = const TypeKind('typedef');
30 static const TypeKind TYPE_VARIABLE = const TypeKind('type variable');
31 static const TypeKind MALFORMED_TYPE = const TypeKind('malformed');
32 static const TypeKind DYNAMIC = const TypeKind('dynamic');
33 static const TypeKind VOID = const TypeKind('void');
34
35 String toString() => id;
36 }
37
38 abstract class DartType {
39 String get name;
40
41 TypeKind get kind;
42
43 const DartType();
44
45 /**
46 * Returns the [Element] which declared this type.
47 *
48 * This can be [ClassElement] for classes, [TypedefElement] for typedefs,
49 * [TypeVariableElement] for type variables and [FunctionElement] for
50 * function types.
51 *
52 * Invariant: [element] must be a declaration element.
53 */
54 Element get element;
55
56 /**
57 * Performs the substitution [: [arguments[i]/parameters[i]]this :].
58 *
59 * The notation is known from this lambda calculus rule:
60 *
61 * (lambda x.e0)e1 -> [e1/x]e0.
62 *
63 * See [TypeVariableType] for a motivation for this method.
64 *
65 * Invariant: There must be the same number of [arguments] and [parameters].
66 */
67 DartType subst(List<DartType> arguments, List<DartType> parameters);
68
69 /// Performs the substitution of the type arguments of [type] for their
70 /// corresponding type variables in this type.
71 DartType substByContext(GenericType type) {
72 return subst(type.typeArguments, type.element.typeVariables);
73 }
74
75 /**
76 * Returns the unaliased type of this type.
77 *
78 * The unaliased type of a typedef'd type is the unaliased type to which its
79 * name is bound. The unaliased version of any other type is the type itself.
80 *
81 * For example, the unaliased type of [: typedef A Func<A,B>(B b) :] is the
82 * function type [: (B) -> A :] and the unaliased type of
83 * [: Func<int,String> :] is the function type [: (String) -> int :].
84 */
85 DartType unalias(Compiler compiler);
86
87 /**
88 * If this type is malformed or a generic type created with the wrong number
89 * of type arguments then [userProvidedBadType] holds the bad type provided
90 * by the user.
91 */
92 DartType get userProvidedBadType => null;
93
94 /// Is [: true :] if this type has no explict type arguments.
95 bool get isRaw => true;
96
97 /// Returns the raw version of this type.
98 DartType asRaw() => this;
99
100 /// Is [: true :] if this type has no non-dynamic type arguments.
101 bool get treatAsRaw => isRaw;
102
103 /// Is [: true :] if this type should be treated as the dynamic type.
104 bool get treatAsDynamic => false;
105
106 /// Is [: true :] if this type is the dynamic type.
107 bool get isDynamic => kind == TypeKind.DYNAMIC;
108
109 /// Is [: true :] if this type is the void type.
110 bool get isVoid => kind == TypeKind.VOID;
111
112 /// Is [: true :] if this is the type of `Object` from dart:core.
113 bool get isObject => false;
114
115 /// Is [: true :] if this type is an interface type.
116 bool get isInterfaceType => kind == TypeKind.INTERFACE;
117
118 /// Is [: true :] if this type is a typedef.
119 bool get isTypedef => kind == TypeKind.TYPEDEF;
120
121 /// Is [: true :] if this type is a function type.
122 bool get isFunctionType => kind == TypeKind.FUNCTION;
123
124 /// Is [: true :] if this type is a type variable.
125 bool get isTypeVariable => kind == TypeKind.TYPE_VARIABLE;
126
127 /// Is [: true :] if this type is a malformed type.
128 bool get isMalformed => kind == TypeKind.MALFORMED_TYPE;
129
130 /// Returns an occurrence of a type variable within this type, if any.
131 TypeVariableType get typeVariableOccurrence => null;
132
133 /// Applies [f] to each occurence of a [TypeVariableType] within this type.
134 void forEachTypeVariable(f(TypeVariableType variable)) {}
135
136 TypeVariableType _findTypeVariableOccurrence(List<DartType> types) {
137 for (DartType type in types) {
138 TypeVariableType typeVariable = type.typeVariableOccurrence;
139 if (typeVariable != null) {
140 return typeVariable;
141 }
142 }
143 return null;
144 }
145
146 /// Is [: true :] if this type contains any type variables.
147 bool get containsTypeVariables => typeVariableOccurrence != null;
148
149 /// Returns a textual representation of this type as if it was the type
150 /// of a member named [name].
151 String getStringAsDeclared(String name) {
152 return new TypeDeclarationFormatter().format(this, name);
153 }
154
155 accept(DartTypeVisitor visitor, var argument);
156
157 void visitChildren(DartTypeVisitor visitor, var argument) {}
158
159 static void visitList(List<DartType> types,
160 DartTypeVisitor visitor, var argument) {
161 for (DartType type in types) {
162 type.accept(visitor, argument);
163 }
164 }
165 }
166
167 /**
168 * Represents a type variable, that is the type parameters of a class type.
169 *
170 * For example, in [: class Array<E> { ... } :], E is a type variable.
171 *
172 * Each class should have its own unique type variables, one for each type
173 * parameter. A class with type parameters is said to be parameterized or
174 * generic.
175 *
176 * Non-static members, constructors, and factories of generic
177 * class/interface can refer to type variables of the current class
178 * (not of supertypes).
179 *
180 * When using a generic type, also known as an application or
181 * instantiation of the type, the actual type arguments should be
182 * substituted for the type variables in the class declaration.
183 *
184 * For example, given a box, [: class Box<T> { T value; } :], the
185 * type of the expression [: new Box<String>().value :] is
186 * [: String :] because we must substitute [: String :] for the
187 * the type variable [: T :].
188 */
189 class TypeVariableType extends DartType {
190 final TypeVariableElement element;
191
192 TypeVariableType(this.element);
193
194 TypeKind get kind => TypeKind.TYPE_VARIABLE;
195
196 String get name => element.name;
197
198 DartType subst(List<DartType> arguments, List<DartType> parameters) {
199 assert(arguments.length == parameters.length);
200 if (parameters.isEmpty) {
201 // Return fast on empty substitutions.
202 return this;
203 }
204 for (int index = 0; index < arguments.length; index++) {
205 TypeVariableType parameter = parameters[index];
206 DartType argument = arguments[index];
207 if (parameter == this) {
208 return argument;
209 }
210 }
211 // The type variable was not substituted.
212 return this;
213 }
214
215 DartType unalias(Compiler compiler) => this;
216
217 DartType get typeVariableOccurrence => this;
218
219 void forEachTypeVariable(f(TypeVariableType variable)) {
220 f(this);
221 }
222
223 accept(DartTypeVisitor visitor, var argument) {
224 return visitor.visitTypeVariableType(this, argument);
225 }
226
227 int get hashCode => 17 * element.hashCode;
228
229 bool operator ==(other) {
230 if (other is !TypeVariableType) return false;
231 return identical(other.element, element);
232 }
233
234 String toString() => name;
235 }
236
237 /// Internal type representing the result of analyzing a statement.
238 class StatementType extends DartType {
239 Element get element => null;
240
241 TypeKind get kind => TypeKind.STATEMENT;
242
243 String get name => 'statement';
244
245 const StatementType();
246
247 DartType subst(List<DartType> arguments, List<DartType> parameters) => this;
248
249 DartType unalias(Compiler compiler) => this;
250
251 accept(DartTypeVisitor visitor, var argument) {
252 return visitor.visitStatementType(this, argument);
253 }
254 }
255
256 class VoidType extends DartType {
257 const VoidType();
258
259 TypeKind get kind => TypeKind.VOID;
260
261 String get name => 'void';
262
263 Element get element => null;
264
265 DartType subst(List<DartType> arguments, List<DartType> parameters) {
266 // Void cannot be substituted.
267 return this;
268 }
269
270 DartType unalias(Compiler compiler) => this;
271
272 accept(DartTypeVisitor visitor, var argument) {
273 return visitor.visitVoidType(this, argument);
274 }
275
276 String toString() => name;
277 }
278
279 class MalformedType extends DartType {
280 final ErroneousElement element;
281
282 /**
283 * [declaredType] holds the type which the user wrote in code.
284 *
285 * For instance, for a resolved but malformed type like [: Map<String> :] the
286 * [declaredType] is [: Map<String> :] whereas for an unresolved type
287 * [userProvidedBadType] is [: null :].
288 */
289 final DartType userProvidedBadType;
290
291 /**
292 * Type arguments for the malformed typed, if these cannot fit in the
293 * [declaredType].
294 *
295 * This field is for instance used for [: dynamic<int> :] and [: T<int> :]
296 * where [: T :] is a type variable, in which case [declaredType] holds
297 * [: dynamic :] and [: T :], respectively, or for [: X<int> :] where [: X :]
298 * is not resolved or does not imply a type.
299 */
300 final List<DartType> typeArguments;
301
302 final int hashCode = (nextHash++) & 0x3fffffff;
303 static int nextHash = 43765;
304
305 MalformedType(this.element, this.userProvidedBadType,
306 [this.typeArguments = null]);
307
308 TypeKind get kind => TypeKind.MALFORMED_TYPE;
309
310 String get name => element.name;
311
312 DartType subst(List<DartType> arguments, List<DartType> parameters) {
313 // Malformed types are not substitutable.
314 return this;
315 }
316
317 // Malformed types are treated as dynamic.
318 bool get treatAsDynamic => true;
319
320 DartType unalias(Compiler compiler) => this;
321
322 accept(DartTypeVisitor visitor, var argument) {
323 return visitor.visitMalformedType(this, argument);
324 }
325
326 String toString() {
327 var sb = new StringBuffer();
328 if (typeArguments != null) {
329 if (userProvidedBadType != null) {
330 sb.write(userProvidedBadType.name);
331 } else {
332 sb.write(element.name);
333 }
334 if (!typeArguments.isEmpty) {
335 sb.write('<');
336 sb.write(typeArguments.join(', '));
337 sb.write('>');
338 }
339 } else {
340 sb.write(userProvidedBadType.toString());
341 }
342 return sb.toString();
343 }
344 }
345
346 abstract class GenericType extends DartType {
347 final TypeDeclarationElement element;
348 final List<DartType> typeArguments;
349
350 GenericType(TypeDeclarationElement element,
351 this.typeArguments,
352 {bool checkTypeArgumentCount: true})
353 : this.element = element {
354 assert(invariant(element, () {
355 if (!checkTypeArgumentCount) return true;
356 if (element is TypeDeclarationElementX) {
357 return element.thisTypeCache == null ||
358 typeArguments.length == element.typeVariables.length;
359 }
360 return true;
361 }, message: () => 'Invalid type argument count on ${element.thisType}. '
362 'Provided type arguments: $typeArguments.'));
363 }
364
365 /// Creates a new instance of this type using the provided type arguments.
366 GenericType createInstantiation(List<DartType> newTypeArguments);
367
368 DartType subst(List<DartType> arguments, List<DartType> parameters) {
369 if (typeArguments.isEmpty) {
370 // Return fast on non-generic types.
371 return this;
372 }
373 if (parameters.isEmpty) {
374 assert(arguments.isEmpty);
375 // Return fast on empty substitutions.
376 return this;
377 }
378 List<DartType> newTypeArguments =
379 Types.substTypes(typeArguments, arguments, parameters);
380 if (!identical(typeArguments, newTypeArguments)) {
381 // Create a new type only if necessary.
382 return createInstantiation(newTypeArguments);
383 }
384 return this;
385 }
386
387 TypeVariableType get typeVariableOccurrence {
388 return _findTypeVariableOccurrence(typeArguments);
389 }
390
391 void forEachTypeVariable(f(TypeVariableType variable)) {
392 for (DartType type in typeArguments) {
393 type.forEachTypeVariable(f);
394 }
395 }
396
397 void visitChildren(DartTypeVisitor visitor, var argument) {
398 DartType.visitList(typeArguments, visitor, argument);
399 }
400
401 String toString() {
402 StringBuffer sb = new StringBuffer();
403 sb.write(name);
404 if (!isRaw) {
405 sb.write('<');
406 sb.write(typeArguments.join(', '));
407 sb.write('>');
408 }
409 return sb.toString();
410 }
411
412 int get hashCode {
413 int hash = element.hashCode;
414 for (DartType argument in typeArguments) {
415 int argumentHash = argument != null ? argument.hashCode : 0;
416 hash = 17 * hash + 3 * argumentHash;
417 }
418 return hash;
419 }
420
421 bool operator ==(other) {
422 if (other is !GenericType) return false;
423 return kind == other.kind
424 && element == other.element
425 && equalElements(typeArguments, other.typeArguments);
426 }
427
428 /// Returns `true` if the declaration of this type has type variables.
429 bool get isGeneric => !typeArguments.isEmpty;
430
431 bool get isRaw => typeArguments.isEmpty || identical(this, element.rawType);
432
433 GenericType asRaw() => element.rawType;
434
435 bool get treatAsRaw {
436 if (isRaw) return true;
437 for (DartType type in typeArguments) {
438 if (!type.treatAsDynamic) return false;
439 }
440 return true;
441 }
442 }
443
444 class InterfaceType extends GenericType {
445 InterfaceType(ClassElement element,
446 [List<DartType> typeArguments = const <DartType>[]])
447 : super(element, typeArguments) {
448 assert(invariant(element, element.isDeclaration));
449 }
450
451 InterfaceType.forUserProvidedBadType(BaseClassElementX element,
452 [List<DartType> typeArguments =
453 const <DartType>[]])
454 : super(element, typeArguments, checkTypeArgumentCount: false);
455
456 ClassElement get element => super.element;
457
458 TypeKind get kind => TypeKind.INTERFACE;
459
460 String get name => element.name;
461
462 bool get isObject => element.isObject;
463
464 InterfaceType createInstantiation(List<DartType> newTypeArguments) {
465 return new InterfaceType(element, newTypeArguments);
466 }
467
468 /**
469 * Returns the type as an instance of class [other], if possible, null
470 * otherwise.
471 */
472 DartType asInstanceOf(ClassElement other) {
473 other = other.declaration;
474 if (element == other) return this;
475 InterfaceType supertype = element.asInstanceOf(other);
476 if (supertype != null) {
477 List<DartType> arguments = Types.substTypes(supertype.typeArguments,
478 typeArguments,
479 element.typeVariables);
480 return new InterfaceType(supertype.element, arguments);
481 }
482 return null;
483 }
484
485 DartType unalias(Compiler compiler) => this;
486
487 MemberSignature lookupInterfaceMember(Name name) {
488 MemberSignature member = element.lookupInterfaceMember(name);
489 if (member != null && isGeneric) {
490 return new InterfaceMember(this, member);
491 }
492 return member;
493 }
494
495 MemberSignature lookupClassMember(Name name) {
496 MemberSignature member = element.lookupClassMember(name);
497 if (member != null && isGeneric) {
498 return new InterfaceMember(this, member);
499 }
500 return member;
501 }
502
503 int get hashCode => super.hashCode;
504
505 InterfaceType asRaw() => super.asRaw();
506
507 accept(DartTypeVisitor visitor, var argument) {
508 return visitor.visitInterfaceType(this, argument);
509 }
510
511 /// Returns the type of the 'call' method in this interface type, or
512 /// `null` if the interface type has no 'call' method.
513 FunctionType get callType {
514 FunctionType type = element.callType;
515 return type != null && isGeneric ? type.substByContext(this) : type;
516 }
517 }
518
519 /**
520 * Special subclass of [InterfaceType] used for generic interface types created
521 * with the wrong number of type arguments.
522 *
523 * The type uses [:dynamic:] for all it s type arguments.
524 */
525 class BadInterfaceType extends InterfaceType {
526 final InterfaceType userProvidedBadType;
527
528 BadInterfaceType(ClassElement element,
529 InterfaceType this.userProvidedBadType)
530 : super(element, element.rawType.typeArguments);
531
532 String toString() {
533 return userProvidedBadType.toString();
534 }
535 }
536
537
538 /**
539 * Special subclass of [TypedefType] used for generic typedef types created
540 * with the wrong number of type arguments.
541 *
542 * The type uses [:dynamic:] for all it s type arguments.
543 */
544 class BadTypedefType extends TypedefType {
545 final TypedefType userProvidedBadType;
546
547 BadTypedefType(TypedefElement element,
548 TypedefType this.userProvidedBadType)
549 : super(element, element.rawType.typeArguments);
550
551 String toString() {
552 return userProvidedBadType.toString();
553 }
554 }
555
556 class FunctionType extends DartType {
557 final FunctionTypedElement element;
558 final DartType returnType;
559 final List<DartType> parameterTypes;
560 final List<DartType> optionalParameterTypes;
561
562 /**
563 * The names of the named parameters ordered lexicographically.
564 */
565 final List<String> namedParameters;
566
567 /**
568 * The types of the named parameters in the order corresponding to the
569 * [namedParameters].
570 */
571 final List<DartType> namedParameterTypes;
572
573 factory FunctionType(
574 FunctionTypedElement element,
575 [DartType returnType = const DynamicType(),
576 List<DartType> parameterTypes = const <DartType>[],
577 List<DartType> optionalParameterTypes = const <DartType>[],
578 List<String> namedParameters = const <String>[],
579 List<DartType> namedParameterTypes = const <DartType>[]]) {
580 assert(invariant(CURRENT_ELEMENT_SPANNABLE, element != null));
581 assert(invariant(element, element.isDeclaration));
582 return new FunctionType.internal(element,
583 returnType, parameterTypes, optionalParameterTypes,
584 namedParameters, namedParameterTypes);
585 }
586
587 factory FunctionType.synthesized(
588 [DartType returnType = const DynamicType(),
589 List<DartType> parameterTypes = const <DartType>[],
590 List<DartType> optionalParameterTypes = const <DartType>[],
591 List<String> namedParameters = const <String>[],
592 List<DartType> namedParameterTypes = const <DartType>[]]) {
593 return new FunctionType.internal(null,
594 returnType, parameterTypes, optionalParameterTypes,
595 namedParameters, namedParameterTypes);
596 }
597
598 FunctionType.internal(FunctionTypedElement this.element,
599 [DartType this.returnType = const DynamicType(),
600 this.parameterTypes = const <DartType>[],
601 this.optionalParameterTypes = const <DartType>[],
602 this.namedParameters = const <String>[],
603 this.namedParameterTypes = const <DartType>[]]) {
604 assert(invariant(CURRENT_ELEMENT_SPANNABLE,
605 element == null || element.isDeclaration));
606 // Assert that optional and named parameters are not used at the same time.
607 assert(optionalParameterTypes.isEmpty || namedParameterTypes.isEmpty);
608 assert(namedParameters.length == namedParameterTypes.length);
609 }
610
611
612
613 TypeKind get kind => TypeKind.FUNCTION;
614
615 DartType getNamedParameterType(String name) {
616 for (int i = 0; i < namedParameters.length; i++) {
617 if (namedParameters[i] == name) {
618 return namedParameterTypes[i];
619 }
620 }
621 return null;
622 }
623
624 DartType subst(List<DartType> arguments, List<DartType> parameters) {
625 if (parameters.isEmpty) {
626 assert(arguments.isEmpty);
627 // Return fast on empty substitutions.
628 return this;
629 }
630 DartType newReturnType = returnType.subst(arguments, parameters);
631 bool changed = !identical(newReturnType, returnType);
632 List<DartType> newParameterTypes =
633 Types.substTypes(parameterTypes, arguments, parameters);
634 List<DartType> newOptionalParameterTypes =
635 Types.substTypes(optionalParameterTypes, arguments, parameters);
636 List<DartType> newNamedParameterTypes =
637 Types.substTypes(namedParameterTypes, arguments, parameters);
638 if (!changed &&
639 (!identical(parameterTypes, newParameterTypes) ||
640 !identical(optionalParameterTypes, newOptionalParameterTypes) ||
641 !identical(namedParameterTypes, newNamedParameterTypes))) {
642 changed = true;
643 }
644 if (changed) {
645 // Create a new type only if necessary.
646 return new FunctionType.internal(element,
647 newReturnType,
648 newParameterTypes,
649 newOptionalParameterTypes,
650 namedParameters,
651 newNamedParameterTypes);
652 }
653 return this;
654 }
655
656 DartType unalias(Compiler compiler) => this;
657
658 DartType get typeVariableOccurrence {
659 TypeVariableType typeVariableType = returnType.typeVariableOccurrence;
660 if (typeVariableType != null) return typeVariableType;
661
662 typeVariableType = _findTypeVariableOccurrence(parameterTypes);
663 if (typeVariableType != null) return typeVariableType;
664
665 typeVariableType = _findTypeVariableOccurrence(optionalParameterTypes);
666 if (typeVariableType != null) return typeVariableType;
667
668 return _findTypeVariableOccurrence(namedParameterTypes);
669 }
670
671 void forEachTypeVariable(f(TypeVariableType variable)) {
672 returnType.forEachTypeVariable(f);
673 parameterTypes.forEach((DartType type) {
674 type.forEachTypeVariable(f);
675 });
676 optionalParameterTypes.forEach((DartType type) {
677 type.forEachTypeVariable(f);
678 });
679 namedParameterTypes.forEach((DartType type) {
680 type.forEachTypeVariable(f);
681 });
682 }
683
684 accept(DartTypeVisitor visitor, var argument) {
685 return visitor.visitFunctionType(this, argument);
686 }
687
688 void visitChildren(DartTypeVisitor visitor, var argument) {
689 returnType.accept(visitor, argument);
690 DartType.visitList(parameterTypes, visitor, argument);
691 DartType.visitList(optionalParameterTypes, visitor, argument);
692 DartType.visitList(namedParameterTypes, visitor, argument);
693 }
694
695 String toString() {
696 StringBuffer sb = new StringBuffer();
697 sb.write('(');
698 sb.write(parameterTypes.join(', '));
699 bool first = parameterTypes.isEmpty;
700 if (!optionalParameterTypes.isEmpty) {
701 if (!first) {
702 sb.write(', ');
703 }
704 sb.write('[');
705 sb.write(optionalParameterTypes.join(', '));
706 sb.write(']');
707 first = false;
708 }
709 if (!namedParameterTypes.isEmpty) {
710 if (!first) {
711 sb.write(', ');
712 }
713 sb.write('{');
714 first = true;
715 for (int i = 0; i < namedParameters.length; i++) {
716 if (!first) {
717 sb.write(', ');
718 }
719 sb.write(namedParameterTypes[i]);
720 sb.write(' ');
721 sb.write(namedParameters[i]);
722 first = false;
723 }
724 sb.write('}');
725 }
726 sb.write(') -> ${returnType}');
727 return sb.toString();
728 }
729
730 String get name => 'Function';
731
732 int computeArity() {
733 int arity = 0;
734 parameterTypes.forEach((_) { arity++; });
735 return arity;
736 }
737
738 int get hashCode {
739 int hash = 3 * returnType.hashCode;
740 for (DartType parameter in parameterTypes) {
741 hash = 17 * hash + 5 * parameter.hashCode;
742 }
743 for (DartType parameter in optionalParameterTypes) {
744 hash = 19 * hash + 7 * parameter.hashCode;
745 }
746 for (String name in namedParameters) {
747 hash = 23 * hash + 11 * name.hashCode;
748 }
749 for (DartType parameter in namedParameterTypes) {
750 hash = 29 * hash + 13 * parameter.hashCode;
751 }
752 return hash;
753 }
754
755 bool operator ==(other) {
756 if (other is !FunctionType) return false;
757 return returnType == other.returnType &&
758 equalElements(parameterTypes, other.parameterTypes) &&
759 equalElements(optionalParameterTypes, other.optionalParameterTypes) &&
760 equalElements(namedParameters, other.namedParameters) &&
761 equalElements(namedParameterTypes, other.namedParameterTypes);
762 }
763 }
764
765 class TypedefType extends GenericType {
766 TypedefType(TypedefElement element,
767 [List<DartType> typeArguments = const <DartType>[]])
768 : super(element, typeArguments);
769
770 TypedefType.forUserProvidedBadType(TypedefElement element,
771 [List<DartType> typeArguments =
772 const <DartType>[]])
773 : super(element, typeArguments, checkTypeArgumentCount: false);
774
775 TypedefElement get element => super.element;
776
777 TypeKind get kind => TypeKind.TYPEDEF;
778
779 String get name => element.name;
780
781 TypedefType createInstantiation(List<DartType> newTypeArguments) {
782 return new TypedefType(element, newTypeArguments);
783 }
784
785 DartType unalias(Compiler compiler) {
786 element.ensureResolved(compiler);
787 element.checkCyclicReference(compiler);
788 DartType definition = element.alias.unalias(compiler);
789 return definition.substByContext(this);
790 }
791
792 int get hashCode => super.hashCode;
793
794 TypedefType asRaw() => super.asRaw();
795
796 accept(DartTypeVisitor visitor, var argument) {
797 return visitor.visitTypedefType(this, argument);
798 }
799 }
800
801 /// A typedef which has already been resolved to its alias.
802 class ResolvedTypedefType extends TypedefType {
803 FunctionType alias;
804
805 ResolvedTypedefType(TypedefElement element,
806 List<DartType> typeArguments,
807 this.alias)
808 : super(element, typeArguments) {
809 assert(invariant(element, alias != null,
810 message: 'Alias must be non-null on $element.'));
811 }
812
813 FunctionType unalias(Compiler compiler) => alias;
814 }
815
816 /**
817 * Special type for the `dynamic` type.
818 */
819 class DynamicType extends DartType {
820 const DynamicType();
821
822 Element get element => null;
823
824 String get name => 'dynamic';
825
826 bool get treatAsDynamic => true;
827
828 TypeKind get kind => TypeKind.DYNAMIC;
829
830 DartType unalias(Compiler compiler) => this;
831
832 DartType subst(List<DartType> arguments, List<DartType> parameters) => this;
833
834 accept(DartTypeVisitor visitor, var argument) {
835 return visitor.visitDynamicType(this, argument);
836 }
837
838 String toString() => name;
839 }
840
841 /**
842 * [InterfaceMember] encapsulates a member (method, field, property) with
843 * the types of the declarer and receiver in order to do substitution on the
844 * member type.
845 *
846 * Consider for instance these classes and the variable `B<String> b`:
847 *
848 * class A<E> {
849 * E field;
850 * }
851 * class B<F> extends A<F> {}
852 *
853 * In an [InterfaceMember] for `b.field` the [receiver] is the type
854 * `B<String>` and the declarer is the type `A<F>`, which is the supertype of
855 * `B<F>` from which `field` has been inherited. To compute the type of
856 * `b.field` we must first substitute `E` by `F` using the relation between
857 * `A<E>` and `A<F>`, and then `F` by `String` using the relation between
858 * `B<F>` and `B<String>`.
859 */
860 class InterfaceMember implements MemberSignature {
861 final InterfaceType instance;
862 final MemberSignature member;
863
864 InterfaceMember(this.instance, this.member);
865
866 Name get name => member.name;
867
868 DartType get type => member.type.substByContext(instance);
869
870 FunctionType get functionType => member.functionType.substByContext(instance);
871
872 bool get isGetter => member.isGetter;
873
874 bool get isSetter => member.isSetter;
875
876 bool get isMethod => member.isMethod;
877
878 Iterable<Member> get declarations => member.declarations;
879 }
880
881 abstract class DartTypeVisitor<R, A> {
882 const DartTypeVisitor();
883
884 R visitType(DartType type, A argument);
885
886 R visitVoidType(VoidType type, A argument) =>
887 visitType(type, argument);
888
889 R visitTypeVariableType(TypeVariableType type, A argument) =>
890 visitType(type, argument);
891
892 R visitFunctionType(FunctionType type, A argument) =>
893 visitType(type, argument);
894
895 R visitMalformedType(MalformedType type, A argument) =>
896 visitType(type, argument);
897
898 R visitStatementType(StatementType type, A argument) =>
899 visitType(type, argument);
900
901 R visitGenericType(GenericType type, A argument) =>
902 visitType(type, argument);
903
904 R visitInterfaceType(InterfaceType type, A argument) =>
905 visitGenericType(type, argument);
906
907 R visitTypedefType(TypedefType type, A argument) =>
908 visitGenericType(type, argument);
909
910 R visitDynamicType(DynamicType type, A argument) =>
911 visitType(type, argument);
912 }
913
914 /**
915 * Abstract visitor for determining relations between types.
916 */
917 abstract class AbstractTypeRelation extends DartTypeVisitor<bool, DartType> {
918 final Compiler compiler;
919
920 AbstractTypeRelation(Compiler this.compiler);
921
922 bool visitType(DartType t, DartType s) {
923 throw 'internal error: unknown type kind ${t.kind}';
924 }
925
926 bool visitVoidType(VoidType t, DartType s) {
927 assert(s is! VoidType);
928 return false;
929 }
930
931 bool invalidTypeArguments(DartType t, DartType s);
932
933 bool invalidFunctionReturnTypes(DartType t, DartType s);
934
935 bool invalidFunctionParameterTypes(DartType t, DartType s);
936
937 bool invalidTypeVariableBounds(DartType bound, DartType s);
938
939 /// Handle as dynamic for both subtype and more specific relation to avoid
940 /// spurious errors from malformed types.
941 bool visitMalformedType(MalformedType t, DartType s) => true;
942
943 bool visitInterfaceType(InterfaceType t, DartType s) {
944
945 // TODO(johnniwinther): Currently needed since literal types like int,
946 // double, bool etc. might not have been resolved yet.
947 t.element.ensureResolved(compiler);
948
949 bool checkTypeArguments(InterfaceType instance, InterfaceType other) {
950 List<DartType> tTypeArgs = instance.typeArguments;
951 List<DartType> sTypeArgs = other.typeArguments;
952 assert(tTypeArgs.length == sTypeArgs.length);
953 for (int i = 0; i < tTypeArgs.length; i++) {
954 if (invalidTypeArguments(tTypeArgs[i], sTypeArgs[i])) {
955 return false;
956 }
957 }
958 return true;
959 }
960
961 if (s is InterfaceType) {
962 InterfaceType instance = t.asInstanceOf(s.element);
963 return instance != null && checkTypeArguments(instance, s);
964 } else {
965 return false;
966 }
967 }
968
969 bool visitFunctionType(FunctionType t, DartType s) {
970 if (s is InterfaceType && identical(s.element, compiler.functionClass)) {
971 return true;
972 }
973 if (s is !FunctionType) return false;
974 FunctionType tf = t;
975 FunctionType sf = s;
976 if (invalidFunctionReturnTypes(tf.returnType, sf.returnType)) {
977 return false;
978 }
979
980 // TODO(johnniwinther): Rewrite the function subtyping to be more readable
981 // but still as efficient.
982
983 // For the comments we use the following abbreviations:
984 // x.p : parameterTypes on [:x:],
985 // x.o : optionalParameterTypes on [:x:], and
986 // len(xs) : length of list [:xs:].
987
988 Iterator<DartType> tps = tf.parameterTypes.iterator;
989 Iterator<DartType> sps = sf.parameterTypes.iterator;
990 bool sNotEmpty = sps.moveNext();
991 bool tNotEmpty = tps.moveNext();
992 tNext() => (tNotEmpty = tps.moveNext());
993 sNext() => (sNotEmpty = sps.moveNext());
994
995 bool incompatibleParameters() {
996 while (tNotEmpty && sNotEmpty) {
997 if (invalidFunctionParameterTypes(tps.current, sps.current)) {
998 return true;
999 }
1000 tNext();
1001 sNext();
1002 }
1003 return false;
1004 }
1005
1006 if (incompatibleParameters()) return false;
1007 if (tNotEmpty) {
1008 // We must have [: len(t.p) <= len(s.p) :].
1009 return false;
1010 }
1011 if (!sf.namedParameters.isEmpty) {
1012 // We must have [: len(t.p) == len(s.p) :].
1013 if (sNotEmpty) {
1014 return false;
1015 }
1016 // Since named parameters are globally ordered we can determine the
1017 // subset relation with a linear search for [:sf.namedParameters:]
1018 // within [:tf.namedParameters:].
1019 List<String> tNames = tf.namedParameters;
1020 List<DartType> tTypes = tf.namedParameterTypes;
1021 List<String> sNames = sf.namedParameters;
1022 List<DartType> sTypes = sf.namedParameterTypes;
1023 int tIndex = 0;
1024 int sIndex = 0;
1025 while (tIndex < tNames.length && sIndex < sNames.length) {
1026 if (tNames[tIndex] == sNames[sIndex]) {
1027 if (invalidFunctionParameterTypes(tTypes[tIndex], sTypes[sIndex])) {
1028 return false;
1029 }
1030 sIndex++;
1031 }
1032 tIndex++;
1033 }
1034 if (sIndex < sNames.length) {
1035 // We didn't find all names.
1036 return false;
1037 }
1038 } else {
1039 // Check the remaining [: s.p :] against [: t.o :].
1040 tps = tf.optionalParameterTypes.iterator;
1041 tNext();
1042 if (incompatibleParameters()) return false;
1043 if (sNotEmpty) {
1044 // We must have [: len(t.p) + len(t.o) >= len(s.p) :].
1045 return false;
1046 }
1047 if (!sf.optionalParameterTypes.isEmpty) {
1048 // Check the remaining [: s.o :] against the remaining [: t.o :].
1049 sps = sf.optionalParameterTypes.iterator;
1050 sNext();
1051 if (incompatibleParameters()) return false;
1052 if (sNotEmpty) {
1053 // We didn't find enough parameters:
1054 // We must have [: len(t.p) + len(t.o) <= len(s.p) + len(s.o) :].
1055 return false;
1056 }
1057 } else {
1058 if (sNotEmpty) {
1059 // We must have [: len(t.p) + len(t.o) >= len(s.p) :].
1060 return false;
1061 }
1062 }
1063 }
1064 return true;
1065 }
1066
1067 bool visitTypeVariableType(TypeVariableType t, DartType s) {
1068 // Identity check is handled in [isSubtype].
1069 DartType bound = t.element.bound;
1070 if (bound.isTypeVariable) {
1071 // The bound is potentially cyclic so we need to be extra careful.
1072 Set<TypeVariableElement> seenTypeVariables =
1073 new Set<TypeVariableElement>();
1074 seenTypeVariables.add(t.element);
1075 while (bound.isTypeVariable) {
1076 TypeVariableElement element = bound.element;
1077 if (identical(bound.element, s.element)) {
1078 // [t] extends [s].
1079 return true;
1080 }
1081 if (seenTypeVariables.contains(element)) {
1082 // We have a cycle and have already checked all bounds in the cycle
1083 // against [s] and can therefore conclude that [t] is not a subtype
1084 // of [s].
1085 return false;
1086 }
1087 seenTypeVariables.add(element);
1088 bound = element.bound;
1089 }
1090 }
1091 if (invalidTypeVariableBounds(bound, s)) return false;
1092 return true;
1093 }
1094 }
1095
1096 class MoreSpecificVisitor extends AbstractTypeRelation {
1097 MoreSpecificVisitor(Compiler compiler) : super(compiler);
1098
1099 bool isMoreSpecific(DartType t, DartType s) {
1100 if (identical(t, s) || s.treatAsDynamic ||
1101 identical(t.element, compiler.nullClass)) {
1102 return true;
1103 }
1104 if (t.isVoid || s.isVoid) {
1105 return false;
1106 }
1107 if (t.treatAsDynamic) {
1108 return false;
1109 }
1110 if (identical(s.element, compiler.objectClass)) {
1111 return true;
1112 }
1113 t = t.unalias(compiler);
1114 s = s.unalias(compiler);
1115
1116 return t.accept(this, s);
1117 }
1118
1119 bool invalidTypeArguments(DartType t, DartType s) {
1120 return !isMoreSpecific(t, s);
1121 }
1122
1123 bool invalidFunctionReturnTypes(DartType t, DartType s) {
1124 if (s.treatAsDynamic && t.isVoid) return true;
1125 return !s.isVoid && !isMoreSpecific(t, s);
1126 }
1127
1128 bool invalidFunctionParameterTypes(DartType t, DartType s) {
1129 return !isMoreSpecific(t, s);
1130 }
1131
1132 bool invalidTypeVariableBounds(DartType bound, DartType s) {
1133 return !isMoreSpecific(bound, s);
1134 }
1135 }
1136
1137 /**
1138 * Type visitor that determines the subtype relation two types.
1139 */
1140 class SubtypeVisitor extends MoreSpecificVisitor {
1141
1142 SubtypeVisitor(Compiler compiler) : super(compiler);
1143
1144 bool isSubtype(DartType t, DartType s) {
1145 return t.treatAsDynamic || isMoreSpecific(t, s);
1146 }
1147
1148 bool isAssignable(DartType t, DartType s) {
1149 return isSubtype(t, s) || isSubtype(s, t);
1150 }
1151
1152 bool invalidTypeArguments(DartType t, DartType s) {
1153 return !isSubtype(t, s);
1154 }
1155
1156 bool invalidFunctionReturnTypes(DartType t, DartType s) {
1157 return !s.isVoid && !isAssignable(t, s);
1158 }
1159
1160 bool invalidFunctionParameterTypes(DartType t, DartType s) {
1161 return !isAssignable(t, s);
1162 }
1163
1164 bool invalidTypeVariableBounds(DartType bound, DartType s) {
1165 return !isSubtype(bound, s);
1166 }
1167
1168 bool visitInterfaceType(InterfaceType t, DartType s) {
1169 if (super.visitInterfaceType(t, s)) return true;
1170
1171 if (s is InterfaceType &&
1172 s.element == compiler.functionClass &&
1173 t.element.callType != null) {
1174 return true;
1175 } else if (s is FunctionType) {
1176 FunctionType callType = t.callType;
1177 return callType != null && isSubtype(callType, s);
1178 }
1179 return false;
1180 }
1181 }
1182
1183 /**
1184 * Callback used to check whether the [typeArgument] of [type] is a valid
1185 * substitute for the bound of [typeVariable]. [bound] holds the bound against
1186 * which [typeArgument] should be checked.
1187 */
1188 typedef void CheckTypeVariableBound(GenericType type,
1189 DartType typeArgument,
1190 TypeVariableType typeVariable,
1191 DartType bound);
1192
1193 class Types {
1194 final Compiler compiler;
1195 final MoreSpecificVisitor moreSpecificVisitor;
1196 final SubtypeVisitor subtypeVisitor;
1197 final PotentialSubtypeVisitor potentialSubtypeVisitor;
1198
1199 Types(Compiler compiler)
1200 : this.compiler = compiler,
1201 this.moreSpecificVisitor = new MoreSpecificVisitor(compiler),
1202 this.subtypeVisitor = new SubtypeVisitor(compiler),
1203 this.potentialSubtypeVisitor = new PotentialSubtypeVisitor(compiler);
1204
1205 Types copy(Compiler compiler) {
1206 return new Types(compiler);
1207 }
1208
1209 /** Returns true if [t] is more specific than [s]. */
1210 bool isMoreSpecific(DartType t, DartType s) {
1211 return moreSpecificVisitor.isMoreSpecific(t, s);
1212 }
1213
1214 /**
1215 * Returns the most specific type of [t] and [s] or `null` if neither is more
1216 * specific than the other.
1217 */
1218 DartType getMostSpecific(DartType t, DartType s) {
1219 if (isMoreSpecific(t, s)) {
1220 return t;
1221 } else if (isMoreSpecific(s, t)) {
1222 return s;
1223 } else {
1224 return null;
1225 }
1226 }
1227
1228 /** Returns true if t is a subtype of s */
1229 bool isSubtype(DartType t, DartType s) {
1230 return subtypeVisitor.isSubtype(t, s);
1231 }
1232
1233 bool isAssignable(DartType r, DartType s) {
1234 return subtypeVisitor.isAssignable(r, s);
1235 }
1236
1237 static const int IS_SUBTYPE = 1;
1238 static const int MAYBE_SUBTYPE = 0;
1239 static const int NOT_SUBTYPE = -1;
1240
1241 int computeSubtypeRelation(DartType t, DartType s) {
1242 // TODO(johnniwinther): Compute this directly in [isPotentialSubtype].
1243 if (isSubtype(t, s)) return IS_SUBTYPE;
1244 return isPotentialSubtype(t, s) ? MAYBE_SUBTYPE : NOT_SUBTYPE;
1245 }
1246
1247 bool isPotentialSubtype(DartType t, DartType s) {
1248 // TODO(johnniwinther): Return a set of variable points in the positive
1249 // cases.
1250 return potentialSubtypeVisitor.isSubtype(t, s);
1251 }
1252
1253 /**
1254 * Checks the type arguments of [type] against the type variable bounds
1255 * declared on [element]. Calls [checkTypeVariableBound] on each type
1256 * argument and bound.
1257 */
1258 void checkTypeVariableBounds(GenericType type,
1259 CheckTypeVariableBound checkTypeVariableBound) {
1260 TypeDeclarationElement element = type.element;
1261 List<DartType> typeArguments = type.typeArguments;
1262 List<DartType> typeVariables = element.typeVariables;
1263 assert(typeVariables.length == typeArguments.length);
1264 for (int index = 0; index < typeArguments.length; index++) {
1265 TypeVariableType typeVariable = typeVariables[index];
1266 DartType bound = typeVariable.element.bound.substByContext(type);
1267 DartType typeArgument = typeArguments[index];
1268 checkTypeVariableBound(type, typeArgument, typeVariable, bound);
1269 }
1270 }
1271
1272 /**
1273 * Helper method for performing substitution of a list of types.
1274 *
1275 * If no types are changed by the substitution, the [types] is returned
1276 * instead of a newly created list.
1277 */
1278 static List<DartType> substTypes(List<DartType> types,
1279 List<DartType> arguments,
1280 List<DartType> parameters) {
1281 bool changed = false;
1282 List<DartType> result = new List<DartType>.generate(types.length, (index) {
1283 DartType type = types[index];
1284 DartType argument = type.subst(arguments, parameters);
1285 if (!changed && !identical(argument, type)) {
1286 changed = true;
1287 }
1288 return argument;
1289 });
1290 // Use the new List only if necessary.
1291 return changed ? result : types;
1292 }
1293
1294 /**
1295 * Returns the [ClassElement] which declares the type variables occurring in
1296 * [type], or [:null:] if [type] does not contain type variables.
1297 */
1298 static ClassElement getClassContext(DartType type) {
1299 TypeVariableType typeVariable = type.typeVariableOccurrence;
1300 if (typeVariable == null) return null;
1301 return typeVariable.element.typeDeclaration;
1302 }
1303
1304 /**
1305 * A `compareTo` function that globally orders types using
1306 * [Elements.compareByPosition] to order types defined by a declaration.
1307 *
1308 * The order is:
1309 * * void
1310 * * dynamic
1311 * * interface, typedef, type variables ordered by element order
1312 * - interface and typedef of the same element are ordered by
1313 * the order of their type arguments
1314 * * function types, ordered by
1315 * - return type
1316 * - required parameter types
1317 * - optional parameter types
1318 * - named parameter names
1319 * - named parameter types
1320 * * malformed types
1321 * * statement types
1322 */
1323 static int compare(DartType a, DartType b) {
1324 if (a == b) return 0;
1325 if (a.isVoid) {
1326 // [b] is not void => a < b.
1327 return -1;
1328 } else if (b.isVoid) {
1329 // [a] is not void => a > b.
1330 return 1;
1331 }
1332 if (a.isDynamic) {
1333 // [b] is not dynamic => a < b.
1334 return -1;
1335 } else if (b.isDynamic) {
1336 // [a] is not dynamic => a > b.
1337 return 1;
1338 }
1339 bool isDefinedByDeclaration(DartType type) {
1340 return type.isInterfaceType ||
1341 type.isTypedef ||
1342 type.isTypeVariable;
1343 }
1344
1345 if (isDefinedByDeclaration(a)) {
1346 if (isDefinedByDeclaration(b)) {
1347 int result = Elements.compareByPosition(a.element, b.element);
1348 if (result != 0) return result;
1349 if (a.isTypeVariable) {
1350 return b.isTypeVariable
1351 ? 0
1352 : 1; // [b] is not a type variable => a > b.
1353 } else {
1354 if (b.isTypeVariable) {
1355 // [a] is not a type variable => a < b.
1356 return -1;
1357 } else {
1358 return compareList((a as GenericType).typeArguments,
1359 (b as GenericType).typeArguments);
1360 }
1361 }
1362 } else {
1363 // [b] is neither an interface, typedef, type variable, dynamic,
1364 // nor void => a < b.
1365 return -1;
1366 }
1367 } else if (isDefinedByDeclaration(b)) {
1368 // [a] is neither an interface, typedef, type variable, dynamic,
1369 // nor void => a > b.
1370 return 1;
1371 }
1372 if (a.isFunctionType) {
1373 if (b.isFunctionType) {
1374 FunctionType aFunc = a;
1375 FunctionType bFunc = b;
1376 int result = compare(aFunc.returnType, bFunc.returnType);
1377 if (result != 0) return result;
1378 result = compareList(aFunc.parameterTypes, bFunc.parameterTypes);
1379 if (result != 0) return result;
1380 result = compareList(aFunc.optionalParameterTypes,
1381 bFunc.optionalParameterTypes);
1382 if (result != 0) return result;
1383 // TODO(karlklose): reuse [compareList].
1384 Iterator<String> aNames = aFunc.namedParameters.iterator;
1385 Iterator<String> bNames = bFunc.namedParameters.iterator;
1386 while (aNames.moveNext() && bNames.moveNext()) {
1387 int result = aNames.current.compareTo(bNames.current);
1388 if (result != 0) return result;
1389 }
1390 if (aNames.moveNext()) {
1391 // [aNames] is longer that [bNames] => a > b.
1392 return 1;
1393 } else if (bNames.moveNext()) {
1394 // [bNames] is longer that [aNames] => a < b.
1395 return -1;
1396 }
1397 return compareList(aFunc.namedParameterTypes,
1398 bFunc.namedParameterTypes);
1399 } else {
1400 // [b] is a malformed or statement type => a < b.
1401 return -1;
1402 }
1403 } else if (b.isFunctionType) {
1404 // [b] is a malformed or statement type => a > b.
1405 return 1;
1406 }
1407 if (a.kind == TypeKind.STATEMENT) {
1408 if (b.kind == TypeKind.STATEMENT) {
1409 return 0;
1410 } else {
1411 // [b] is a malformed type => a > b.
1412 return 1;
1413 }
1414 } else if (b.kind == TypeKind.STATEMENT) {
1415 // [a] is a malformed type => a < b.
1416 return -1;
1417 }
1418 assert (a.isMalformed);
1419 assert (b.isMalformed);
1420 // TODO(johnniwinther): Can we do this better?
1421 return Elements.compareByPosition(a.element, b.element);
1422 }
1423
1424 static int compareList(List<DartType> a, List<DartType> b) {
1425 for (int index = 0; index < min(a.length, b.length); index++) {
1426 int result = compare(a[index], b[index]);
1427 if (result != 0) return result;
1428 }
1429 if (a.length > b.length) {
1430 return 1;
1431 } else if (a.length < b.length) {
1432 return -1;
1433 }
1434 return 0;
1435 }
1436
1437 static List<DartType> sorted(Iterable<DartType> types) {
1438 return types.toList()..sort(compare);
1439 }
1440
1441 /// Computes the least upper bound of two interface types [a] and [b].
1442 InterfaceType computeLeastUpperBoundInterfaces(InterfaceType a,
1443 InterfaceType b) {
1444
1445 /// Returns the set of supertypes of [type] at depth [depth].
1446 Set<DartType> getSupertypesAtDepth(InterfaceType type, int depth) {
1447 OrderedTypeSet types = type.element.allSupertypesAndSelf;
1448 Set<DartType> set = new Set<DartType>();
1449 types.forEach(depth, (DartType supertype) {
1450 set.add(supertype.substByContext(type));
1451 });
1452 return set;
1453 }
1454
1455 ClassElement aClass = a.element;
1456 ClassElement bClass = b.element;
1457 int maxCommonDepth = min(aClass.hierarchyDepth, bClass.hierarchyDepth);
1458 for (int depth = maxCommonDepth; depth >= 0; depth--) {
1459 Set<DartType> aTypeSet = getSupertypesAtDepth(a, depth);
1460 Set<DartType> bTypeSet = getSupertypesAtDepth(b, depth);
1461 Set<DartType> intersection = aTypeSet..retainAll(bTypeSet);
1462 if (intersection.length == 1) {
1463 return intersection.first;
1464 }
1465 }
1466 invariant(CURRENT_ELEMENT_SPANNABLE, false,
1467 message: 'No least upper bound computed for $a and $b.');
1468 return null;
1469 }
1470
1471 /// Computes the least upper bound of the types in the longest prefix of [a]
1472 /// and [b].
1473 List<DartType> computeLeastUpperBoundsTypes(List<DartType> a,
1474 List<DartType> b) {
1475 if (a.isEmpty || b.isEmpty) return const <DartType>[];
1476 int prefixLength = min(a.length, b.length);
1477 List<DartType> types = new List<DartType>(prefixLength);
1478 for (int index = 0; index < prefixLength; index++) {
1479 types[index] = computeLeastUpperBound(a[index], b[index]);
1480 }
1481 return types;
1482 }
1483
1484 /// Computes the least upper bound of two function types [a] and [b].
1485 ///
1486 /// If the required parameter count of [a] and [b] does not match, `Function`
1487 /// is returned.
1488 ///
1489 /// Otherwise, a function type is returned whose return type and
1490 /// parameter types are the least upper bound of those of [a] and [b],
1491 /// respectively. In addition, the optional parameters are the least upper
1492 /// bound of the longest common prefix of the optional parameters of [a] and
1493 /// [b], and the named parameters are the least upper bound of those common to
1494 /// [a] and [b].
1495 DartType computeLeastUpperBoundFunctionTypes(FunctionType a,
1496 FunctionType b) {
1497 if (a.parameterTypes.length != b.parameterTypes.length) {
1498 return compiler.functionClass.rawType;
1499 }
1500 DartType returnType = computeLeastUpperBound(a.returnType, b.returnType);
1501 List<DartType> parameterTypes =
1502 computeLeastUpperBoundsTypes(a.parameterTypes, b.parameterTypes);
1503 List<DartType> optionalParameterTypes =
1504 computeLeastUpperBoundsTypes(a.optionalParameterTypes,
1505 b.optionalParameterTypes);
1506 List<String> namedParameters = <String>[];
1507 List<String> aNamedParameters = a.namedParameters;
1508 List<String> bNamedParameters = b.namedParameters;
1509 List<DartType> namedParameterTypes = <DartType>[];
1510 List<DartType> aNamedParameterTypes = a.namedParameterTypes;
1511 List<DartType> bNamedParameterTypes = b.namedParameterTypes;
1512 int aIndex = 0;
1513 int bIndex = 0;
1514 int prefixLength =
1515 min(aNamedParameterTypes.length, bNamedParameterTypes.length);
1516 while (aIndex < aNamedParameters.length &&
1517 bIndex < bNamedParameters.length) {
1518 String aNamedParameter = aNamedParameters[aIndex];
1519 String bNamedParameter = bNamedParameters[bIndex];
1520 int result = aNamedParameter.compareTo(bNamedParameter);
1521 if (result == 0) {
1522 namedParameters.add(aNamedParameter);
1523 namedParameterTypes.add(computeLeastUpperBound(
1524 aNamedParameterTypes[aIndex], bNamedParameterTypes[bIndex]));
1525 }
1526 if (result <= 0) {
1527 aIndex++;
1528 }
1529 if (result >= 0) {
1530 bIndex++;
1531 }
1532 }
1533 return new FunctionType.synthesized(
1534 returnType,
1535 parameterTypes, optionalParameterTypes,
1536 namedParameters, namedParameterTypes);
1537 }
1538
1539 /// Computes the least upper bound of two types of which at least one is a
1540 /// type variable. The least upper bound of a type variable is defined in
1541 /// terms of its bound, but to ensure reflexivity we need to check for common
1542 /// bounds transitively.
1543 DartType computeLeastUpperBoundTypeVariableTypes(DartType a,
1544 DartType b) {
1545 Set<DartType> typeVariableBounds = new Set<DartType>();
1546 while (a.isTypeVariable) {
1547 if (a == b) return a;
1548 typeVariableBounds.add(a);
1549 TypeVariableElement element = a.element;
1550 a = element.bound;
1551 }
1552 while (b.isTypeVariable) {
1553 if (typeVariableBounds.contains(b)) return b;
1554 TypeVariableElement element = b.element;
1555 b = element.bound;
1556 }
1557 return computeLeastUpperBound(a, b);
1558 }
1559
1560 /// Computes the least upper bound for [a] and [b].
1561 DartType computeLeastUpperBound(DartType a, DartType b) {
1562 if (a == b) return a;
1563
1564 if (a.isTypeVariable ||
1565 b.isTypeVariable) {
1566 return computeLeastUpperBoundTypeVariableTypes(a, b);
1567 }
1568
1569 a = a.unalias(compiler);
1570 b = b.unalias(compiler);
1571
1572 if (a.treatAsDynamic || b.treatAsDynamic) return const DynamicType();
1573 if (a.isVoid || b.isVoid) return const VoidType();
1574
1575 if (a.isFunctionType && b.isFunctionType) {
1576 return computeLeastUpperBoundFunctionTypes(a, b);
1577 }
1578
1579 if (a.isFunctionType) {
1580 a = compiler.functionClass.rawType;
1581 }
1582 if (b.isFunctionType) {
1583 b = compiler.functionClass.rawType;
1584 }
1585
1586 if (a.isInterfaceType && b.isInterfaceType) {
1587 return computeLeastUpperBoundInterfaces(a, b);
1588 }
1589 return const DynamicType();
1590 }
1591 }
1592
1593 /**
1594 * Type visitor that determines one type could a subtype of another given the
1595 * right type variable substitution. The computation is approximate and returns
1596 * [:false:] only if we are sure no such substitution exists.
1597 */
1598 class PotentialSubtypeVisitor extends SubtypeVisitor {
1599 PotentialSubtypeVisitor(Compiler compiler) : super(compiler);
1600
1601 bool isSubtype(DartType t, DartType s) {
1602 if (t is TypeVariableType || s is TypeVariableType) {
1603 return true;
1604 }
1605 return super.isSubtype(t, s);
1606 }
1607 }
1608
1609 /// Visitor used to compute an instantiation of a generic type that is more
1610 /// specific than a given type.
1611 ///
1612 /// The visitor tries to compute constraints for all type variables in the
1613 /// visited type by structurally matching it with the argument type. If the
1614 /// constraints are too complex or the two types are too different, `false`
1615 /// is returned. Otherwise, the [constraintMap] holds the valid constraints.
1616 class MoreSpecificSubtypeVisitor extends DartTypeVisitor<bool, DartType> {
1617 final Compiler compiler;
1618 Map<TypeVariableType, DartType> constraintMap;
1619
1620 MoreSpecificSubtypeVisitor(Compiler this.compiler);
1621
1622 /// Compute an instance of [element] which is more specific than [supertype].
1623 /// If no instance is found, `null` is returned.
1624 ///
1625 /// Note that this computation is a heuristic. It does not find a suggestion
1626 /// in all possible cases.
1627 InterfaceType computeMoreSpecific(ClassElement element,
1628 InterfaceType supertype) {
1629 InterfaceType supertypeInstance =
1630 element.thisType.asInstanceOf(supertype.element);
1631 if (supertypeInstance == null) return null;
1632
1633 constraintMap = new Map<TypeVariableType, DartType>();
1634 element.typeVariables.forEach((TypeVariableType typeVariable) {
1635 constraintMap[typeVariable] = const DynamicType();
1636 });
1637 if (supertypeInstance.accept(this, supertype)) {
1638 List<DartType> variables = element.typeVariables;
1639 List<DartType> typeArguments = new List<DartType>.generate(
1640 variables.length, (int index) => constraintMap[variables[index]]);
1641 return element.thisType.createInstantiation(typeArguments);
1642 }
1643 return null;
1644 }
1645
1646 bool visitType(DartType type, DartType argument) {
1647 return compiler.types.isMoreSpecific(type, argument);
1648 }
1649
1650 bool visitTypes(List<DartType> a, List<DartType> b) {
1651 int prefixLength = min(a.length, b.length);
1652 for (int index = 0; index < prefixLength; index++) {
1653 if (!a[index].accept(this, b[index])) return false;
1654 }
1655 return prefixLength == a.length && a.length == b.length;
1656 }
1657
1658 bool visitTypeVariableType(TypeVariableType type, DartType argument) {
1659 DartType constraint =
1660 compiler.types.getMostSpecific(constraintMap[type], argument);
1661 constraintMap[type] = constraint;
1662 return constraint != null;
1663 }
1664
1665 bool visitFunctionType(FunctionType type, DartType argument) {
1666 if (argument is FunctionType) {
1667 if (type.parameterTypes.length !=
1668 argument.parameterTypes.length) {
1669 return false;
1670 }
1671 if (type.optionalParameterTypes.length !=
1672 argument.optionalParameterTypes.length) {
1673 return false;
1674 }
1675 if (type.namedParameters != argument.namedParameters) {
1676 return false;
1677 }
1678
1679 if (!type.returnType.accept(this, argument.returnType)) return false;
1680 if (visitTypes(type.parameterTypes, argument.parameterTypes)) {
1681 return false;
1682 }
1683 if (visitTypes(type.optionalParameterTypes,
1684 argument.optionalParameterTypes)) {
1685 return false;
1686 }
1687 return visitTypes(type.namedParameterTypes, argument.namedParameterTypes);
1688 }
1689 return false;
1690 }
1691
1692 bool visitGenericType(GenericType type, DartType argument) {
1693 if (argument is GenericType) {
1694 if (type.element != argument.element) return false;
1695 return visitTypes(type.typeArguments, argument.typeArguments);
1696 }
1697 return false;
1698 }
1699 }
1700
1701 /// Visitor used to print type annotation like they used in the source code.
1702 /// The visitor is especially for printing a function type like
1703 /// `(Foo,[Bar])->Baz` as `Baz m(Foo a1, [Bar a2])`.
1704 class TypeDeclarationFormatter extends DartTypeVisitor<dynamic, String> {
1705 Set<String> usedNames;
1706 StringBuffer sb;
1707
1708 /// Creates textual representation of [type] as if a member by the [name] were
1709 /// declared. For instance 'String foo' for `format(String, 'foo')`.
1710 String format(DartType type, String name) {
1711 sb = new StringBuffer();
1712 usedNames = new Set<String>();
1713 type.accept(this, name);
1714 usedNames = null;
1715 return sb.toString();
1716 }
1717
1718 String createName(String name) {
1719 if (name != null && !usedNames.contains(name)) {
1720 usedNames.add(name);
1721 return name;
1722 }
1723 int index = usedNames.length;
1724 String proposal;
1725 do {
1726 proposal = '${name}${index++}';
1727 } while (usedNames.contains(proposal));
1728 usedNames.add(proposal);
1729 return proposal;
1730 }
1731
1732 void visit(DartType type) {
1733 type.accept(this, null);
1734 }
1735
1736 void visitTypes(List<DartType> types, String prefix) {
1737 bool needsComma = false;
1738 for (DartType type in types) {
1739 if (needsComma) {
1740 sb.write(', ');
1741 }
1742 type.accept(this, prefix);
1743 needsComma = true;
1744 }
1745 }
1746
1747 void visitType(DartType type, String name) {
1748 if (name == null) {
1749 sb.write(type);
1750 } else {
1751 sb.write('$type ${createName(name)}');
1752 }
1753 }
1754
1755 void visitGenericType(GenericType type, String name) {
1756 sb.write(type.name);
1757 if (!type.treatAsRaw) {
1758 sb.write('<');
1759 visitTypes(type.typeArguments, null);
1760 sb.write('>');
1761 }
1762 if (name != null) {
1763 sb.write(' ');
1764 sb.write(createName(name));
1765 }
1766 }
1767
1768 void visitFunctionType(FunctionType type, String name) {
1769 visit(type.returnType);
1770 sb.write(' ');
1771 if (name != null) {
1772 sb.write(name);
1773 } else {
1774 sb.write(createName('f'));
1775 }
1776 sb.write('(');
1777 visitTypes(type.parameterTypes, 'a');
1778 bool needsComma = !type.parameterTypes.isEmpty;
1779 if (!type.optionalParameterTypes.isEmpty) {
1780 if (needsComma) {
1781 sb.write(', ');
1782 }
1783 sb.write('[');
1784 visitTypes(type.optionalParameterTypes, 'a');
1785 sb.write(']');
1786 needsComma = true;
1787 }
1788 if (!type.namedParameterTypes.isEmpty) {
1789 if (needsComma) {
1790 sb.write(', ');
1791 }
1792 sb.write('{');
1793 List<String> namedParameters = type.namedParameters;
1794 List<DartType> namedParameterTypes = type.namedParameterTypes;
1795 needsComma = false;
1796 for (int index = 0; index < namedParameters.length; index++) {
1797 if (needsComma) {
1798 sb.write(', ');
1799 }
1800 namedParameterTypes[index].accept(this, namedParameters[index]);
1801 needsComma = true;
1802 }
1803 sb.write('}');
1804 }
1805 sb.write(')');
1806 }
1807 }
1808
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698