-
Notifications
You must be signed in to change notification settings - Fork 207
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
Local variable is not promoted when checked that its value is a non-null literal #1726
Comments
There was a commet somewhere else that explained it better, but I believe this is intended, and only explicit checks for I think it's simple to say that checking against other nullable expressions shouldn't be enough to promote, but a non-null literal may be possible. |
Cool! Note that #1224 has a similar topic, and the topic flow-analysis in general is related. I'll add the label 'flow-analysis' and remove the label 'bug' because the discussion is concerned with a language enhancement. We can strengthen the rule proposed here a bit, though: It seems to be a sound rule that When In other words, there's no way we can write a twisted implementation of |
There is no end to the expressions we could potentially allow to promote. The following ones are ones we haven't chosen to promote on: x is Null // if true, x is null
identical(x, nonNullableValue) // if true, x is not null
identical(x, null) // if true, x is null
x == nonNullableValue // if true, x is not null
x?.foo == nonNullableValue // if true, x is not null
(x ?? nullableValue) == null // if true, x is null We have to draw a line at some point, at we drew it early. |
Note, though, that x?.foo == nonNullableValue is in the title of #1224. So we may have drawn that line early, but it's still under consideration to move it. |
I agree with @eernstg here, that x == nonNullableValue and x?.foo == nonNullableValue are both used often enough that it would be nice if they're supported, but the rest don't have to be. I don't see |
I'm not sure I get this I have had this problem with direct null checks many times such as:
This also gives me an error, shouldn't it be getting promoted? |
That's a slightly different issue because fields work differently than local variables. When you access a field, you're really calling a getter, and that getter is essentially a function, which can return any value. More importantly, it can return different values each time it's called. So just because /// This is probably what you have.
class MyWidget extends StatefulWidget {
final VoidCallback? onChanged;
MyWidget(this.onChanged);
}
/// But this is valid as well
class MyTrickyWidget extends StatefulWidget {
VoidCallback? get onChanged => Random.nextBool() ? () { print("Hello"); } : null;
} Because of this difference, Dart can't promote fields. There is some syntax being proposed to get around it, like #1514 and #1201, but they all boil down to shortcuts for the following: void onChanged() {
// Because callback is local, it can't be overriden with a getter, so it's value won't change between checks
final VoidCallback? callback = widget.onChanged;
if (callback != null) {
callback(query); // promoted
}
} } |
@Levi-Lesches I see, thank you very much for the detailed explanation! I won't spam this thread with a different issue. |
Also just want to promote null-aware invocation of the |
Consider the following code:
The code above won't compile, even if it is (seemingly) clear that, if
fruit
isFruit.apple
it won't possibly benull
. The same happens if using aswitch-case
. The following won't compile:Obviously, if I explicitly check for null (
if (fruit != null && fruit == Fruit.apple)
) it will be properly promoted.Is this the intended behavior? If yes, why? Maybe I am missing something and there's some technical reason to why the compiler can't be sure that the value is not null in these cases?
The text was updated successfully, but these errors were encountered: