-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Promotion not always getting into a local function #50573
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
I hope we can. I'll defer to @stereotype441 about whether we actually can. It should be "obvious" that a function cannot be called before its declaration. It can be called at any later time. (We do not try to determine whether the function can escape. If it does, "any later time" must mean until the end of the program, not just until the end of the declaring function. And since we don't know, we have to assume the worst case.) The bigger problem is guaranteeing that every code path from that declaration to the end of the program will never assign a value to variables that the function refers to, which do not have the type they were promoted to. But what defines demotion? Does that mean that (If any closure contains an assignment to Since the second example works, my guess is that we are already doing something, but it takes very little to throw us off course. Possibly the problem in the third example is that the |
Yeah. This is a common complaint and a lot of people would like it to be improved. The canonical tracking bug for this request is dart-lang/language#1536. I'm absolutely open to improving this; it's just a matter of prioritizing it against other work, and this year when I looked into possible flow analysis improvements to take on, I decided that field promotion would give a bigger benefit. I'll add a note to that issue to point to this one, so that when we look at prioritizing flow analysis work for next year, we'll be reminded that this came up again. FWIW, it's not a trivial fix to do, because type analysis happens in a two fixed passes: one pass where we resolve each bare identifier to its declaration, and a second pass where we assign a type to everything. (There are some assumptions pretty deeply baked in to the analyzer and front end that would make it difficult to expand this to more than two passes). In the front end the first pass happens during parsing, so we have some additional limitations on what data we can collect during that pass. At the moment, the data we collect is approximately: for every block, what variables does it assign to and/or write capture? Returning to your first example: void foo([int? x]) {
x ??= 42;
print(x + 1); // <- not an error; x is non-null because of the above line.
void y() {
print(x + 1); // <-- error because I don't know.
}
y();
} During the first pass, the only information we collect about The way I would approach improving this is to change the first pass so that instead of keeping track of information on a block-by-block basis, it builds up a simplified graph of the control flow in the function, and then I'd add a step in between the two passes that analyzes that simplified graph to determine which variables need to be demoted at the beginning of each block. So for your example above, the first pass would essentially model the code as:
And it would see that at the time
Correct. What's happening in the second example is that we see that there are no assignments to
Actually it's not about what does the promotion, it's simply that in both the first and third examples, there is an assignment to |
Closing this issue in favor of the canonical issue dart-lang/language#1536. Let's have any further discussion there. |
This doesn't work:
But this does:
But this doesn't:
and on the last example if I analyze it with the analyzer I get this:
where I'm told that on line 7 it can't be null so the 'if'-check is unnecessary (which is true), but on line 10 I'm told that I can't use it because it can be null (it can't).
I was told by @johnniwinther (about the first example) that
Can we do better?
/cc @lrhn @stereotype441
The text was updated successfully, but these errors were encountered: