-
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
Dart should warn on guaranteed cast errors #33372
Comments
This could also be a I totally understand why Dart2, the specification, does not allow try {
giveMeListOfStrings(names);
} on CastError {
// ...
} For example, for: void main() {
var x = [];
useListOfString(x);
}
void useListOfString(List<String> _) {
print('Yay!');
} Dart2JS emits, roughly: main: function() {
H.assertSubtype([], "$isList", [P.String], "$asList");
H.printString("Yay!");
} But given that I think 99.99%+ of users do not want a |
Note #33307, 'Exact types': A situation where a cast is guaranteed to fail is also often a situation where some relevant expression may be given an exact type. |
Thanks @eernstg. To be clear, I hope this isn't gated on changing the specification :) (Call it a "warning" or a "hint" or whatever nomenclature lets me have it sooner!) |
I can see the point, but if we don't know which types will be considered exact then we may not know how to deal with some concrete situations. Say, how about the return type of a local function declared as |
Honestly for most cases I see users hit this, just considering the precise/exact/simple cases (i.e. doesn't require global inference) is a huuuuuuuuge benefit. I'd hate to try and solve 100%. |
We can't hope for completeness because the underlying problem is undecidable, but we must be able to tell precisely which expressions have an exact type. Focusing on literals (including function literals) at first would make sense, but constant expressions have an exact type as well, even when accessed via one or more declared names, so it isn't even obvious which cases are "easy" to be included in a first round. In any case, any new error will conflict with the intention to stay away from breaking changes for quite a while, so it would have to be a lint. |
Yes, the request was for a lint or hint or warning not an error 👍 |
Thanks @matanlurey for pointing me to the correct issue. I just want to add an example, where this caused a runtime error because the analyzer did not complain: Map<String, dynamic> hitmap = {};
mergeHitmaps(createHitmap(reportFile), hitmap); resulting in a runtime exception of In my opinion this should be reported by the analyzer by default as it fails on runtime anyway and can never be successful so it should not require any flags. I can get a warning by using
but this will also add warnings to places that at least have a chance to succeed -> all paces where the parameter itself is dynamic and not one of the type parameters. |
@denniskaselow, note that this situation could not give rise to a 'guaranteed cast error': Map<String, dynamic> hitmap = {};
mergeHitmaps(createHitmap(reportFile), hitmap); Surely, the problem could have arisen because However, it cannot be a 'guaranteed cast error'; it's just a regular downcast, and unless you want to flag all downcasts (cf. Maybe the cure would have two steps: (1) detect that |
I don't think you need to go that far. For any For any mutable ( |
Ah, that's right: If a final variable (local or not) with no type annotation is initialized by an expression whose type has some kind of exactness, the variable itself can be given the same type including the exactness. But if it's constant then we always know the actual value, which in particular means that its type is exact. For the 'effectively final' stuff, I hope we can introduce something like |
Is this issue still valid? The below triggers Should a fix be offered to have it as void giveMeListOfStrings(List<String> names) {}
void f(bool b) {
// "Effectively" final List<dynamic>
var names = [];
if (b) {
names.add('Matan');
}
// Statically does *not* accept List<dynamic>
giveMeListOfStrings(names);
} |
I'll close this issue: The original example relies on implicit downcasts, and they have not been present in the language for any other source type than @matanlurey, please reopen or create a new issue if you think there a substantial part of this issue that hasn't already been handled by more recent language updates. |
(I think this would significantly help Flutter, Angular, and all Dart2 users)
Best explained through an example:
This line:
giveMeListOfStrings(names);
... will never succeed, statically. It is a runtime error in Dart2, however, because of implicit downcasts. That's a much harder problem, and might require additional flags and such. I think we could catch a good number of "local" downcast errors in the analyzer:
Generic<T>
whereT
isdynamic
T
!=dynamic
... issue a warning or lint or whatever:
This might remind you of @Hixie's bugs around
List<Widget>
. That is intentional :)... in conjunction with a "quick fix", it could suggest rewriting
names
as<String> []
.The text was updated successfully, but these errors were encountered: