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

Unified Diff: sdk/lib/_internal/compiler/implementation/dart_types.dart

Issue 88483002: Compute suggestions for failed type promotions. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Updated cf. comments. Created 7 years 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | sdk/lib/_internal/compiler/implementation/typechecker.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: sdk/lib/_internal/compiler/implementation/dart_types.dart
diff --git a/sdk/lib/_internal/compiler/implementation/dart_types.dart b/sdk/lib/_internal/compiler/implementation/dart_types.dart
index cd9dff9ac36e8ce4933fb55c583aa2159ea3f573..a4603f0f6cbc10415db4b88911a20e4c907ac5f3 100644
--- a/sdk/lib/_internal/compiler/implementation/dart_types.dart
+++ b/sdk/lib/_internal/compiler/implementation/dart_types.dart
@@ -1249,11 +1249,25 @@ class Types {
this.moreSpecificVisitor, this.subtypeVisitor,
this.potentialSubtypeVisitor);
- /** Returns true if t is more specific than s */
+ /** Returns true if [t] is more specific than [s]. */
bool isMoreSpecific(DartType t, DartType s) {
return moreSpecificVisitor.isMoreSpecific(t, s);
}
+ /**
+ * Returns the most specific type of [t] and [s] or `null` if neither is more
+ * specific than the other.
+ */
+ DartType getMostSpecific(DartType t, DartType s) {
+ if (isMoreSpecific(t, s)) {
+ return t;
+ } else if (isMoreSpecific(s, t)) {
+ return s;
+ } else {
+ return null;
+ }
+ }
+
/** Returns true if t is a subtype of s */
bool isSubtype(DartType t, DartType s) {
return subtypeVisitor.isSubtype(t, s);
@@ -1652,3 +1666,97 @@ class PotentialSubtypeVisitor extends SubtypeVisitor {
return super.isSubtype(t, s);
}
}
+
+/// Visitor used to compute an instantiation of a generic type that is more
+/// specific than a given type.
+///
+/// The visitor tries to compute constraints for all type variables in the
+/// visited type by structurally matching it with the argument type. If the
+/// constraints are too complex or the two types are too different, `false`
+/// is returned. Otherwise, the [constraintMap] holds the valid constraints.
+class MoreSpecificSubtypeVisitor extends DartTypeVisitor<bool, DartType> {
+ final Compiler compiler;
+ Map<TypeVariableType, DartType> constraintMap;
+
+ MoreSpecificSubtypeVisitor(Compiler this.compiler);
+
+ /// Compute an instance of [element] which is more specific than [supertype].
+ /// If no instance is found, `null` is returned.
+ ///
+ /// Note that this computation is a heuristic. It does not find a suggestion
+ /// in all possible cases.
+ InterfaceType computeMoreSpecific(ClassElement element,
+ InterfaceType supertype) {
+ InterfaceType supertypeInstance =
+ element.thisType.asInstanceOf(supertype.element);
+ if (supertypeInstance == null) return null;
+
+ constraintMap = new Map<TypeVariableType, DartType>();
+ element.typeVariables.forEach((TypeVariableType typeVariable) {
+ constraintMap[typeVariable] = compiler.types.dynamicType;
+ });
+ if (supertypeInstance.accept(this, supertype)) {
+ LinkBuilder<DartType> typeArguments = new LinkBuilder<DartType>();
+ element.typeVariables.forEach((TypeVariableType typeVariable) {
+ typeArguments.addLast(constraintMap[typeVariable]);
+ });
+ return element.thisType._createType(typeArguments.toLink());
+ }
+ return null;
+ }
+
+ bool visitType(DartType type, DartType argument) {
+ return compiler.types.isMoreSpecific(type, argument);
+ }
+
+ bool visitTypes(Link<DartType> a, Link<DartType> b) {
+ while (!a.isEmpty && !b.isEmpty) {
+ if (!a.head.accept(this, b.head)) return false;
+ a = a.tail;
+ b = b.tail;
+ }
+ return a.isEmpty && b.isEmpty;
+ }
+
+ bool visitTypeVariableType(TypeVariableType type, DartType argument) {
+ DartType constraint =
+ compiler.types.getMostSpecific(constraintMap[type], argument);
+ constraintMap[type] = constraint;
+ return constraint != null;
+ }
+
+ bool visitFunctionType(FunctionType type, DartType argument) {
+ if (argument is FunctionType) {
+ if (type.parameterTypes.slowLength() !=
+ argument.parameterTypes.slowLength()) {
+ return false;
+ }
+ if (type.optionalParameterTypes.slowLength() !=
+ argument.optionalParameterTypes.slowLength()) {
+ return false;
+ }
+ if (type.namedParameters != argument.namedParameters) {
+ return false;
+ }
+
+ if (!type.returnType.accept(this, argument.returnType)) return false;
+ if (visitTypes(type.parameterTypes, argument.parameterTypes)) {
+ return false;
+ }
+ if (visitTypes(type.optionalParameterTypes,
+ argument.optionalParameterTypes)) {
+ return false;
+ }
+ return visitTypes(type.namedParameterTypes, argument.namedParameterTypes);
+ }
+ return false;
+ }
+
+ bool visitGenericType(GenericType type, DartType argument) {
+ if (argument is GenericType) {
+ if (type.element != argument.element) return false;
+ return visitTypes(type.typeArguments, argument.typeArguments);
+ }
+ return false;
+ }
+}
« no previous file with comments | « no previous file | sdk/lib/_internal/compiler/implementation/typechecker.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698