Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

proposal: operator_is_tests_a_type #4917

Open
4 of 5 tasks
eernstg opened this issue Mar 22, 2024 · 0 comments
Open
4 of 5 tasks

proposal: operator_is_tests_a_type #4917

eernstg opened this issue Mar 22, 2024 · 0 comments
Labels
lint-proposal status-pending type-enhancement A request for a change that isn't a bug

Comments

@eernstg
Copy link
Member

eernstg commented Mar 22, 2024

operator_is_tests_a_type

The operator is has a left operand whose static type is Type.

Description

Warn when an expression of the form t is T is encountered where the static type of t is Type.

Details

Emit a warning when an expression of the form t is T is encountered where the static type of t is Type.

The is operator will decide whether the left operand is an object whose run-time type is a subtype of the right operand, and it is essentially always wrong to pass a type literal as the left hand operand, or indeed any expression of type Type.

It seems likely that such an expression was intended to test whether the left operand as a type is a subtype of the right operand. Many terms denoting a type will also be accepted as the left operand of is because they are expressions as well as types, syntactically. This means that the construct is very likely to be wrong, but developers will not get any compile-time errors or warnings about these expressions, except for this lint.

There is no Dart operator (or any other mechanism) that directly tests the run-time subtype relationship between two terms derived from <type>, but the subtype query is a query which can be expressed indirectly (e.g., <S>[] is List<T> will evaluate to true if and only if S is a subtype of T).

Kind

This lint guards against errors by flagging expressions whose semantics is almost certainly very different from the author's intentions.

Bad Examples

void f<X>(X x) {
  // Wrong: `X is int` is simply another way to write `false`.
  if (X is int) { ... }
}

Good Examples

void g<X>(X x) {
  // Right: `is` expects an object on the left, not a type.
  if (x is int) x.isEven;
}

Discussion

It is actually possible to create a situation where t is T may be a useful query even though t is or could be a type, but it is expected to be quite rare. In this case, T would probably always be Type, because t is Object is rather useless (t != null is the preferred way to test the same thing), and t is U where U is a top type is just another way to write true, and any other value for T would just yield false whenever t is indeed a type.

It is reasonable to expect that such rare cases can be marked using // ignore: operator_is_tests_a_type.

Discussion checklist

  • List any existing rules this proposal modifies, complements, overlaps or conflicts with. I could not find any such rules.
  • List any relevant issues (reported here, the [SDK Tracker], or elsewhere). It does come up, e.g.: Generic Type Inheritance Checking sdk#43390, registerHandler not working with ValueNotifier escamoteur/watch_it#28.
  • _If there's any prior art (e.g., in other linters), please add references here.
  • If this proposal corresponds to [Effective Dart] or [Flutter Style Guide] advice, please call it out. As far as I can see, the style guides do not currently cover this topic.
  • If this proposal is motivated by real-world examples, please provide as many details as you can.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
lint-proposal status-pending type-enhancement A request for a change that isn't a bug
Projects
None yet
Development

No branches or pull requests

2 participants