dart-lang / sdk

The Dart SDK, including the VM, JS and Wasm compilers, analysis, core libraries, and more.
https://dart.dev
BSD 3-Clause "New" or "Revised" License
10.23k stars 1.57k forks source link

Report type checks which always fail in analyzer #46170

Open alexmarkov opened 3 years ago

alexmarkov commented 3 years ago

For example:

double foo() => 1;

main() {
  print(foo() as int);
}

With null safety this code always throws an error and dartanalyzer can figure this out using static types and issue a hint or lint. Such type checks happened in practice in package:flutter_quill (fix: https://github.com/singerdmx/flutter-quill/pull/239/files).

srawlins commented 3 years ago

@alexmarkov what check are you looking for? Given:

class A {}
class B {}

...

B f(A a) => a as B;

There can be classes which extend both A and B.

Are you just thinking of the un-extendable classes (int, double, num, String, bool, Future, FutureOr, void, Never, or something like this)? Given the prevalence of int, double, String, etc, I think this could be useful.

alexmarkov commented 3 years ago

The real code was converting double to int via as int, so we can at least cover sealed built-in classes.

In general, we can conclude that the cast will always fail if we know all possible subtypes of static type of an operand (A) or all possible subtypes of a target type (B). That may happen for sealed built-in classes, library-private classes which don't have public subtypes or if we're analyzing the whole program and see all classes (but I'm not sure if analyzer can ever make closed-world assumptions). In certain cases it is also possible to infer actual runtime type of an operand from a generative constructor invocation / constant.

srawlins commented 3 years ago

Yeah, whole program will be a neat feature in the future. Analyzer does not do it today.

I think sealed built-in classes will be most useful. Private classes with no public subtypes is not as useful.