-
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
"Runtime check on non-ground type T may throw StrongModeError" #24565
Comments
This is primarily relevant to DDC generated JS code, but it is a general soundness issue in Dart. What this means is that we can't guarantee that the
prints In general, type checks on For type parameters ( |
Isn't that a Here are the actual errors I get, with pointers to the code online:
|
Yes, but So, it's both a In general, To take the first example on your list, if you do something like:
then |
Is the runtimeType of a I guess I'm saying it depends on what the definition of It sounds to me like what you're saying is that the bug is using |
The actual runtimeType is different. The The funny thing about Dart's subtype relationship is that it is cyclic in a few corners. A no implicit dynamic would be useful, but perhaps not really usable until we have generic methods. (E.g., Another (complementary) possibility is to annotate classes like |
What I'd ideally want is to allow DragTargetState to differentiate |
We might be able to make that work. To do it statically, we may need to annotate both
which would allow |
DragTargetState can't know about Foo, and Foo can't know about DragTargetState. Foo could be List, for instance. Or some generic class from some random pub package. I'm fine with waiting for generic methods if it would allow us to warn on implicit dynamics. |
Anyway, it sounds like this error message is actually useful (even outside strict mode). The bug is that it's very unclear what it means or what action should be taken to address it. |
I believe @munificent recently fixed this? |
I don't think so. The underlying behavior is unchanged as far as I know. I definitely think we can improve the error message, and I'd be happy to do that. |
merging #26100, CC @hermanbergwerf |
Now that more folks are hitting this, I wonder if we can add a document somewhere to describe why @hermanbergwerf -- the way to handle that in your example would be something like: factory fromData(Map<String, dynamic> data) {
List<int> field;
if(data.containsKey('field') && data['field'] is List/*OLD: <int>*/) {
// OLD: field = data['field'] as List<int>;
field = new List<int>.from(data['field']); // NEW
} else {
throw new ArgumentError.value(data, 'data', "no valid data field for 'field'");
}
return new MyClass(field);
} ... the copy will ensure that each item is checked that it's actually an integer. An alternative would be to supply a checked wrapper of some sort, e.g. |
I think @nex3 is working on a wrapper class like that for the collections package. |
I think it's worth considering where to put the blame. Vijay said
The underlying issue is that a reference of type But if From the point of view of soundness this is an expensive design choice. In particular, navigation in the object graph is unsound even in checked mode if we encounter an object whose runtime type is a reified-dynamic type (that is, a generic class whose type arguments include I'd like to be able to guarantee that such objects just don't exist, in which case Strong mode in the analyzer uses a different approach, where reified-dynamic type instances are allowed to exist, and dynamic type checks for instantiations of generic classes are frowned upon. This means, of course, that a List<Object> f(List<int> xs) => xs;
main() {
List<int> xs = [];
List<Object> ys = f(xs);
ys.add("Hello, world!");
int x = xs[0];
print("$x");
} This program has 'No issues' in strong mode analysis, and still it stops with a runtime error in checked mode. It's because of this kind of phenomenon that strong mode cannot have exactly the same semantics as the one that the spec describes. I'd love to see strong mode and the spec converge, but it is not trivial (especially as long as we allow all these reified-dynamic instances to exist ;-). |
@eernstg Just a quick note: For soundness, strong mode still requires a runtime type check on generic class method arguments where the parameter type is a type parameter (or based on the type parameter). In DDC, ys.add("Hello, world!"); would fail at runtime. The alternative is to disallow covariance on generics, but that's a bigger change. |
Indeed, but you're not being entirely explicit about what is going on here: If you want a runtime check to fail at So the only way you can get the run time failure you mention is by making sure that the given list is an instance of something else than This is the kind of thing I was referring to when I said 'cannot have exactly the same semantics'. |
For what it's worth, over in Flutter land, we don't really care that We're designing our framework to handle two cases:
For people in the first category, we have configured the analyzer to complain about any missing types, and (once the analyzer supports this) this will include complaining about untyped literals. So there will never be a For people in the second category, all their lists are We try to write our code to handle both. This means we don't do checks like "is this a As a side note, for people in the first bucket, I'm totally fine with the analyzer and the runtime using types on the LHS to imply types on the RHS or vice versa. (I think I'd prefer explicit RHS types implying LHS types, but that's another story.) For people in the second bucket, though, there's no types at all in the source, and it's not ok to turn this: var xs = [0]; ...into a |
@Hixie could you please file a separate bug on this? There is a general question of how strong (magical?) inference should be for generic methods and generic class constructors (and list literals are just a case of the latter).
Edit: I believe the above - what you don't want - is our current behavior. |
Happy to file bugs -- can you clarify which of my various passive aggressive complaints in my last comment you'd like bugs for? :-) |
We currently infer / instantiate: var xs = [0]; as That means you'll get a static error if follow that with: xs.add("hello"); I think you're objecting. :-) |
In strong mode? That certainly doesn't cause any problems today. :-) |
Type-asserting wrapper methods have landed in collection 1.5.0. |
Duping this against #28988 ... but the good news is, we're going to remove this error. |
(also, that bug is about DDC runtime behavior, the analyzer message was removed quite a while ago) |
I got the strong-mode analyzer message:
Runtime check on non-ground type T may throw StrongModeError
...but what does it mean? When may it throw that? Why? How do I fix it?
The text was updated successfully, but these errors were encountered: