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 8857a95b809e9f48ff25173440325c3aa20db440..9d09ba4f591edbf3415b823eeae4477f1c45a9cf 100644 |
--- a/pkg/analyzer/lib/src/dart/element/type.dart |
+++ b/pkg/analyzer/lib/src/dart/element/type.dart |
@@ -718,7 +718,7 @@ class FunctionTypeImpl extends TypeImpl implements FunctionType { |
// variables, and see if the result is equal. |
if (typeFormals.isNotEmpty) { |
List<DartType> freshVariables = |
- relateTypeFormals(this, object, (t, s) => t == s); |
+ relateTypeFormals(this, object, (t, s, _, __) => t == s); |
if (freshVariables == null) { |
return false; |
} |
@@ -895,7 +895,7 @@ class FunctionTypeImpl extends TypeImpl implements FunctionType { |
return relate( |
this, |
type, |
- (DartType t, DartType s, _, __) => |
+ (DartType t, DartType s) => |
(t as TypeImpl).isMoreSpecificThan(s, withDynamic), |
new TypeSystemImpl(null).instantiateToBounds); |
} |
@@ -906,7 +906,7 @@ class FunctionTypeImpl extends TypeImpl implements FunctionType { |
return relate( |
typeSystem.instantiateToBounds(this), |
typeSystem.instantiateToBounds(type), |
- (DartType t, DartType s, _, __) => t.isAssignableTo(s), |
+ (DartType t, DartType s) => t.isAssignableTo(s), |
typeSystem.instantiateToBounds); |
} |
@@ -1076,16 +1076,16 @@ class FunctionTypeImpl extends TypeImpl implements FunctionType { |
* structural rules for handling optional parameters and arity, but use their |
* own relation for comparing corresponding parameters or return types. |
* |
- * If [returnRelation] is omitted, uses [parameterRelation] for both. |
+ * If [parameterRelation] is omitted, uses [returnRelation] for both. This |
+ * is convenient for Dart 1 type system methods. |
*/ |
static bool relate( |
FunctionType t, |
DartType other, |
- bool parameterRelation( |
- DartType t, DartType s, bool tIsCovariant, bool sIsCovariant), |
+ bool returnRelation(DartType t, DartType s), |
DartType instantiateToBounds(DartType t), |
- {bool returnRelation(DartType t, DartType s)}) { |
- returnRelation ??= (t, s) => parameterRelation(t, s, false, false); |
+ {bool parameterRelation(ParameterElement t, ParameterElement s)}) { |
+ parameterRelation ??= (t, s) => returnRelation(t.type, s.type); |
// Trivial base cases. |
if (other == null) { |
@@ -1102,7 +1102,8 @@ class FunctionTypeImpl extends TypeImpl implements FunctionType { |
// This type cast is safe, because we checked it above. |
FunctionType s = other as FunctionType; |
if (t.typeFormals.isNotEmpty) { |
- List<DartType> freshVariables = relateTypeFormals(t, s, returnRelation); |
+ List<DartType> freshVariables = |
+ relateTypeFormals(t, s, (s, t, _, __) => returnRelation(s, t)); |
if (freshVariables == null) { |
return false; |
} |
@@ -1119,14 +1120,34 @@ class FunctionTypeImpl extends TypeImpl implements FunctionType { |
} |
// Test the parameter types. |
+ return relateParameters(t.parameters, s.parameters, parameterRelation); |
+ } |
+ /** |
+ * Compares parameters [tParams] and [sParams] of two function types, taking |
+ * corresponding parameters from the lists, and see if they match |
+ * [parameterRelation]. |
+ * |
+ * Corresponding parameters are defined as a pair `(t, s)` where `t` is a |
+ * parameter from [tParams] and `s` is a parameter from [sParams], and both |
+ * `t` and `s` are at the same position (for positional parameters) |
+ * or have the same name (for named parameters). |
+ * |
+ * 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 the parameters. |
+ */ |
+ static bool relateParameters( |
+ List<ParameterElement> tParams, |
+ List<ParameterElement> sParams, |
+ bool parameterRelation(ParameterElement t, ParameterElement s)) { |
// TODO(jmesserly): this could be implemented with less allocation if we |
// wanted, by taking advantage of the fact that positional arguments must |
// appear before named ones. |
var tRequired = <ParameterElement>[]; |
var tOptional = <ParameterElement>[]; |
var tNamed = <String, ParameterElement>{}; |
- for (var p in t.parameters) { |
+ for (var p in tParams) { |
var kind = p.parameterKind; |
if (kind == ParameterKind.REQUIRED) { |
tRequired.add(p); |
@@ -1141,7 +1162,7 @@ class FunctionTypeImpl extends TypeImpl implements FunctionType { |
var sRequired = <ParameterElement>[]; |
var sOptional = <ParameterElement>[]; |
var sNamed = <String, ParameterElement>{}; |
- for (var p in s.parameters) { |
+ for (var p in sParams) { |
var kind = p.parameterKind; |
if (kind == ParameterKind.REQUIRED) { |
sRequired.add(p); |
@@ -1174,8 +1195,7 @@ class FunctionTypeImpl extends TypeImpl implements FunctionType { |
return false; |
} |
var sParam = sNamed[key]; |
- if (!parameterRelation( |
- tParam.type, sParam.type, tParam.isCovariant, sParam.isCovariant)) { |
+ if (!parameterRelation(tParam, sParam)) { |
return false; |
} |
} |
@@ -1204,10 +1224,7 @@ class FunctionTypeImpl extends TypeImpl implements FunctionType { |
} |
for (int i = 0; i < sPositional.length; i++) { |
- var tParam = tPositional[i]; |
- var sParam = sPositional[i]; |
- if (!parameterRelation( |
- tParam.type, sParam.type, tParam.isCovariant, sParam.isCovariant)) { |
+ if (!parameterRelation(tPositional[i], sPositional[i])) { |
return false; |
} |
} |
@@ -1227,7 +1244,10 @@ class FunctionTypeImpl extends TypeImpl implements FunctionType { |
* `F` to get `F -> F` and `F -> F`, which we can see are equal. |
*/ |
static List<DartType> relateTypeFormals( |
- FunctionType f1, FunctionType f2, bool relation(DartType t, DartType s)) { |
+ FunctionType f1, |
+ FunctionType f2, |
+ bool relation(DartType bound2, DartType bound1, |
+ TypeParameterElement formal2, TypeParameterElement formal1)) { |
List<TypeParameterElement> params1 = f1.typeFormals; |
List<TypeParameterElement> params2 = f2.typeFormals; |
int count = params1.length; |
@@ -1258,7 +1278,7 @@ class FunctionTypeImpl extends TypeImpl implements FunctionType { |
bound1 = bound1.substitute2(variablesFresh, variables1); |
bound2 = bound2.substitute2(variablesFresh, variables2); |
pFresh.bound = bound2; |
- if (!relation(bound2, bound1)) { |
+ if (!relation(bound2, bound1, p2, p1)) { |
return null; |
} |
} |