-
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
[lint] [omit_obvious_local_variable_types] false positive #59957
Comments
The reason why the type of The iterable is a local variable, (If you want that then The underlying rationale is that the developer who wrote that local variable declaration (of In short, when it comes to local variables that depend on each other, the rule of thumb is as follows: "If some of these variables need a type annotation then go to the root cause rather than fixing it downstream". This would make the code more evidently typed overall with a small number of type annotations (most dependency trees have more nodes near the leaves than near the root). We could adopt other approaches. E.g., the type of a local variable could be considered to be non-obvious if its declaration has an initializing expression whose type isn't obvious (which could then rely on recursive queries in cases like |
We can see with paths that it is not always the case. If paths type was obvious I would agree with your lint but because here var is used it is not obvious. Your assumption about local variable obviousness is not always right. I think you should revisit this assumption and see if var is used on local variables before deciding it's obvious |
@stephane-archer, it sounds like you'd prefer the version in void early() {
Iterable<String> paths = dropDoneDetails.files.map((e) { // <---
return e.path;
});
for (var path in paths) { // <---
if (FileSystemEntity.isDirectorySync(path)) {
await lutFoldersNotifier.addLutDir(path);
}
}
}
void late() {
var paths = dropDoneDetails.files.map((e) { // <---
return e.path;
});
for (String path in paths) { // <---
if (FileSystemEntity.isDirectorySync(path)) {
await lutFoldersNotifier.addLutDir(path);
}
}
} The lint will flag the I wasn't suggesting that It would of course also be possible to consider local variables to have a non-obvious type, but my experience with this approach (which was the approach I used at first, and for a while) is that it gets quite noisy (that is, there will be type annotations all over the place). We could also say that a local variable has an obvious type if its declaration has an initializing expression whose type is obvious, or if it has a type annotation (and in both cases: if it isn't promoted). Thinking about it. ;-) |
@eernstg void early() {
Iterable<String> paths = dropDoneDetails.files.map((e) {
return e.path;
});
for (String path in paths) { // <- omit_obvious_local_variable_types warning
if (FileSystemEntity.isDirectorySync(path)) {
await lutFoldersNotifier.addLutDir(path);
}
}
} I would agree with the lint because From my understanding, you explain that this warning forces you to write your code like the
in the original code, we can see this assumption is not true. var str = "hello word" // ok var paths = dropDoneDetails.files.map((e) { // not ok, we need the presence of type annotation to assume that
return e.path;
}); I hope you can consider my point and I'm happy to discuss about it. |
This lint tells you to not type variables whose types are obvious. I think that's a reasonable base assumption. If you want to catch cases where a variable isn't obvious, you need the other lint. |
I used var on paths not because his type was obvious but because I didn't care about the type as long as I had a string in the for loop. Here the lint mentions that string is an obvious type and it's not if you look at the original function. I see this has a false positive for the lint because it asks you to remove a type that is not obvious to see without the type annotation |
@stephane-archer wrote:
I can certainly follow your line of reasoning: The type annotation on However, this line of reasoning doesn't quite match the notion of "having an obvious type" that governs the behavior of the lints This works fine for However, we don't get to use declarations without a type annotation often enough just based on these fully unambiguous cases. In practice, there are many other expressions that deserve to be treated as "obviously typed". This is a policy rather than an objective fact, so we can't expect to settle a debate about where to draw the line based on hard facts alone, this will to some extent be an opinionated choice. So we include constructor invocations like This means that "having an obvious type" relies on very foundational properties, like "this is a constructor" vs. "this is a static method", and a reader of the code doesn't need to look up the declaration of that constructor in order to know more about the type of the result. For example, type arguments must be provided explicitly in order to make the type obvious (and the reader doesn't need to look up the constructor declaration in order to reason about how those actual type arguments could be inferred from the types of the actual arguments). The treatment of local variables is similar: It should be enough to know that a particular name denotes a local variable, and then it's classified in a certain way by the During my early experiments with the lints I hadn't done anything special about local variables. This gives rise to a very heavily type annotated style (because So we have a conflict: In isolation, your argument makes sense (that is, |
@eernstg I think we both agree that this lint assumes a local variable has an obvious type and my example shows that is not always the case. If we consider that local variable types have obvious types when they are annotated, then the lint will work as usual for people who use I think the main issue I have with this lint only concerns loops. |
Yes, I do agree. I also understand that the case you mentioned is a strong counter example because the type of However, I prefer the remedy which is to use a style where every local variable is sufficiently clearly typed to justify the rule that the type of a local variable is always "obvious", rather than the remedy which is to classify the type of some local variables as non-obvious, and then propagating that status to any number of other local variables (e.g., from You mention that you don't care about the type of The point is that the following is a simple policy which will help keeping the total number of type annotations low while preserving a clear typing of all expressions: "Local variables have an obvious type, and if you don't think it is sufficiently obvious then please add a type annotation to the earliest possible point in the dependency graph". Otherwise (if this policy is not adopted), I'm worried about the amount of type annotations which will be held up as appropriate if you enable both Some local variables have a type which could never be determined from the type of an initializing expression. For example, For all other local variables with an initializing expression, there will be a unique recommendation if both This is an automatic judgment, and the point is that (1) we don't have to spend a lot of time discussing whether or not a given local variable should have a type annotation, because the lints will say so, and (2) we can use This means that if we change In the end, the overall "goal" of having these lints is that the code should be as readable as possible, with as few local variable type annotations as possible, and I'm afraid the code will have a lot more type annotations if we start considering some local variables to have a non-obvious type. |
You explained my point perfectly. I'm still in favor of omitting the lint warning only in "for loop" if the type is not annotated. var a;
for (int i in a) { // no warning
} List<int> a;
for (int i in a) { // warning
} But I have no more evidence to show and you have well understood my point, I trust in your judgment. Should we close this issue? 🙂 |
Omit the type annotation on a local variable when the type is obvious. Try removing the type annotation.
for me, there is nothing obvious here that makes
path
aString
except the name.So I think this is a false positive for
omit_obvious_local_variable_types
The text was updated successfully, but these errors were encountered: