| Index: pkg/compiler/lib/src/js_backend/no_such_method_registry.dart
|
| diff --git a/pkg/compiler/lib/src/js_backend/no_such_method_registry.dart b/pkg/compiler/lib/src/js_backend/no_such_method_registry.dart
|
| index ee09ed328ee1b416092a94c24990a7be30c1fd78..4db23870b62dd0576e5632d4f99e47aa2e807cf8 100644
|
| --- a/pkg/compiler/lib/src/js_backend/no_such_method_registry.dart
|
| +++ b/pkg/compiler/lib/src/js_backend/no_such_method_registry.dart
|
| @@ -14,7 +14,7 @@ part of js_backend;
|
| *
|
| * The situation can be ameliorated with some heuristics for disregarding some
|
| * `noSuchMethod` implementations during type inference. We can partition
|
| - * `noSuchMethod` implementations into 3 categories.
|
| + * `noSuchMethod` implementations into 4 categories.
|
| *
|
| * Implementations in category A are the default implementations
|
| * `Object.noSuchMethod` and `Interceptor.noSuchMethod`.
|
| @@ -23,8 +23,13 @@ part of js_backend;
|
| *
|
| * noSuchMethod(x) => throw 'not implemented'
|
| *
|
| - * Implementations that do not fall into category A or B are in category C. They
|
| - * are the only category of implementation that are considered during type
|
| + * Implementations in category C are not applicable, for example:
|
| + *
|
| + * noSuchMethod() { /* missing parameter */ }
|
| + * noSuchMethod(a, b) { /* too many parameters */ }
|
| + *
|
| + * Implementations that do not fall into category A, B or C are in category D.
|
| + * They are the only category of implementation that are considered during type
|
| * inference.
|
| *
|
| * Implementations that syntactically just forward to the super implementation,
|
| @@ -42,11 +47,13 @@ class NoSuchMethodRegistry {
|
| /// The implementations that fall into category B, described above.
|
| final Set<FunctionElement> throwingImpls = new Set<FunctionElement>();
|
| /// The implementations that fall into category C, described above.
|
| + final Set<FunctionElement> notApplicableImpls = new Set<FunctionElement>();
|
| + /// The implementations that fall into category D, described above.
|
| final Set<FunctionElement> otherImpls = new Set<FunctionElement>();
|
|
|
| - /// The implementations that fall into category C1
|
| + /// The implementations that fall into category D1
|
| final Set<FunctionElement> complexNoReturnImpls = new Set<FunctionElement>();
|
| - /// The implementations that fall into category C2
|
| + /// The implementations that fall into category D2
|
| final Set<FunctionElement> complexReturningImpls = new Set<FunctionElement>();
|
|
|
| /// The implementations that have not yet been categorized.
|
| @@ -73,8 +80,8 @@ class NoSuchMethodRegistry {
|
| _uncategorizedImpls.clear();
|
| }
|
|
|
| - /// Now that type inference is complete, split category C into two
|
| - /// subcategories: C1, those that have no return type, and C2, those
|
| + /// Now that type inference is complete, split category D into two
|
| + /// subcategories: D1, those that have no return type, and D2, those
|
| /// that have a return type.
|
| void onTypeInferenceComplete() {
|
| otherImpls.forEach(_subcategorizeOther);
|
| @@ -104,7 +111,7 @@ class NoSuchMethodRegistry {
|
|
|
| /// Returns [true] if the given element is a complex [noSuchMethod]
|
| /// implementation. An implementation is complex if it falls into
|
| - /// category C, as described above.
|
| + /// category D, as described above.
|
| bool isComplex(FunctionElement element) {
|
| assert(element.name == Identifiers.noSuchMethod_);
|
| return otherImpls.contains(element);
|
| @@ -131,9 +138,12 @@ class NoSuchMethodRegistry {
|
| if (otherImpls.contains(element)) {
|
| return NsmCategory.OTHER;
|
| }
|
| + if (notApplicableImpls.contains(element)) {
|
| + return NsmCategory.NOT_APPLICABLE;
|
| + }
|
| if (!Selectors.noSuchMethod_.signatureApplies(element)) {
|
| - otherImpls.add(element);
|
| - return NsmCategory.OTHER;
|
| + notApplicableImpls.add(element);
|
| + return NsmCategory.NOT_APPLICABLE;
|
| }
|
| if (_isDefaultNoSuchMethodImplementation(element)) {
|
| defaultImpls.add(element);
|
| @@ -141,8 +151,8 @@ class NoSuchMethodRegistry {
|
| } else if (_hasForwardingSyntax(element)) {
|
| // If the implementation is 'noSuchMethod(x) => super.noSuchMethod(x);'
|
| // then it is in the same category as the super call.
|
| - Element superCall = element.enclosingClass
|
| - .lookupSuperByName(Selectors.noSuchMethod_.memberName);
|
| + Element superCall =
|
| + element.enclosingClass.lookupSuperByName(Names.noSuchMethod_);
|
| NsmCategory category = _categorizeImpl(superCall);
|
| switch(category) {
|
| case NsmCategory.DEFAULT:
|
| @@ -154,6 +164,12 @@ class NoSuchMethodRegistry {
|
| case NsmCategory.OTHER:
|
| otherImpls.add(element);
|
| break;
|
| + case NsmCategory.NOT_APPLICABLE:
|
| + // If the super method is not applicable, the call is redirected to
|
| + // `Object.noSuchMethod`.
|
| + defaultImpls.add(element);
|
| + category = NsmCategory.DEFAULT;
|
| + break;
|
| }
|
| return category;
|
| } else if (_hasThrowingSyntax(element)) {
|
| @@ -224,4 +240,9 @@ class NoSuchMethodRegistry {
|
| }
|
| }
|
|
|
| -enum NsmCategory { DEFAULT, THROWING, OTHER }
|
| +enum NsmCategory {
|
| + DEFAULT,
|
| + THROWING,
|
| + NOT_APPLICABLE,
|
| + OTHER,
|
| +}
|
|
|