Skip to content

Commit 6547f74

Browse files
stereotype441commit-bot@chromium.org
authored andcommitted
Add language tests illustrating issue #42603.
Bug: #42603 Change-Id: I1d59b7b65d77e5f1accb4f9c3c99e92e48ffb364 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/153709 Commit-Queue: Paul Berry <[email protected]> Reviewed-by: Bob Nystrom <[email protected]>
1 parent 5867639 commit 6547f74

File tree

2 files changed

+134
-0
lines changed

2 files changed

+134
-0
lines changed
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
import "package:expect/expect.dart";
5+
6+
// SharedOptions=--enable-experiment=non-nullable
7+
8+
// Test that `super == x` is allowed when `x` has a nullable type, even if the
9+
// targeted definition of `operator==` has a parameter with a non-nullable type,
10+
// as per this spec text (from
11+
// accepted/future-releases/nnbd/feature-specification.md):
12+
//
13+
// Similarly, consider an expression `e` of the form `super == e2` that
14+
// occurs in a class whose superclass is `C`, where the static type of `e2`
15+
// is `T2`. Let `S` be the formal parameter type of the concrete declaration
16+
// of `operator ==` found by method lookup in `C` (_if that search succeeds,
17+
// otherwise it is a compile-time error_). It is a compile-time error
18+
// unless `T2` is assignable to `S?`.
19+
//
20+
// Also test that `super == null` evaluates to `false` without calling
21+
// `super.operator==`, as per this spec text (from section "Equality"):
22+
//
23+
// Evaluation of an equality expression ee of the form super == e proceeds
24+
// as follows:
25+
// - The expression e is evaluated to an object o.
26+
// - If either this or o is the null object (16.4), then ee evaluates to
27+
// evaluates to true if both this and o are the null object and to false
28+
// otherwise. Otherwise,
29+
// - evaluation of ee is equivalent to the method invocation super.==(o).
30+
31+
MapEntry<dynamic, dynamic>? _call = null;
32+
33+
class BaseObject {
34+
bool operator ==(Object other) {
35+
Expect.isNull(_call);
36+
_call = MapEntry(this, other);
37+
return false;
38+
}
39+
}
40+
41+
class DerivedObject extends BaseObject {
42+
void test() {
43+
Object? nullAsObjectQuestion = null;
44+
Object? nonNullAsObjectQuestion = 0;
45+
dynamic nullAsDynamic = null;
46+
dynamic nonNullAsDynamic = 1;
47+
Expect.isFalse(super == nullAsObjectQuestion);
48+
Expect.isNull(_call);
49+
Expect.isFalse(super == nonNullAsObjectQuestion);
50+
Expect.identical(_call!.key, this);
51+
Expect.identical(_call!.value, nonNullAsObjectQuestion);
52+
_call = null;
53+
Expect.isFalse(super == nullAsDynamic);
54+
Expect.isNull(_call);
55+
Expect.isFalse(super == nonNullAsDynamic);
56+
Expect.identical(_call!.key, this);
57+
Expect.identical(_call!.value, nonNullAsDynamic);
58+
_call = null;
59+
}
60+
}
61+
62+
class BaseNum {
63+
bool operator ==(covariant num other) {
64+
Expect.isNull(_call);
65+
_call = MapEntry(this, other);
66+
return false;
67+
}
68+
}
69+
70+
class DerivedNum extends BaseNum {
71+
void test() {
72+
num? nullAsNumQuestion = null;
73+
num? nonNullAsNumQuestion = 0;
74+
dynamic nullAsDynamic = null;
75+
dynamic nonNullAsDynamic = 1;
76+
dynamic nonNumAsDynamic = 'foo';
77+
Expect.isFalse(super == nullAsNumQuestion);
78+
Expect.isNull(_call);
79+
Expect.isFalse(super == nonNullAsNumQuestion);
80+
Expect.identical(_call!.key, this);
81+
Expect.identical(_call!.value, nonNullAsNumQuestion);
82+
_call = null;
83+
Expect.isFalse(super == nullAsDynamic);
84+
Expect.isNull(_call);
85+
Expect.isFalse(super == nonNullAsDynamic);
86+
Expect.identical(_call!.key, this);
87+
Expect.identical(_call!.value, nonNullAsDynamic);
88+
_call = null;
89+
Expect.throwsTypeError(() => super == nonNumAsDynamic);
90+
Expect.isNull(_call);
91+
}
92+
}
93+
94+
main() {
95+
DerivedObject().test();
96+
DerivedNum().test();
97+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
import "package:expect/expect.dart";
5+
6+
// SharedOptions=--enable-experiment=non-nullable
7+
8+
// Test that `super == x` is properly type checked against the target
9+
// `operator==` method. That is, the special allowance in the following spec
10+
// text (from accepted/future-releases/nnbd/feature-specification.md) allows `x`
11+
// to be nullable, but still requires that the type otherwise matches:
12+
//
13+
// Similarly, consider an expression `e` of the form `super == e2` that
14+
// occurs in a class whose superclass is `C`, where the static type of `e2`
15+
// is `T2`. Let `S` be the formal parameter type of the concrete declaration
16+
// of `operator ==` found by method lookup in `C` (_if that search succeeds,
17+
// otherwise it is a compile-time error_). It is a compile-time error
18+
// unless `T2` is assignable to `S?`.
19+
20+
class Base {
21+
bool operator ==(covariant num other) => false;
22+
}
23+
24+
class Derived extends Base {
25+
void test() {
26+
String string = 'foo';
27+
String? stringQuestion = 'foo';
28+
super == string;
29+
// ^^^^^^
30+
// [analyzer] STATIC_WARNING.ARGUMENT_TYPE_NOT_ASSIGNABLE
31+
// [cfe] The argument type 'String' can't be assigned to the parameter type 'num?'.
32+
super == stringQuestion;
33+
// ^^^^^^^^^^^^^^
34+
// [analyzer] STATIC_WARNING.ARGUMENT_TYPE_NOT_ASSIGNABLE
35+
// [cfe] The argument type 'String?' can't be assigned to the parameter type 'num?'.
36+
}
37+
}

0 commit comments

Comments
 (0)