-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
Use of uninitialized late
variables should be a linter error
#46759
Comments
The compiler will do that checking for you if you don't make the local variable String foo(int x) {
String result;
if (x == 1) {
result = 'one';
}
return result;
} Would that solve your need? |
As @bwilkerson says, this is actually expected and intended behavior. Non-late variables requires that they are definitely assigned before they are read. They are safe. Late variables are introduced in order to loosen that requirement for situations where the compiler cannot determine that the variable is actually always assigned, but the programmer knows that it is. (Actually, late String floo;
if (someTest) {
floo = "bad";
}
compute(...);
if (someTest) {
state += floo; // Compiler only knows that `floo` is potentially assigned.
} Here the author knows that The compiler will still complain if there is no way for |
In my exact case it wouldn't since my variable is nullable and not initializing a variable is the idiomatic way to make null variables. So it's more like this: String? foo(int x) {
late String? result;
if (x == 1) {
result = 'one';
}
return result;
} |
Yep, I'm suggesting we make that logic a bit smarter by examining the branches through the code, it's technically possible to do. I don't know if it is feasible given how the code is written. String foo(int x) {
late String result;
return result; // currently we correctly error here
} |
The current behavior is not accidentally being less smart than possible, it's entirely deliberate that it's not flagging the use you have here, and adding You can write the same code as: String? foo(int x) {
String? result;
if (x == 1) {
result = 'one';
}
return result;
} Since the variable is nullable, it's implicitly initialized to Or, you can write it as: String? foo(int x) {
String result;
if (x == 1) {
result = 'one';
}
return result;
} In that case, you do get an error because the In most cases, you don't need to add |
The second case you mention with the uninitialized I have code like this: String? foo(int x) {
if (x > 0) {
if ( x == 1) {
return 'one';
} else {
return 'bigger than one';
}
} else {
return null;
}
} The reviewer of my code doesn't like the if-block with multiple returns. I like it because the compiler forces the maintainer to return an answer in each branch. So, I considered condensing it to one return statement but if I do that I want the same guarantee that I have with the branching return statements. I want to guarantee statically that each branch will set that variable we are returning. I refactored it to String? foo(int x) {
late String? result;
if (x > 0) {
if ( x == 1) {
result = 'one';
} else {
result = 'bigger than one';
}
} else {
result = null;
}
return result;
} This however doesn't give me the same level of static checks that the multiple return statements has. As someone is editing the code they could easily forget to to set I could also use nested ternary operators to get what I want, but in the actual code that would be pretty messy. |
Closing as WAI. |
@jcollins-g, respectfully, the question wasn't wether this works as intended or not. The question is wether the intention was correct and if this is an improvement worth pursuing. When people make suggestions on how to improve Dart, we shouldn't close the issues as WAI because thats dismissing feedback to improve the language from users that have valuable real world usage of Dart. A decision should be made if this is something worth doing or the issue should be filed as a proposal where it can be decided on in the future, not just pocket vetoed. If the team doesn't like the suggestion, say so. |
@gaaclarke, the issue is you're using I don't see what's wrong with using
Using If returning Regarding structure, I don't know your full code, but maybe you can "flatten" some of your ifs? So instead of
you can do: String? foo(int x) {
String? result;
if (x <= 0) result = null;
else if (x == 1) result = "one";
else result = "bigger than one";
return result;
} This way, it's obvious that the final Finally, if you really want to go this way, you can abuse semantics a bit by using a non-nullable variable and returning String? foo(int x) {
String result;
if (x <= 0) return null;
else if (x == 1) { /* forgot to assign here */ }
else result = "bigger than one";
return result; // Error: 'result' must be assigned before it can be used
} |
Example:
The linter should verify that every branch through the code has the potential to set
result
before it is actually used. It can't guarantee that it will bet set but static analysis can detect this code is problematic.The text was updated successfully, but these errors were encountered: