| // Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file |
| // for details. All rights reserved. Use of this source code is governed by a |
| // BSD-style license that can be found in the LICENSE file. |
| import "package:expect/expect.dart"; |
| |
| |
| // Test that `super == x` is allowed when `x` has a nullable type, even if the |
| // targeted definition of `operator==` has a parameter with a non-nullable type, |
| // as per this spec text (from |
| // accepted/future-releases/nnbd/feature-specification.md): |
| // |
| // Similarly, consider an expression `e` of the form `super == e2` that |
| // occurs in a class whose superclass is `C`, where the static type of `e2` |
| // is `T2`. Let `S` be the formal parameter type of the concrete declaration |
| // of `operator ==` found by method lookup in `C` (_if that search succeeds, |
| // otherwise it is a compile-time error_). It is a compile-time error |
| // unless `T2` is assignable to `S?`. |
| // |
| // Also test that `super == null` evaluates to `false` without calling |
| // `super.operator==`, as per this spec text (from section "Equality"): |
| // |
| // Evaluation of an equality expression ee of the form super == e proceeds |
| // as follows: |
| // - The expression e is evaluated to an object o. |
| // - If either this or o is the null object (16.4), then ee evaluates to |
| // evaluates to true if both this and o are the null object and to false |
| // otherwise. Otherwise, |
| // - evaluation of ee is equivalent to the method invocation super.==(o). |
| |
| MapEntry<dynamic, dynamic>? _call = null; |
| |
| class BaseObject { |
| bool operator ==(Object other) { |
| Expect.isNull(_call); |
| _call = MapEntry(this, other); |
| return false; |
| } |
| } |
| |
| class DerivedObject extends BaseObject { |
| void test() { |
| Object? nullAsObjectQuestion = null; |
| Object? nonNullAsObjectQuestion = 0; |
| dynamic nullAsDynamic = null; |
| dynamic nonNullAsDynamic = 1; |
| Expect.isFalse(super == nullAsObjectQuestion); |
| Expect.isNull(_call); |
| Expect.isFalse(super == nonNullAsObjectQuestion); |
| Expect.identical(_call!.key, this); |
| Expect.identical(_call!.value, nonNullAsObjectQuestion); |
| _call = null; |
| Expect.isFalse(super == nullAsDynamic); |
| Expect.isNull(_call); |
| Expect.isFalse(super == nonNullAsDynamic); |
| Expect.identical(_call!.key, this); |
| Expect.identical(_call!.value, nonNullAsDynamic); |
| _call = null; |
| } |
| } |
| |
| class BaseNum { |
| bool operator ==(covariant num other) { |
| Expect.isNull(_call); |
| _call = MapEntry(this, other); |
| return false; |
| } |
| } |
| |
| class DerivedNum extends BaseNum { |
| void test() { |
| num? nullAsNumQuestion = null; |
| num? nonNullAsNumQuestion = 0; |
| dynamic nullAsDynamic = null; |
| dynamic nonNullAsDynamic = 1; |
| dynamic nonNumAsDynamic = 'foo'; |
| Expect.isFalse(super == nullAsNumQuestion); |
| Expect.isNull(_call); |
| Expect.isFalse(super == nonNullAsNumQuestion); |
| Expect.identical(_call!.key, this); |
| Expect.identical(_call!.value, nonNullAsNumQuestion); |
| _call = null; |
| Expect.isFalse(super == nullAsDynamic); |
| Expect.isNull(_call); |
| Expect.isFalse(super == nonNullAsDynamic); |
| Expect.identical(_call!.key, this); |
| Expect.identical(_call!.value, nonNullAsDynamic); |
| _call = null; |
| Expect.throwsTypeError(() => super == nonNumAsDynamic); |
| Expect.isNull(_call); |
| } |
| } |
| |
| main() { |
| DerivedObject().test(); |
| DerivedNum().test(); |
| } |