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 9639b3d3c5130421451f63e249b5ab7965e71588..fd08d0c93ef5969a6fdb59340171091af6002818 100644 |
--- a/sdk/lib/_internal/compiler/implementation/dart_types.dart |
+++ b/sdk/lib/_internal/compiler/implementation/dart_types.dart |
@@ -999,6 +999,10 @@ class SubtypeVisitor extends DartTypeVisitor<bool, DartType> { |
if (s is !FunctionType) return false; |
FunctionType tf = t; |
FunctionType sf = s; |
+ if (!identical(sf.returnType, voidType) && |
+ !isAssignable(tf.returnType, sf.returnType)) { |
+ return false; |
+ } |
Link<DartType> tps = tf.parameterTypes; |
Link<DartType> sps = sf.parameterTypes; |
while (!tps.isEmpty && !sps.isEmpty) { |
@@ -1006,12 +1010,17 @@ class SubtypeVisitor extends DartTypeVisitor<bool, DartType> { |
tps = tps.tail; |
sps = sps.tail; |
} |
- if (!tps.isEmpty || !sps.isEmpty) return false; |
- if (!identical(sf.returnType, voidType) && |
- !isAssignable(tf.returnType, sf.returnType)) { |
+ if (!tps.isEmpty) { |
+ // We must have |
+ // t.parameterTypes.length <= s.parameterTypes.length |
return false; |
} |
if (!sf.namedParameters.isEmpty) { |
+ if (!sps.isEmpty) { |
+ // We must have |
+ // t.parameterTypes.length == s.parameterTypes.length |
karlklose
2013/04/24 11:59:20
Perhaps you could define abbreviations for t/s.par
Johnni Winther
2013/04/25 07:54:12
Done.
|
+ return false; |
+ } |
// Since named parameters are globally ordered we can determine the |
// subset relation with a linear search for [:sf.NamedParameters:] |
// within [:tf.NamedParameters:]. |
@@ -1033,23 +1042,44 @@ class SubtypeVisitor extends DartTypeVisitor<bool, DartType> { |
// We didn't find all names. |
return false; |
} |
- } |
- if (!sf.optionalParameterTypes.isEmpty) { |
- Link<DartType> tOptionalParameterType = tf.optionalParameterTypes; |
- Link<DartType> sOptionalParameterType = sf.optionalParameterTypes; |
- while (!tOptionalParameterType.isEmpty && |
- !sOptionalParameterType.isEmpty) { |
- if (!isAssignable(tOptionalParameterType.head, |
- sOptionalParameterType.head)) { |
- return false; |
- } |
- sOptionalParameterType = sOptionalParameterType.tail; |
- tOptionalParameterType = tOptionalParameterType.tail; |
+ } else { |
+ // Check the remaining required parameters of [s] against the optional |
+ // parameters of [t]. |
+ tps = tf.optionalParameterTypes; |
+ while (!tps.isEmpty && !sps.isEmpty) { |
+ if (!isAssignable(tps.head, sps.head)) return false; |
+ tps = tps.tail; |
+ sps = sps.tail; |
} |
- if (!sOptionalParameterType.isEmpty) { |
- // We didn't find enough optional parameters. |
+ if (!sps.isEmpty) { |
karlklose
2013/04/24 11:59:20
It would be nicer to check the number of arguments
Johnni Winther
2013/04/25 07:54:12
Added a TODO for a more readable implementation.
|
+ // We must have |
+ // t.parameterTypes.length + t.optionalParameterTypes.length |
+ // >= s.parameterTypes.length |
return false; |
} |
+ if (!sf.optionalParameterTypes.isEmpty) { |
+ // Check the remaining optional parameters of [s] against the remaining |
+ // optional parameters of [t]. |
+ sps = sf.optionalParameterTypes; |
+ while (!tps.isEmpty && !sps.isEmpty) { |
+ if (!isAssignable(tps.head, sps.head)) return false; |
+ tps = tps.tail; |
+ sps = sps.tail; |
+ } |
+ if (!sps.isEmpty) { |
+ // We didn't find enough parameters: |
+ // We must have |
+ // t.parameterTypes.length + t.optionalParameterTypes.length |
+ // <= s.parameterTypes.length + s.optionalParameterTypes.length |
+ return false; |
+ } |
+ } else { |
+ if (!sps.isEmpty) { |
+ // We must have |
+ // t.parameterTypes.length == s.parameterTypes.length |
+ return false; |
+ } |
+ } |
} |
return true; |
} |