4

I've recently came across this question How do I solve the 'Failed assertion: boolean expression must not be null' exception in Flutter

where the problem comes from a should be invalid code that gets treated as valid.

This code can be summarized as :

int stuff;
if (stuff = null) { // = instead of ==
}

But why does this code compiles ? As the following will not.

int stuff;
if (stuff = 42) {
}

With the following compile error :

Conditions must have a static type of 'bool'.

So I'd expect out of consistency that if (stuff = null) to gives the same error.

Rémi Rousselet
  • 256,336
  • 79
  • 519
  • 432

3 Answers3

6

null is a valid value for a bool variable in Dart, at least until Dart supports non-nullable types.

bool foo = null;

or just

bool foo;

is valid.

Therefore in the first case there is nothing wrong from a statical analysis point of view.

In the 2nd case the type int is inferred because of the assignment, which is known to not be a valid boolean value.

bool foo = 42; 

is invalid.

Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567
  • but `stuff` isn't a `bool`. And `if (stuff)`doesn't work. So I see no reason `if (stuff = null)` should work too. I can understand technically _why_. But it feels more like a bug than a feature. – Rémi Rousselet Jun 27 '18 at 08:51
  • same goes for `bool myVar = stuff = null`. If `stuff` isn't a bool, that shouldn't be possible. – Rémi Rousselet Jun 27 '18 at 08:54
  • Yeah, these are more interesting questions. I guess we better wait for @lrhn to get a proper answer ;-) – Günter Zöchbauer Jun 27 '18 at 08:58
  • 1
    For the record, the current answer is proper. The value and type of `stuff = null` is `null` at type `Null`. You are not assigning `stuff` to anything. You are assigning `null` to two different things, and whether you write `foo = bar = null` or `bar = foo = null` only changes the order of assignment, not what value is assigned (it's `null` in both cases). – lrn Aug 22 '19 at 08:51
2

When you say var stuff; with no initial value it is giving stuff a static type of dynamic. Since dyamic might be a bool, it's legal to assign null to a variable of type dynamic, and it's legal to use a possibly null bool in a conditional, the compiler doesn't flag this. When you say int stuff; the compiler knows that stuff could not be a bool. The reported error in that case is cause by the static type of stuff, not the assignment to null.

Edit: Got the real answer from someone who knows how to read the spec.

The static type of an assignment expression is the right hand side of the assignment. So the expression stuff = null has the static type of Null which is assignable to bool.

The reasoning is that the value of an assignment is the right hand side, so it makes sense to also use it's type. This allows expressions like:

int foo;
num bar;
foo = bar = 1;
Nate Bosch
  • 10,145
  • 2
  • 26
  • 22
  • `var` changes nothing here. I could have used `int` or `Map` or whatever. I edited my code snippet to make it clearer – Rémi Rousselet Jun 27 '18 at 09:20
  • Here's an example of the issue in dartpad: https://dartpad.dartlang.org/f1b096609d831bd03d88fe4f1b7ce19b – Rémi Rousselet Jun 27 '18 at 09:36
  • 1
    You're totally right, I had the wrong understanding of the cause. I also filed https://github.com/dart-lang/linter/issues/1047 to see if we can add a lint for this. – Nate Bosch Jun 27 '18 at 17:12
0

Commonly assignment operation returns the value that it assigns.

int a = 0;
  print(a = 3);//Prints 3

So,

When stuff = null,

'stuff = null' returns null. if statement needs a boolean .null is a sub-Type of boolean.

if(null){}

is valid

When stuff = 42,

'stuff = 42' returns 42. if statement needs a boolean .42 is not a sub-Type of boolean.

if(42){}

is not valid

Dummy
  • 47
  • 3