OLD | NEW |
1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 import '../common_elements.dart'; | 5 import '../common_elements.dart'; |
6 import '../util/util.dart' show equalElements; | 6 import '../util/util.dart' show equalElements; |
7 import 'entities.dart'; | 7 import 'entities.dart'; |
8 | 8 |
9 /// Hierarchy to describe types in Dart. | 9 /// Hierarchy to describe types in Dart. |
10 /// | 10 /// |
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
118 } | 118 } |
119 | 119 |
120 bool get treatAsRaw { | 120 bool get treatAsRaw { |
121 for (DartType type in typeArguments) { | 121 for (DartType type in typeArguments) { |
122 if (!type.treatAsDynamic) return false; | 122 if (!type.treatAsDynamic) return false; |
123 } | 123 } |
124 return true; | 124 return true; |
125 } | 125 } |
126 | 126 |
127 @override | 127 @override |
128 R accept<R, A>(DartTypeVisitor visitor, A argument) => | 128 R accept<R, A>(DartTypeVisitor<R, A> visitor, A argument) => |
129 visitor.visitInterfaceType(this, argument); | 129 visitor.visitInterfaceType(this, argument); |
130 | 130 |
131 int get hashCode { | 131 int get hashCode { |
132 int hash = element.hashCode; | 132 int hash = element.hashCode; |
133 for (DartType argument in typeArguments) { | 133 for (DartType argument in typeArguments) { |
134 int argumentHash = argument != null ? argument.hashCode : 0; | 134 int argumentHash = argument != null ? argument.hashCode : 0; |
135 hash = 17 * hash + 3 * argumentHash; | 135 hash = 17 * hash + 3 * argumentHash; |
136 } | 136 } |
137 return hash; | 137 return hash; |
138 } | 138 } |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
183 } | 183 } |
184 int index = parameters.indexOf(this); | 184 int index = parameters.indexOf(this); |
185 if (index != -1) { | 185 if (index != -1) { |
186 return arguments[index]; | 186 return arguments[index]; |
187 } | 187 } |
188 // The type variable was not substituted. | 188 // The type variable was not substituted. |
189 return this; | 189 return this; |
190 } | 190 } |
191 | 191 |
192 @override | 192 @override |
193 R accept<R, A>(DartTypeVisitor visitor, A argument) => | 193 R accept<R, A>(DartTypeVisitor<R, A> visitor, A argument) => |
194 visitor.visitTypeVariableType(this, argument); | 194 visitor.visitTypeVariableType(this, argument); |
195 | 195 |
196 int get hashCode => 17 * element.hashCode; | 196 int get hashCode => 17 * element.hashCode; |
197 | 197 |
198 bool operator ==(other) { | 198 bool operator ==(other) { |
199 if (other is! TypeVariableType) return false; | 199 if (other is! TypeVariableType) return false; |
200 return identical(other.element, element); | 200 return identical(other.element, element); |
201 } | 201 } |
202 | 202 |
203 String toString() => '${element.typeDeclaration.name}.${element.name}'; | 203 String toString() => '${element.typeDeclaration.name}.${element.name}'; |
204 } | 204 } |
205 | 205 |
206 class VoidType extends DartType { | 206 class VoidType extends DartType { |
207 const VoidType(); | 207 const VoidType(); |
208 | 208 |
209 bool get isVoid => true; | 209 bool get isVoid => true; |
210 | 210 |
211 DartType subst(List<DartType> arguments, List<DartType> parameters) { | 211 DartType subst(List<DartType> arguments, List<DartType> parameters) { |
212 // `void` cannot be substituted. | 212 // `void` cannot be substituted. |
213 return this; | 213 return this; |
214 } | 214 } |
215 | 215 |
216 @override | 216 @override |
217 R accept<R, A>(DartTypeVisitor visitor, A argument) => | 217 R accept<R, A>(DartTypeVisitor<R, A> visitor, A argument) => |
218 visitor.visitVoidType(this, argument); | 218 visitor.visitVoidType(this, argument); |
219 | 219 |
220 int get hashCode => 6007; | 220 int get hashCode => 6007; |
221 | 221 |
222 String toString() => 'void'; | 222 String toString() => 'void'; |
223 } | 223 } |
224 | 224 |
225 class DynamicType extends DartType { | 225 class DynamicType extends DartType { |
226 const DynamicType(); | 226 const DynamicType(); |
227 | 227 |
228 @override | 228 @override |
229 bool get isDynamic => true; | 229 bool get isDynamic => true; |
230 | 230 |
231 @override | 231 @override |
232 bool get treatAsDynamic => true; | 232 bool get treatAsDynamic => true; |
233 | 233 |
234 DartType subst(List<DartType> arguments, List<DartType> parameters) { | 234 DartType subst(List<DartType> arguments, List<DartType> parameters) { |
235 // `dynamic` cannot be substituted. | 235 // `dynamic` cannot be substituted. |
236 return this; | 236 return this; |
237 } | 237 } |
238 | 238 |
239 @override | 239 @override |
240 R accept<R, A>(DartTypeVisitor visitor, A argument) => | 240 R accept<R, A>(DartTypeVisitor<R, A> visitor, A argument) => |
241 visitor.visitDynamicType(this, argument); | 241 visitor.visitDynamicType(this, argument); |
242 | 242 |
243 int get hashCode => 91; | 243 int get hashCode => 91; |
244 | 244 |
245 String toString() => 'dynamic'; | 245 String toString() => 'dynamic'; |
246 } | 246 } |
247 | 247 |
248 class FunctionType extends DartType { | 248 class FunctionType extends DartType { |
249 final DartType returnType; | 249 final DartType returnType; |
250 final List<DartType> parameterTypes; | 250 final List<DartType> parameterTypes; |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
302 } | 302 } |
303 if (changed) { | 303 if (changed) { |
304 // Create a new type only if necessary. | 304 // Create a new type only if necessary. |
305 return new FunctionType(newReturnType, newParameterTypes, | 305 return new FunctionType(newReturnType, newParameterTypes, |
306 newOptionalParameterTypes, namedParameters, newNamedParameterTypes); | 306 newOptionalParameterTypes, namedParameters, newNamedParameterTypes); |
307 } | 307 } |
308 return this; | 308 return this; |
309 } | 309 } |
310 | 310 |
311 @override | 311 @override |
312 R accept<R, A>(DartTypeVisitor visitor, A argument) => | 312 R accept<R, A>(DartTypeVisitor<R, A> visitor, A argument) => |
313 visitor.visitFunctionType(this, argument); | 313 visitor.visitFunctionType(this, argument); |
314 | 314 |
315 int get hashCode { | 315 int get hashCode { |
316 int hash = 3 * returnType.hashCode; | 316 int hash = 3 * returnType.hashCode; |
317 for (DartType parameter in parameterTypes) { | 317 for (DartType parameter in parameterTypes) { |
318 hash = 17 * hash + 5 * parameter.hashCode; | 318 hash = 17 * hash + 5 * parameter.hashCode; |
319 } | 319 } |
320 for (DartType parameter in optionalParameterTypes) { | 320 for (DartType parameter in optionalParameterTypes) { |
321 hash = 19 * hash + 7 * parameter.hashCode; | 321 hash = 19 * hash + 7 * parameter.hashCode; |
322 } | 322 } |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
403 } | 403 } |
404 return argument; | 404 return argument; |
405 }); | 405 }); |
406 // Use the new List only if necessary. | 406 // Use the new List only if necessary. |
407 return changed ? result : types; | 407 return changed ? result : types; |
408 } | 408 } |
409 | 409 |
410 abstract class DartTypeVisitor<R, A> { | 410 abstract class DartTypeVisitor<R, A> { |
411 const DartTypeVisitor(); | 411 const DartTypeVisitor(); |
412 | 412 |
413 R visit(DartType type, A argument) => type.accept(this, argument); | 413 R visit(covariant DartType type, A argument) => type.accept(this, argument); |
414 | 414 |
415 R visitVoidType(VoidType type, A argument) => null; | 415 R visitVoidType(covariant VoidType type, A argument) => null; |
416 | 416 |
417 R visitTypeVariableType(TypeVariableType type, A argument) => null; | 417 R visitTypeVariableType(covariant TypeVariableType type, A argument) => null; |
418 | 418 |
419 R visitFunctionType(FunctionType type, A argument) => null; | 419 R visitFunctionType(covariant FunctionType type, A argument) => null; |
420 | 420 |
421 R visitInterfaceType(InterfaceType type, A argument) => null; | 421 R visitInterfaceType(covariant InterfaceType type, A argument) => null; |
422 | 422 |
423 R visitDynamicType(DynamicType type, A argument) => null; | 423 R visitDynamicType(covariant DynamicType type, A argument) => null; |
424 } | 424 } |
425 | 425 |
426 abstract class BaseDartTypeVisitor<R, A> extends DartTypeVisitor<R, A> { | 426 abstract class BaseDartTypeVisitor<R, A> extends DartTypeVisitor<R, A> { |
427 const BaseDartTypeVisitor(); | 427 const BaseDartTypeVisitor(); |
428 | 428 |
429 R visitType(DartType type, A argument); | 429 R visitType(covariant DartType type, A argument); |
430 | 430 |
431 @override | 431 @override |
432 R visitVoidType(VoidType type, A argument) => visitType(type, argument); | 432 R visitVoidType(covariant VoidType type, A argument) => |
433 | |
434 @override | |
435 R visitTypeVariableType(TypeVariableType type, A argument) => | |
436 visitType(type, argument); | 433 visitType(type, argument); |
437 | 434 |
438 @override | 435 @override |
439 R visitFunctionType(FunctionType type, A argument) => | 436 R visitTypeVariableType(covariant TypeVariableType type, A argument) => |
440 visitType(type, argument); | 437 visitType(type, argument); |
441 | 438 |
442 @override | 439 @override |
443 R visitInterfaceType(InterfaceType type, A argument) => | 440 R visitFunctionType(covariant FunctionType type, A argument) => |
444 visitType(type, argument); | 441 visitType(type, argument); |
445 | 442 |
446 @override | 443 @override |
447 R visitDynamicType(DynamicType type, A argument) => visitType(type, argument); | 444 R visitInterfaceType(covariant InterfaceType type, A argument) => |
| 445 visitType(type, argument); |
| 446 |
| 447 @override |
| 448 R visitDynamicType(covariant DynamicType type, A argument) => |
| 449 visitType(type, argument); |
448 } | 450 } |
449 | 451 |
450 /// Abstract visitor for determining relations between types. | 452 /// Abstract visitor for determining relations between types. |
451 abstract class AbstractTypeRelation | 453 abstract class AbstractTypeRelation<T extends DartType> |
452 extends BaseDartTypeVisitor<bool, DartType> { | 454 extends BaseDartTypeVisitor<bool, T> { |
453 CommonElements get commonElements; | 455 CommonElements get commonElements; |
454 | 456 |
455 /// Ensures that the super hierarchy of [type] is computed. | 457 /// Ensures that the super hierarchy of [type] is computed. |
456 void ensureResolved(InterfaceType type) {} | 458 void ensureResolved(InterfaceType type) {} |
457 | 459 |
458 /// Returns the unaliased version of [type]. | 460 /// Returns the unaliased version of [type]. |
459 DartType getUnaliased(DartType type) => type.unaliased; | 461 T getUnaliased(T type) => type.unaliased; |
460 | 462 |
461 /// Returns [type] as an instance of [cls], or `null` if [type] is not subtype | 463 /// Returns [type] as an instance of [cls], or `null` if [type] is not subtype |
462 /// if [cls]. | 464 /// if [cls]. |
463 InterfaceType asInstanceOf(InterfaceType type, ClassEntity cls); | 465 InterfaceType asInstanceOf(InterfaceType type, ClassEntity cls); |
464 | 466 |
465 /// Returns the type of the `call` method on [type], or `null` if the class | 467 /// Returns the type of the `call` method on [type], or `null` if the class |
466 /// of [type] does not have a `call` method. | 468 /// of [type] does not have a `call` method. |
467 FunctionType getCallType(InterfaceType type); | 469 FunctionType getCallType(InterfaceType type); |
468 | 470 |
469 /// Returns the declared bound of [element]. | 471 /// Returns the declared bound of [element]. |
470 DartType getTypeVariableBound(TypeVariableEntity element); | 472 DartType getTypeVariableBound(TypeVariableEntity element); |
471 | 473 |
472 bool visitType(DartType t, DartType s) { | 474 bool visitType(T t, T s) { |
473 throw 'internal error: unknown type ${t}'; | 475 throw 'internal error: unknown type ${t}'; |
474 } | 476 } |
475 | 477 |
476 bool visitVoidType(VoidType t, DartType s) { | 478 bool visitVoidType(VoidType t, T s) { |
477 assert(s is! VoidType); | 479 assert(s is! VoidType); |
478 return false; | 480 return false; |
479 } | 481 } |
480 | 482 |
481 bool invalidTypeArguments(DartType t, DartType s); | 483 bool invalidTypeArguments(T t, T s); |
482 | 484 |
483 bool invalidFunctionReturnTypes(DartType t, DartType s); | 485 bool invalidFunctionReturnTypes(T t, T s); |
484 | 486 |
485 bool invalidFunctionParameterTypes(DartType t, DartType s); | 487 bool invalidFunctionParameterTypes(T t, T s); |
486 | 488 |
487 bool invalidTypeVariableBounds(DartType bound, DartType s); | 489 bool invalidTypeVariableBounds(T bound, T s); |
488 | 490 |
489 bool invalidCallableType(DartType callType, DartType s); | 491 bool invalidCallableType(covariant DartType callType, covariant DartType s); |
490 | 492 |
491 bool visitInterfaceType(InterfaceType t, DartType s) { | 493 bool visitInterfaceType(InterfaceType t, covariant DartType s) { |
492 ensureResolved(t); | 494 ensureResolved(t); |
493 | 495 |
494 bool checkTypeArguments(InterfaceType instance, InterfaceType other) { | 496 bool checkTypeArguments(InterfaceType instance, InterfaceType other) { |
495 List<DartType> tTypeArgs = instance.typeArguments; | 497 List<T> tTypeArgs = instance.typeArguments; |
496 List<DartType> sTypeArgs = other.typeArguments; | 498 List<T> sTypeArgs = other.typeArguments; |
497 assert(tTypeArgs.length == sTypeArgs.length); | 499 assert(tTypeArgs.length == sTypeArgs.length); |
498 for (int i = 0; i < tTypeArgs.length; i++) { | 500 for (int i = 0; i < tTypeArgs.length; i++) { |
499 if (invalidTypeArguments(tTypeArgs[i], sTypeArgs[i])) { | 501 if (invalidTypeArguments(tTypeArgs[i], sTypeArgs[i])) { |
500 return false; | 502 return false; |
501 } | 503 } |
502 } | 504 } |
503 return true; | 505 return true; |
504 } | 506 } |
505 | 507 |
506 if (s is InterfaceType) { | 508 if (s is InterfaceType) { |
(...skipping 25 matching lines...) Expand all Loading... |
532 } | 534 } |
533 | 535 |
534 // TODO(johnniwinther): Rewrite the function subtyping to be more readable | 536 // TODO(johnniwinther): Rewrite the function subtyping to be more readable |
535 // but still as efficient. | 537 // but still as efficient. |
536 | 538 |
537 // For the comments we use the following abbreviations: | 539 // For the comments we use the following abbreviations: |
538 // x.p : parameterTypes on [:x:], | 540 // x.p : parameterTypes on [:x:], |
539 // x.o : optionalParameterTypes on [:x:], and | 541 // x.o : optionalParameterTypes on [:x:], and |
540 // len(xs) : length of list [:xs:]. | 542 // len(xs) : length of list [:xs:]. |
541 | 543 |
542 Iterator<DartType> tps = tf.parameterTypes.iterator; | 544 Iterator<T> tps = tf.parameterTypes.iterator; |
543 Iterator<DartType> sps = sf.parameterTypes.iterator; | 545 Iterator<T> sps = sf.parameterTypes.iterator; |
544 bool sNotEmpty = sps.moveNext(); | 546 bool sNotEmpty = sps.moveNext(); |
545 bool tNotEmpty = tps.moveNext(); | 547 bool tNotEmpty = tps.moveNext(); |
546 tNext() => (tNotEmpty = tps.moveNext()); | 548 tNext() => (tNotEmpty = tps.moveNext()); |
547 sNext() => (sNotEmpty = sps.moveNext()); | 549 sNext() => (sNotEmpty = sps.moveNext()); |
548 | 550 |
549 bool incompatibleParameters() { | 551 bool incompatibleParameters() { |
550 while (tNotEmpty && sNotEmpty) { | 552 while (tNotEmpty && sNotEmpty) { |
551 if (invalidFunctionParameterTypes(tps.current, sps.current)) { | 553 if (invalidFunctionParameterTypes(tps.current, sps.current)) { |
552 return true; | 554 return true; |
553 } | 555 } |
(...skipping 10 matching lines...) Expand all Loading... |
564 } | 566 } |
565 if (!sf.namedParameters.isEmpty) { | 567 if (!sf.namedParameters.isEmpty) { |
566 // We must have [: len(t.p) == len(s.p) :]. | 568 // We must have [: len(t.p) == len(s.p) :]. |
567 if (sNotEmpty) { | 569 if (sNotEmpty) { |
568 return false; | 570 return false; |
569 } | 571 } |
570 // Since named parameters are globally ordered we can determine the | 572 // Since named parameters are globally ordered we can determine the |
571 // subset relation with a linear search for [:sf.namedParameters:] | 573 // subset relation with a linear search for [:sf.namedParameters:] |
572 // within [:tf.namedParameters:]. | 574 // within [:tf.namedParameters:]. |
573 List<String> tNames = tf.namedParameters; | 575 List<String> tNames = tf.namedParameters; |
574 List<DartType> tTypes = tf.namedParameterTypes; | 576 List<T> tTypes = tf.namedParameterTypes; |
575 List<String> sNames = sf.namedParameters; | 577 List<String> sNames = sf.namedParameters; |
576 List<DartType> sTypes = sf.namedParameterTypes; | 578 List<T> sTypes = sf.namedParameterTypes; |
577 int tIndex = 0; | 579 int tIndex = 0; |
578 int sIndex = 0; | 580 int sIndex = 0; |
579 while (tIndex < tNames.length && sIndex < sNames.length) { | 581 while (tIndex < tNames.length && sIndex < sNames.length) { |
580 if (tNames[tIndex] == sNames[sIndex]) { | 582 if (tNames[tIndex] == sNames[sIndex]) { |
581 if (invalidFunctionParameterTypes(tTypes[tIndex], sTypes[sIndex])) { | 583 if (invalidFunctionParameterTypes(tTypes[tIndex], sTypes[sIndex])) { |
582 return false; | 584 return false; |
583 } | 585 } |
584 sIndex++; | 586 sIndex++; |
585 } | 587 } |
586 tIndex++; | 588 tIndex++; |
(...skipping 24 matching lines...) Expand all Loading... |
611 } else { | 613 } else { |
612 if (sNotEmpty) { | 614 if (sNotEmpty) { |
613 // We must have [: len(t.p) + len(t.o) >= len(s.p) :]. | 615 // We must have [: len(t.p) + len(t.o) >= len(s.p) :]. |
614 return false; | 616 return false; |
615 } | 617 } |
616 } | 618 } |
617 } | 619 } |
618 return true; | 620 return true; |
619 } | 621 } |
620 | 622 |
621 bool visitTypeVariableType(TypeVariableType t, DartType s) { | 623 bool visitTypeVariableType(TypeVariableType t, T s) { |
622 // Identity check is handled in [isSubtype]. | 624 // Identity check is handled in [isSubtype]. |
623 DartType bound = getTypeVariableBound(t.element); | 625 DartType bound = getTypeVariableBound(t.element); |
624 if (bound.isTypeVariable) { | 626 if (bound.isTypeVariable) { |
625 // The bound is potentially cyclic so we need to be extra careful. | 627 // The bound is potentially cyclic so we need to be extra careful. |
626 Set<TypeVariableEntity> seenTypeVariables = new Set<TypeVariableEntity>(); | 628 Set<TypeVariableEntity> seenTypeVariables = new Set<TypeVariableEntity>(); |
627 seenTypeVariables.add(t.element); | 629 seenTypeVariables.add(t.element); |
628 while (bound.isTypeVariable) { | 630 while (bound.isTypeVariable) { |
629 TypeVariableType typeVariable = bound; | 631 TypeVariableType typeVariable = bound; |
630 if (bound == s) { | 632 if (bound == s) { |
631 // [t] extends [s]. | 633 // [t] extends [s]. |
632 return true; | 634 return true; |
633 } | 635 } |
634 if (seenTypeVariables.contains(typeVariable.element)) { | 636 if (seenTypeVariables.contains(typeVariable.element)) { |
635 // We have a cycle and have already checked all bounds in the cycle | 637 // We have a cycle and have already checked all bounds in the cycle |
636 // against [s] and can therefore conclude that [t] is not a subtype | 638 // against [s] and can therefore conclude that [t] is not a subtype |
637 // of [s]. | 639 // of [s]. |
638 return false; | 640 return false; |
639 } | 641 } |
640 seenTypeVariables.add(typeVariable.element); | 642 seenTypeVariables.add(typeVariable.element); |
641 bound = getTypeVariableBound(typeVariable.element); | 643 bound = getTypeVariableBound(typeVariable.element); |
642 } | 644 } |
643 } | 645 } |
644 if (invalidTypeVariableBounds(bound, s)) return false; | 646 if (invalidTypeVariableBounds(bound, s)) return false; |
645 return true; | 647 return true; |
646 } | 648 } |
647 } | 649 } |
648 | 650 |
649 abstract class MoreSpecificVisitor extends AbstractTypeRelation { | 651 abstract class MoreSpecificVisitor<T extends DartType> |
650 bool isMoreSpecific(DartType t, DartType s) { | 652 extends AbstractTypeRelation<T> { |
| 653 bool isMoreSpecific(T t, T s) { |
651 if (identical(t, s) || s.treatAsDynamic || t == commonElements.nullType) { | 654 if (identical(t, s) || s.treatAsDynamic || t == commonElements.nullType) { |
652 return true; | 655 return true; |
653 } | 656 } |
654 if (t.isVoid || s.isVoid) { | 657 if (t.isVoid || s.isVoid) { |
655 return false; | 658 return false; |
656 } | 659 } |
657 if (t.treatAsDynamic) { | 660 if (t.treatAsDynamic) { |
658 return false; | 661 return false; |
659 } | 662 } |
660 if (s == commonElements.objectType) { | 663 if (s == commonElements.objectType) { |
661 return true; | 664 return true; |
662 } | 665 } |
663 t = getUnaliased(t); | 666 t = getUnaliased(t); |
664 s = getUnaliased(s); | 667 s = getUnaliased(s); |
665 | 668 |
666 return t.accept(this, s); | 669 return t.accept(this, s); |
667 } | 670 } |
668 | 671 |
669 bool invalidTypeArguments(DartType t, DartType s) { | 672 bool invalidTypeArguments(T t, T s) { |
670 return !isMoreSpecific(t, s); | 673 return !isMoreSpecific(t, s); |
671 } | 674 } |
672 | 675 |
673 bool invalidFunctionReturnTypes(DartType t, DartType s) { | 676 bool invalidFunctionReturnTypes(T t, T s) { |
674 if (s.treatAsDynamic && t.isVoid) return true; | 677 if (s.treatAsDynamic && t.isVoid) return true; |
675 return !s.isVoid && !isMoreSpecific(t, s); | 678 return !s.isVoid && !isMoreSpecific(t, s); |
676 } | 679 } |
677 | 680 |
678 bool invalidFunctionParameterTypes(DartType t, DartType s) { | 681 bool invalidFunctionParameterTypes(T t, T s) { |
679 return !isMoreSpecific(t, s); | 682 return !isMoreSpecific(t, s); |
680 } | 683 } |
681 | 684 |
682 bool invalidTypeVariableBounds(DartType bound, DartType s) { | 685 bool invalidTypeVariableBounds(T bound, T s) { |
683 return !isMoreSpecific(bound, s); | 686 return !isMoreSpecific(bound, s); |
684 } | 687 } |
685 | 688 |
686 bool invalidCallableType(DartType callType, DartType s) { | 689 bool invalidCallableType(covariant DartType callType, covariant DartType s) { |
687 return !isMoreSpecific(callType, s); | 690 return !isMoreSpecific(callType, s); |
688 } | 691 } |
689 } | 692 } |
690 | 693 |
691 /// Type visitor that determines the subtype relation two types. | 694 /// Type visitor that determines the subtype relation two types. |
692 abstract class SubtypeVisitor extends MoreSpecificVisitor { | 695 abstract class SubtypeVisitor<T extends DartType> |
693 bool isSubtype(DartType t, DartType s) { | 696 extends MoreSpecificVisitor<T> { |
| 697 bool isSubtype(T t, T s) { |
694 return t.treatAsDynamic || isMoreSpecific(t, s); | 698 return t.treatAsDynamic || isMoreSpecific(t, s); |
695 } | 699 } |
696 | 700 |
697 bool isAssignable(DartType t, DartType s) { | 701 bool isAssignable(T t, T s) { |
698 return isSubtype(t, s) || isSubtype(s, t); | 702 return isSubtype(t, s) || isSubtype(s, t); |
699 } | 703 } |
700 | 704 |
701 bool invalidTypeArguments(DartType t, DartType s) { | 705 bool invalidTypeArguments(T t, T s) { |
702 return !isSubtype(t, s); | 706 return !isSubtype(t, s); |
703 } | 707 } |
704 | 708 |
705 bool invalidFunctionReturnTypes(DartType t, DartType s) { | 709 bool invalidFunctionReturnTypes(T t, T s) { |
706 return !s.isVoid && !isAssignable(t, s); | 710 return !s.isVoid && !isAssignable(t, s); |
707 } | 711 } |
708 | 712 |
709 bool invalidFunctionParameterTypes(DartType t, DartType s) { | 713 bool invalidFunctionParameterTypes(T t, T s) { |
710 return !isAssignable(t, s); | 714 return !isAssignable(t, s); |
711 } | 715 } |
712 | 716 |
713 bool invalidTypeVariableBounds(DartType bound, DartType s) { | 717 bool invalidTypeVariableBounds(T bound, T s) { |
714 return !isSubtype(bound, s); | 718 return !isSubtype(bound, s); |
715 } | 719 } |
716 | 720 |
717 bool invalidCallableType(DartType callType, DartType s) { | 721 bool invalidCallableType(covariant DartType callType, covariant DartType s) { |
718 return !isSubtype(callType, s); | 722 return !isSubtype(callType, s); |
719 } | 723 } |
720 } | 724 } |
721 | 725 |
722 /// Type visitor that determines one type could a subtype of another given the | 726 /// Type visitor that determines one type could a subtype of another given the |
723 /// right type variable substitution. The computation is approximate and returns | 727 /// right type variable substitution. The computation is approximate and returns |
724 /// `false` only if we are sure no such substitution exists. | 728 /// `false` only if we are sure no such substitution exists. |
725 abstract class PotentialSubtypeVisitor extends SubtypeVisitor { | 729 abstract class PotentialSubtypeVisitor<T extends DartType> |
726 bool isSubtype(DartType t, DartType s) { | 730 extends SubtypeVisitor<T> { |
| 731 bool isSubtype(T t, T s) { |
727 if (t is TypeVariableType || s is TypeVariableType) { | 732 if (t is TypeVariableType || s is TypeVariableType) { |
728 return true; | 733 return true; |
729 } | 734 } |
730 return super.isSubtype(t, s); | 735 return super.isSubtype(t, s); |
731 } | 736 } |
732 } | 737 } |
733 | 738 |
734 /// Basic interface for the Dart type system. | 739 /// Basic interface for the Dart type system. |
735 abstract class DartTypes { | 740 abstract class DartTypes { |
736 /// The types defined in 'dart:core'. | 741 /// The types defined in 'dart:core'. |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
808 // include a runtime value for method type variables this must be updated. | 813 // include a runtime value for method type variables this must be updated. |
809 // For full support the global assumption that all type variables are | 814 // For full support the global assumption that all type variables are |
810 // declared by the same enclosing class will not hold: Both an enclosing | 815 // declared by the same enclosing class will not hold: Both an enclosing |
811 // method and an enclosing class may define type variables, so the return | 816 // method and an enclosing class may define type variables, so the return |
812 // type cannot be [ClassElement] and the caller must be prepared to look in | 817 // type cannot be [ClassElement] and the caller must be prepared to look in |
813 // two locations, not one. Currently we ignore method type variables by | 818 // two locations, not one. Currently we ignore method type variables by |
814 // returning in the next statement. | 819 // returning in the next statement. |
815 return contextClass; | 820 return contextClass; |
816 } | 821 } |
817 } | 822 } |
OLD | NEW |