0
void main() {
  int? foo;
  var isNonNull = foo != null;
  
  if (isNonNull) foo.isEven; // Error
}

I already did a check on foo and stored its value in isNonNull variable. I could understand that warning if the scope wasn't local.

Note: I know I can use ! bang operator to resolve it but why flow analysis isn't working?

iDecode
  • 22,623
  • 19
  • 99
  • 186

2 Answers2

1

Dart type promotion is based on a check of a variable going a particular way dominating a later use of that variable.

So, if you do if (x != null) x.foo();, it detects that the check x != null being true means that the later x.foo() is valid. That only works because the compiler can also convince itself that the variable's value doesn't change between the check and the use.

If you introduce an extra boolean variable, like here, then the check is no longer performed inside the branch. That doesn't make it impossible to remember that the isNonNull boolean value being true means that foo is non-null, but it gets more complicated. The compiler now has to ensure that foo doesn't change and that isNotNull doesn't change. The Dart compiler bails out instead, it doesn't track that level of complication. It only tracks promotion through one variable at a time.

lrn
  • 64,680
  • 7
  • 105
  • 121
  • Sir, do you think the bool should work if it was declared `final` instead of `var` in my code i.e. `final isNonNull = foo != null;` because then the compiler can trust the `bool` value not getting assigned again. – iDecode May 31 '21 at 09:51
  • 1
    It's still depending on information one-more-level-of-indirection away from the actual branch. It means the compiler must deduce every consequence of every test in case it might get stored in a variable that might reach branch. Currently, it only has to consider tests that actually occur *in* a branch expression. It's definitely possible to do more, but it's also dangerous if the edges around what can be inferred and what cannot are too fractal for users to predict. Simplicity has the advantage that you can actually explain it. – lrn May 31 '21 at 10:26
  • I don't know which Dart version fixed it but now there are no more issues in the code I asked. – iDecode Jan 11 '22 at 07:20
0

You get the error because flow analysis can't know if isNonNull is ever going to get a new value. Take this example:

final random = Random();
void main() {
  int? foo;
  var isNonNull = foo != null;
  isNonNull = random.nextBool();
  if (isNonNull) foo.isEven;
}

So, its better to use

if (foo != null) foo.isEven;
iDecode
  • 22,623
  • 19
  • 99
  • 186