-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Null safety promotion breaks when using local functions #45094
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
Comments
We are actively working on improving the diagnostics to make this easier to understand. Progress is being tracked on #44897. |
Closing as duplicate |
I may have misunderstood (I'm on triage duty, and triaging many issues). cc @lrhn can you comment? |
No worries, thanks for taking the time! |
It doesn't work because there is an assignment to the variable in a function somewhere. The analysis assumes that that function can be called at any time (because ruling it out is hard in general), and therefore it can't assume that the test result still applies at the later use. Getting a better error message is a good goal, which is what #44897 is about, so if that's the goal, then this issue is a duplicate. If you want the language to actually promote in this situation, then we can keep this issue open as a feature request, but I don't think it's something you should expect to happen. It's not a low hanging fruit for promotion enhancement, so even if we want to make some things better, this particular case is not going to high on the list. |
Thanks for explaining why it doesn't work in this case.
That's exactly what seems to happen now to the user, you simply use the variable in a local function and suddenly you code no longer compiles.
I agree that it should be predictable, perhaps simply only checking the previous statement would do then one could at least use a null check instead of always needing to do a null check and an So for instance: if (test != null) test += ''; Works but: if (test != null) {
otherStuff();
test += ''; // can be null
} does not work. But if you then do: if (test != null) {
otherStuff();
if (test != null) test += '';
} it can work again The benefit being here that one never needs to rewrite it to this: test = test! + ''; |
@Kavantix I'm having trouble following your example here with |
@mit-mit the example is my idea, not how it currently works. I was simply trying to pose a solution to be able to do a null check instead of having to resort to using a So in my example above the difference between the two with |
"No code between" is a very tricky thing to define. if (test != null) test += ''; but only if Also, it looks like if (test != null) someFunction(test); should work, but it only works if |
Closing as by-design. |
@lrhn I get your point so then this will just have to stay open as a feature request until somewhere in the future this promotion will be possible. |
We definitely want to make it easier to work with nullable fields. I'm not convinced that type promotion is the way to do it, we might need a separate feature, like check-and-bind. An either case, I'm closing this issue as a duplicate of the issues related to field promotion in the language repository. |
@lrhn This one is not about a field though it’s a local variable |
Right, this is a local variable, so some of my answer was unrelated. The issue is still that the variable might change value between check and use, which it's assumed to be able to because there is an assignment in a closure, and we don't analyze where that closure might go. These caveats still makes the promotion too unpredictable for users, very small changes can invalidate the promotion, and I don't think the effort needed to make it work for the cases that are actually safe is worth it. If anything, I'd rather work on detecting whether the closure containing the assignment can escape or not, and if not, then only invalidated the promotion when the function is actually called. I think that has a much higher chance of providing promotion in general, than trying to detect whether the use is "right after" the check. It's non-trivial, and not something we currently do. |
Makes sense, thanks for taking the time to explain it :) |
Example code that is incorrectly analyzed:
This is the same on all dart versions that support nnbd
I already read here that this might be by design but it is quite annoying and at least the error could be better (took me a while to figure out it was the local function that was breaking it).
The text was updated successfully, but these errors were encountered: