-
Notifications
You must be signed in to change notification settings - Fork 214
Dart cannot be sure that the method argument is not null if the argument is used in a closure #1597
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
Cf. #1247. It's possible that the flow analysis could give special treatment to the case where all references (read & write) to a given local variable occurs in the same function literal or local function, even though the variable is declared in an enclosing function. |
The general issue here is that the exists a function which assigns to the variable, and we assume it can be invoked at any time. Even inside that function, we can't be sure that the same function won't be invoked again. However, there is something we can do better here. We have a situation where all assignments to the variable assign a non-nullable value. We know that there is no assignment floating around which can make the variable if (nullable == null) {
nullable = 5;
} we do know that |
@lrhn Agreed, it would be really nice if we could see that all assignments to the variable assign non-nullable values. Unfortunately, doing that in the general case is difficult. Consider: extension on int? {
int bar() => this ?? 0;
}
extension on int {
int? bar() => this == 0 ? null : this - 1;
}
void doStuff1(void callback()) { ... }
void doStuff2() { ... }
void foo(int? nullable) {
doStuff(() {
if (nullable == null) {
nullable = 5;
}
doStuff2();
nullable = nullable.bar();
print(nullable.isEven); // Is this ok?
});
} Now, let's assume our rule is that the promotion succeeds if the right hand side of every assignment to Obviously this is a contrived example, but we have to have some sort of plan for how to break loops like this. When I was designing flow analysis, one of my goals was to be able to do the whole algorithm in two passes over the source code: one to locate assignments, and one to do the final type analysis. This eased the implementation by adhering to some assumptions in the analyzer and CFE that type analysis only visits each subexpression once. But it had the disadvantage that in cases like the one @vadlit mentioned, flow analysis has to decide whether it's safe to promote If we dropped the "two passes" requirement, we could certainly do a better job of cases like this by iterating to a fixed point. It would require modification to the analyzer and CFE to allow subexpressions to be visited multiple times during type analysis. And it would require some care in the design to make sure that a fixed point would always be reached (it would be bad if we assigned a variable a provisional type of |
By some reason Dart cannot be sure that the method argument is not null if the argument is used in a closure.
Property 'isEven' cannot be accessed on 'int?' because it is potentially null
In this case, as far as I undestand, there's no chance that the 'nullable' argument suddenly becomes nullable after the 1st check, because it's just a method argument, not class field.
The problem is not reproduced if remove the first check.
Dart 2.12.2
Windows
The text was updated successfully, but these errors were encountered: