| 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..8a2cab29efcfe5a6d64d742572c7e4bdb6d86997 100644
|
| --- a/sdk/lib/_internal/compiler/implementation/dart_types.dart
|
| +++ b/sdk/lib/_internal/compiler/implementation/dart_types.dart
|
| @@ -999,6 +999,19 @@ 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;
|
| + }
|
| +
|
| + // TODO(johnniwinther): Rewrite the function subtyping to be more readable
|
| + // but still as efficient.
|
| +
|
| + // For the comments we use the following abbreviations:
|
| + // x.p : parameterTypes on [:x:],
|
| + // x.o : optionalParameterTypes on [:x:], and
|
| + // len(xs) : length of list [:xs:].
|
| +
|
| Link<DartType> tps = tf.parameterTypes;
|
| Link<DartType> sps = sf.parameterTypes;
|
| while (!tps.isEmpty && !sps.isEmpty) {
|
| @@ -1006,15 +1019,18 @@ 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 [: len(t.p) <= len(s.p) :].
|
| return false;
|
| }
|
| if (!sf.namedParameters.isEmpty) {
|
| + if (!sps.isEmpty) {
|
| + // We must have [: len(t.p) == len(s.p) :].
|
| + return false;
|
| + }
|
| // Since named parameters are globally ordered we can determine the
|
| - // subset relation with a linear search for [:sf.NamedParameters:]
|
| - // within [:tf.NamedParameters:].
|
| + // subset relation with a linear search for [:sf.namedParameters:]
|
| + // within [:tf.namedParameters:].
|
| Link<SourceString> tNames = tf.namedParameters;
|
| Link<DartType> tTypes = tf.namedParameterTypes;
|
| Link<SourceString> sNames = sf.namedParameters;
|
| @@ -1033,23 +1049,37 @@ 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 [: s.p :] against [: t.o :].
|
| + 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) {
|
| + // We must have [: len(t.p) + len(t.o) >= len(s.p) :].
|
| return false;
|
| }
|
| + if (!sf.optionalParameterTypes.isEmpty) {
|
| + // Check the remaining [: s.o :] against the remaining [: t.o :].
|
| + 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 [: len(t.p) + len(t.o) <= len(s.p) + len(s.o) :].
|
| + return false;
|
| + }
|
| + } else {
|
| + if (!sps.isEmpty) {
|
| + // We must have [: len(t.p) + len(t.o) >= len(s.p) :].
|
| + return false;
|
| + }
|
| + }
|
| }
|
| return true;
|
| }
|
|
|