After https://dart-review.googlesource.com/c/sdk/+/120680 lands, flow analysis will only demote variables written to in closures if a closure exists that captures writes to the variable, so for example:
test(Object x) {
if (x is int) {
...
print(x + 1); // Ok, x is promoted
}
localFunction() {
x = 'foo';
}
...
if (x is int) {
...
print(x + 1); // Not ok; localFunction might have been called between the test and usage of x
}
}
However, there is a corner case that is not yet handled properly:
test() {
outerLocalFunction(Object x) {
if (x is int) {
...
print(x + 1); // Should be ok, but flow analysis thinks it isn't
}
innerLocalFunction() {
x = 'foo';
}
...
}
...
}
What's happening in this second example is that innerLocalFunction captures a write to x. So on entry to outerLocalFunction, we assume that a closure for innerLocalFunction might exist (because outerLocalFunction might be called more than once), and therefore we prohibit promotion of x inside outerLocalFunction. But that's unnecessary, because if a closure for innerLocalFunction exists at the time that outerLocalFunction is entered, the writes to x that it captures are to a different instance of x.
I think this is fixable, but I'll want to think carefully through the solution to avoid unsoundness.
After https://dart-review.googlesource.com/c/sdk/+/120680 lands, flow analysis will only demote variables written to in closures if a closure exists that captures writes to the variable, so for example:
However, there is a corner case that is not yet handled properly:
What's happening in this second example is that
innerLocalFunctioncaptures a write tox. So on entry toouterLocalFunction, we assume that a closure forinnerLocalFunctionmight exist (becauseouterLocalFunctionmight be called more than once), and therefore we prohibit promotion ofxinsideouterLocalFunction. But that's unnecessary, because if a closure forinnerLocalFunctionexists at the time thatouterLocalFunctionis entered, the writes toxthat it captures are to a different instance ofx.I think this is fixable, but I'll want to think carefully through the solution to avoid unsoundness.