dart-lang / dart-lang/language
Typed equality operator
- Dominant language
- TeX
- Stars
- 2.9k
- Forks
- 239
- Avg merge
- 2d 18h
- Merged PRs (30d)
- 14
Description
There has been a long-standing tension in Dart between the desire to have `operator==` be typed tightly to take the type of the receiver, and to have it typed loosely to avoid runtime errors when calling `operator==` on a receiver whose static type is more general than the runtime type. Examples:
```dart
class A {
int x;
A(this.x);
bool operator ==(Object other) {
if (other is! A) return false;
return x == other.x;
}
}
class B {
int x;
B(this.x);
bool operator ==(covariant B other) {
return x == other.x;
}
}
void main() {
Object a = A(3);
Object b = B(3);
assert(a == a);
assert(a != b);
assert(b == b);
try {
assert(b == a);
} on TypeError {
print("Oopsie");
}
}
```
The above program, when run with asserts enabled, prints "Oopsie". Making the type of the argument to `operator==` on `B` be covariant gives nice static typing behavior, but interacts poorly with subsumption.
The current solution to this is to use the "unrelated_type_equality_checks" lint which is included in the core set of lints recommended by the Dart team.
Recently, @eernstg suggested adding a typed variant of equality: `e1 == e2` which gives a static error if either `e1` or `e2` are not a subtype of `T`, and then treating the standard `e1 == e2` syntax as syntactic sugar for `e1 = e2`. It occurred to me that we could essentially get the same functionality using an extension method if we added a new equality operator. That is, if we added something like `===` (to pick a random example), then we could also add to the core libraries the following extension:
```dart
extension TypedEquals on T {
bool operator===(T x) => this == x;
}
```
Statically, this enforces that the argument has a type which is a subtype of the type of the receiver, without changing anything about the runtime behavior (essentially encoding the above mentioned lint into the type system). Unlike the lint above, this is an actual static type, and so it can interact with inference and other language mechanisms (e.g. https://github.com/dart-lang/language/issues/4149).
@dart-lang/language-team thoughts?
Contributor guide
Research direction
Start with the examples in this issue and read the linked issue 4149, then review the existing `==` behavior and the `unrelated_type_equality_checks` lint. Done is not defined: the proposal needs an agreed design for a typed equality operator and its interaction with existing equality.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- dart
- Domain
- compilers
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 25/100