dart-lang / dart-lang/language

Typed equality operator

Open
#4,176 6 comments 0 reactions 0 assignees View on GitHub
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

Open the contributing 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.