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

Unified Diff: pkg/analyzer/lib/src/dart/element/type.dart

Issue 1663353002: Refactor strong mode's function type isSubtypeOf() to use the same structural walking code as spec … (Closed) Base URL: https://github.com/dart-lang/sdk.git@master
Patch Set: Merge. Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | pkg/analyzer/lib/src/generated/type_system.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: pkg/analyzer/lib/src/dart/element/type.dart
diff --git a/pkg/analyzer/lib/src/dart/element/type.dart b/pkg/analyzer/lib/src/dart/element/type.dart
index 7c2aebe16b2886a777760b3050ef04c56917c2ff..568ac91b4063b427117a02f3592fb4836f675d01 100644
--- a/pkg/analyzer/lib/src/dart/element/type.dart
+++ b/pkg/analyzer/lib/src/dart/element/type.dart
@@ -727,44 +727,78 @@ class FunctionTypeImpl extends TypeImpl implements FunctionType {
[bool withDynamic = false, Set<Element> visitedElements]) {
// Note: visitedElements is only used for breaking recursion in the type
// hierarchy; we don't use it when recursing into the function type.
- return _testTypeRelation(
- type, (TypeImpl t, TypeImpl s) => t.isMoreSpecificThan(s, withDynamic));
+ bool relation = _trivialFunctionRelation(type);
+ if (relation != null) {
+ return relation;
+ }
+
+ return structuralCompare(this, type,
+ (TypeImpl t, TypeImpl s) => t.isMoreSpecificThan(s, withDynamic));
}
@override
bool isSubtypeOf(DartType type) {
- return _testTypeRelation(
- type, (TypeImpl t, TypeImpl s) => t.isAssignableTo(s));
+ bool relation = _trivialFunctionRelation(type);
+ if (relation != null) {
+ return relation;
+ }
+
+ return structuralCompare(
+ this, type, (TypeImpl t, TypeImpl s) => t.isAssignableTo(s));
}
/**
- * Determines if this function type has a [relation] with [type].
+ * Tests if [other] meets any of the easy relation cases for [isSubtypeOf]
+ * and [isMoreSpecificThan].
*
- * Used for both [isMoreSpecificThan] and [isSubtypeOf] which are structurally
- * identical but use their own relation when recursing into parameters and
- * return types.
+ * Returns `true` if the relation is known to hold, `false` if it isn't, or
+ * `null` if it's unknown and a deeper structural comparison is needed.
*/
- bool _testTypeRelation(DartType type, bool relation(TypeImpl t, TypeImpl s)) {
+ bool _trivialFunctionRelation(DartType other) {
// Trivial base cases.
- if (type == null) {
+ if (other == null) {
return false;
- } else if (identical(this, type) ||
- type.isDynamic ||
- type.isDartCoreFunction ||
- type.isObject) {
+ } else if (identical(this, other) ||
+ other.isDynamic ||
+ other.isDartCoreFunction ||
+ other.isObject) {
return true;
- } else if (type is! FunctionType) {
+ } else if (other is! FunctionType) {
return false;
- } else if (this == type) {
+ } else if (this == other) {
return true;
}
- FunctionType s = type as FunctionType;
- List<DartType> tRequired = normalParameterTypes;
+ return null;
+ }
+
+ /**
+ * Compares two function types [t] and [s] to see if their corresponding
+ * parameter types match [parameterRelation] and their return types match
+ * [returnRelation].
+ *
+ * Used for the various relations on function types which have the same
+ * structural rules for handling optional parameters and arity, but use their
+ * own relation for comparing corresponding paramaters or return types.
+ *
+ * If [returnRelation] is omitted, uses [parameterRelation] for both.
+ */
+ static bool structuralCompare(FunctionType t, FunctionType s,
+ bool parameterRelation(DartType t, DartType s),
+ [bool returnRelation(DartType t, DartType s)]) {
+ // Test the return types.
+ returnRelation ??= parameterRelation;
+ DartType sRetType = s.returnType;
+ if (!sRetType.isVoid && !returnRelation(t.returnType, sRetType)) {
+ return false;
+ }
+
+ // Test the parameter types.
+ List<DartType> tRequired = t.normalParameterTypes;
List<DartType> sRequired = s.normalParameterTypes;
- List<DartType> tOptional = optionalParameterTypes;
+ List<DartType> tOptional = t.optionalParameterTypes;
List<DartType> sOptional = s.optionalParameterTypes;
- Map<String, DartType> tNamed = namedParameterTypes;
+ Map<String, DartType> tNamed = t.namedParameterTypes;
Map<String, DartType> sNamed = s.namedParameterTypes;
// If one function has positional and the other has named parameters,
@@ -787,7 +821,7 @@ class FunctionTypeImpl extends TypeImpl implements FunctionType {
if (tParamType == null) {
return false;
}
- if (!relation(tParamType, sNamed[key])) {
+ if (!parameterRelation(tParamType, sNamed[key])) {
return false;
}
}
@@ -816,13 +850,12 @@ class FunctionTypeImpl extends TypeImpl implements FunctionType {
}
for (int i = 0; i < sPositional.length; i++) {
- if (!relation(tPositional[i], sPositional[i])) {
+ if (!parameterRelation(tPositional[i], sPositional[i])) {
return false;
}
}
- DartType sRetType = s.returnType;
- return sRetType.isVoid || relation(returnType, sRetType);
+ return true;
}
@override
« no previous file with comments | « no previous file | pkg/analyzer/lib/src/generated/type_system.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698