OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 library dart_types; | 5 library dart_types; |
6 | 6 |
| 7 import 'dart:math' show min; |
| 8 |
7 import 'dart2jslib.dart' show Compiler, invariant, Script, Message; | 9 import 'dart2jslib.dart' show Compiler, invariant, Script, Message; |
8 import 'elements/modelx.dart' | 10 import 'elements/modelx.dart' |
9 show VoidElementX, LibraryElementX, BaseClassElementX; | 11 show VoidElementX, LibraryElementX, BaseClassElementX; |
10 import 'elements/elements.dart'; | 12 import 'elements/elements.dart'; |
11 import 'util/util.dart' show Link, LinkBuilder; | 13 import 'ordered_typeset.dart' show OrderedTypeSet; |
| 14 import 'util/util.dart' show Link, LinkBuilder, CURRENT_ELEMENT_SPANNABLE; |
12 | 15 |
13 class TypeKind { | 16 class TypeKind { |
14 final String id; | 17 final String id; |
15 | 18 |
16 const TypeKind(String this.id); | 19 const TypeKind(String this.id); |
17 | 20 |
18 static const TypeKind FUNCTION = const TypeKind('function'); | 21 static const TypeKind FUNCTION = const TypeKind('function'); |
19 static const TypeKind INTERFACE = const TypeKind('interface'); | 22 static const TypeKind INTERFACE = const TypeKind('interface'); |
20 static const TypeKind STATEMENT = const TypeKind('statement'); | 23 static const TypeKind STATEMENT = const TypeKind('statement'); |
21 static const TypeKind TYPEDEF = const TypeKind('typedef'); | 24 static const TypeKind TYPEDEF = const TypeKind('typedef'); |
(...skipping 1448 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1470 } else if (!b.isEmpty) { | 1473 } else if (!b.isEmpty) { |
1471 // [b] is longer than [a] => a < b. | 1474 // [b] is longer than [a] => a < b. |
1472 return -1; | 1475 return -1; |
1473 } | 1476 } |
1474 return 0; | 1477 return 0; |
1475 } | 1478 } |
1476 | 1479 |
1477 static List<DartType> sorted(Iterable<DartType> types) { | 1480 static List<DartType> sorted(Iterable<DartType> types) { |
1478 return types.toList()..sort(compare); | 1481 return types.toList()..sort(compare); |
1479 } | 1482 } |
| 1483 |
| 1484 /// Computes the least upper bound of two interface types [a] and [b]. |
| 1485 InterfaceType computeLeastUpperBoundInterfaces(InterfaceType a, |
| 1486 InterfaceType b) { |
| 1487 |
| 1488 /// Returns the set of supertypes of [type] at depth [depth]. |
| 1489 Set<DartType> getSupertypesAtDepth(InterfaceType type, int depth) { |
| 1490 ClassElement cls = type.element; |
| 1491 OrderedTypeSet types = cls.allSupertypesAndSelf; |
| 1492 Link<DartType> typeVariables = cls.typeVariables; |
| 1493 Link<DartType> typeArguments = type.typeArguments; |
| 1494 Set<DartType> set = new Set<DartType>(); |
| 1495 types.forEach(depth, (DartType type) { |
| 1496 set.add(type.subst(typeArguments, typeVariables)); |
| 1497 }); |
| 1498 return set; |
| 1499 } |
| 1500 |
| 1501 ClassElement aClass = a.element; |
| 1502 ClassElement bClass = b.element; |
| 1503 int maxCommonDepth = min(aClass.hierarchyDepth, bClass.hierarchyDepth); |
| 1504 for (int depth = maxCommonDepth; depth >= 0; depth--) { |
| 1505 Set<DartType> aTypeSet = getSupertypesAtDepth(a, depth); |
| 1506 Set<DartType> bTypeSet = getSupertypesAtDepth(b, depth); |
| 1507 Set<DartType> intersection = aTypeSet..retainAll(bTypeSet); |
| 1508 if (intersection.length == 1) { |
| 1509 return intersection.first; |
| 1510 } |
| 1511 } |
| 1512 assert(invariant(CURRENT_ELEMENT_SPANNABLE, false, |
| 1513 message: 'No least upper bound computed for $a and $b.')); |
| 1514 } |
| 1515 |
| 1516 /// Computes the least upper bound of the types in the longest prefix of [a] |
| 1517 /// and [b]. |
| 1518 Link<DartType> computeLeastUpperBoundsTypes(Link<DartType> a, |
| 1519 Link<DartType> b) { |
| 1520 if (a.isEmpty || b.isEmpty) return const Link<DartType>(); |
| 1521 LinkBuilder<DartType> types = new LinkBuilder<DartType>(); |
| 1522 while (!a.isEmpty && !b.isEmpty) { |
| 1523 types.addLast(computeLeastUpperBound(a.head, b.head)); |
| 1524 a = a.tail; |
| 1525 b = b.tail; |
| 1526 } |
| 1527 return types.toLink(); |
| 1528 } |
| 1529 |
| 1530 /// Computes the least upper bound of two function types [a] and [b]. |
| 1531 /// |
| 1532 /// If the required parameter count of [a] and [b] does not match, `Function` |
| 1533 /// is returned. |
| 1534 /// |
| 1535 /// Otherwise, a function type is returned whose return type and |
| 1536 /// parameter types are the least upper bound of those of [a] and [b], |
| 1537 /// respectively. In addition, the optional parameters are the least upper |
| 1538 /// bound of the longest common prefix of the optional parameters of [a] and |
| 1539 /// [b], and the named parameters are the least upper bound of those common to |
| 1540 /// [a] and [b]. |
| 1541 DartType computeLeastUpperBoundFunctionTypes(FunctionType a, |
| 1542 FunctionType b) { |
| 1543 if (a.parameterTypes.slowLength() != b.parameterTypes.slowLength()) { |
| 1544 return compiler.functionClass.rawType; |
| 1545 } |
| 1546 DartType returnType = computeLeastUpperBound(a.returnType, b.returnType); |
| 1547 Link<DartType> parameterTypes = |
| 1548 computeLeastUpperBoundsTypes(a.parameterTypes, b.parameterTypes); |
| 1549 Link<DartType> optionalParameterTypes = |
| 1550 computeLeastUpperBoundsTypes(a.optionalParameterTypes, |
| 1551 b.optionalParameterTypes); |
| 1552 LinkBuilder<String> namedParameters = new LinkBuilder<String>(); |
| 1553 Link<String> aNamedParameters = a.namedParameters; |
| 1554 Link<String> bNamedParameters = b.namedParameters; |
| 1555 LinkBuilder<DartType> namedParameterTypes = new LinkBuilder<DartType>(); |
| 1556 Link<DartType> aNamedParameterTypes = a.namedParameterTypes; |
| 1557 Link<DartType> bNamedParameterTypes = b.namedParameterTypes; |
| 1558 while (!aNamedParameters.isEmpty && !bNamedParameters.isEmpty) { |
| 1559 String aNamedParameter = aNamedParameters.head; |
| 1560 String bNamedParameter = bNamedParameters.head; |
| 1561 int result = aNamedParameter.compareTo(bNamedParameter); |
| 1562 if (result == 0) { |
| 1563 namedParameters.addLast(aNamedParameter); |
| 1564 namedParameterTypes.addLast(computeLeastUpperBound( |
| 1565 aNamedParameterTypes.head, bNamedParameterTypes.head)); |
| 1566 } |
| 1567 if (result <= 0) { |
| 1568 aNamedParameters = aNamedParameters.tail; |
| 1569 aNamedParameterTypes = aNamedParameterTypes.tail; |
| 1570 } |
| 1571 if (result >= 0) { |
| 1572 bNamedParameters = bNamedParameters.tail; |
| 1573 bNamedParameterTypes = bNamedParameterTypes.tail; |
| 1574 } |
| 1575 } |
| 1576 return new FunctionType(compiler.functionClass, |
| 1577 returnType, |
| 1578 parameterTypes, optionalParameterTypes, |
| 1579 namedParameters.toLink(), namedParameterTypes.toLink()); |
| 1580 } |
| 1581 |
| 1582 /// Computes the least upper bound of two types of which at least one is a |
| 1583 /// type variable. The least upper bound of a type variable is defined in |
| 1584 /// terms of its bound, but to ensure reflexivity we need to check for common |
| 1585 /// bounds transitively. |
| 1586 DartType computeLeastUpperBoundTypeVariableTypes(DartType a, |
| 1587 DartType b) { |
| 1588 Set<DartType> typeVariableBounds = new Set<DartType>(); |
| 1589 while (a.kind == TypeKind.TYPE_VARIABLE) { |
| 1590 if (a == b) return a; |
| 1591 typeVariableBounds.add(a); |
| 1592 TypeVariableElement element = a.element; |
| 1593 a = element.bound; |
| 1594 } |
| 1595 while (b.kind == TypeKind.TYPE_VARIABLE) { |
| 1596 if (typeVariableBounds.contains(b)) return b; |
| 1597 TypeVariableElement element = b.element; |
| 1598 b = element.bound; |
| 1599 } |
| 1600 return computeLeastUpperBound(a, b); |
| 1601 } |
| 1602 |
| 1603 /// Computes the least upper bound for [a] and [b]. |
| 1604 DartType computeLeastUpperBound(DartType a, DartType b) { |
| 1605 if (a == b) return a; |
| 1606 |
| 1607 if (a.kind == TypeKind.TYPE_VARIABLE || |
| 1608 b.kind == TypeKind.TYPE_VARIABLE) { |
| 1609 return computeLeastUpperBoundTypeVariableTypes(a, b); |
| 1610 } |
| 1611 |
| 1612 a = a.unalias(compiler); |
| 1613 b = b.unalias(compiler); |
| 1614 |
| 1615 if (a.treatAsDynamic || b.treatAsDynamic) return dynamicType; |
| 1616 if (a.isVoid || b.isVoid) return voidType; |
| 1617 |
| 1618 if (a.kind == TypeKind.FUNCTION && b.kind == TypeKind.FUNCTION) { |
| 1619 return computeLeastUpperBoundFunctionTypes(a, b); |
| 1620 } |
| 1621 |
| 1622 if (a.kind == TypeKind.FUNCTION) { |
| 1623 a = compiler.functionClass.rawType; |
| 1624 } |
| 1625 if (b.kind == TypeKind.FUNCTION) { |
| 1626 b = compiler.functionClass.rawType; |
| 1627 } |
| 1628 |
| 1629 if (a.kind == TypeKind.INTERFACE && b.kind == TypeKind.INTERFACE) { |
| 1630 return computeLeastUpperBoundInterfaces(a, b); |
| 1631 } |
| 1632 return dynamicType; |
| 1633 } |
1480 } | 1634 } |
1481 | 1635 |
1482 /** | 1636 /** |
1483 * Type visitor that determines one type could a subtype of another given the | 1637 * Type visitor that determines one type could a subtype of another given the |
1484 * right type variable substitution. The computation is approximate and returns | 1638 * right type variable substitution. The computation is approximate and returns |
1485 * [:false:] only if we are sure no such substitution exists. | 1639 * [:false:] only if we are sure no such substitution exists. |
1486 */ | 1640 */ |
1487 class PotentialSubtypeVisitor extends SubtypeVisitor { | 1641 class PotentialSubtypeVisitor extends SubtypeVisitor { |
1488 PotentialSubtypeVisitor(Compiler compiler, | 1642 PotentialSubtypeVisitor(Compiler compiler, |
1489 DynamicType dynamicType, | 1643 DynamicType dynamicType, |
1490 VoidType voidType) | 1644 VoidType voidType) |
1491 : super(compiler, dynamicType, voidType); | 1645 : super(compiler, dynamicType, voidType); |
1492 | 1646 |
1493 | 1647 |
1494 bool isSubtype(DartType t, DartType s) { | 1648 bool isSubtype(DartType t, DartType s) { |
1495 if (t is TypeVariableType || s is TypeVariableType) { | 1649 if (t is TypeVariableType || s is TypeVariableType) { |
1496 return true; | 1650 return true; |
1497 } | 1651 } |
1498 return super.isSubtype(t, s); | 1652 return super.isSubtype(t, s); |
1499 } | 1653 } |
1500 } | 1654 } |
OLD | NEW |