-
Notifications
You must be signed in to change notification settings - Fork 1.7k
language: specify if type literals are valid const map keys #21553
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
Marked this as blocking #17207. |
I note that the dartdoc for Type does not list a == method. So either it needs to change, or dart2js should not have a ==. In any case, we should agree on whether any predefined class implements == across all implementations of Dart and what its semantics are and have that specified in the dartdoc. Since dart2js has different needs than the VM and has a hard time without this override, this would tend to force the VM to have an ==. That doesn't necessarily mean that we disallow const types as keys in maps. Doing so is arguably a breaking change (at least for server apps) and it seems to be an annoying restriction. We could add Type to the list of exclusions in section 16.8 and 17.9 - types that implement == and yet can be used as keys or in switches. In this scenario, the code would be legal, and we would have a binding specification == for Type in the dartdoc saying when two Type objects were equal. Comments? Objections? cc @floitschG. |
I don't think dartdoc's output has any impact. Will reply to the actual issue later. |
Never mind. The spec actually explicitly states that it must be an instance of "Type". "The run-time type of every object is represented as an instance of class Type which can be obtained by calling the getter runtimeType[...]". |
So, are we ok with explicitly allowing constant Type objects to be used as const map keys and switch statements? This will go in post ECMA-408 2nd edition (which hopefully will be official in a month's time). |
Stephen has a proposal to make Types canonicalized in dart2js. |
Regarding #2: I believe we need to allow const Types as const map keys. I would prefer to avoid specifying Type.== and fall back on Object.== since invariably the method has to deal with non-Type arguments and is is worth avoiding the cost of the 'arg is Type' as it is quite high. Regarding #4: On the VM: x.runtimeType.runtimeType prints as '_Type'. I would hope that we can have multiple implementations of Type that also implement an internal interface so that the runtime can do interesting things with specialized subtypes that have optimized private methods. It would be a penalty in code and heap space to have to wrap the internal type simply to avoid there being multiple implementations of Type. |
As Stephen says, anything that implements TYpe is considered an instance of Type. It doesn't matter for the == issue though: anyone who chooses to override == must obey the contract for the built in class Type. |
cc @karlklose. |
Just discussed this with Karl. No resolution yet, but a few discussion points:
Internally we can easily use two different classes for these types, and can guarantee that the canonicalized version doesn't override "==".
|
Florian,
In practice canonicalizing types at runtime is a memory benefit even if they are not stored in a weak set: You limit the number of type objects floating around in the heap. |
I forgot to follow-up, but the more I think of it, the more I think we can canonicalize in the VM too. |
I think that Type should be allowed as const Map keys, and there should be an exception made for them in the spec as there is with Symbol literals. |
If we prevent On the other hand, I don't think you should ever be using equality as the test on types. If possible, you should always use is-subtype to test, and we should make that possible and easy. |
Also note this use case from #30257 , which is abstracted from real code that I ran into internally. class A {}
void main() {
var x = new A();
switch (x.runtimeType) {
case A: print("hello");
}
} |
Note that we have abstained from introducing the "user can't extend/implement" constraint on |
FWIW AngularDart is starting to remove all support for using |
I'm writing a flutter app with some tests, and ran into this issue with the switch case, using class inheritance... i would like to do something like this:
however, the block does not recognize that x must be Child1 inside of that case, so it errors on accessing x.value. Strangely enough, it works if i put extra logic in the block:
is there a way Dart can be smarter about inferring the types? i understand there's an issue if we use labels in the switch case (or continues), but barring those, we should be able to infer types in these case blocks. a related issue is that if we're in a block and we check something like this:
in this block, after the continue, we should be able to infer the type of p as Child1, but no such luck... |
@lowagner We could also be smarter about that kind of type promotion, but improved type promotion is another issue (many other issues, actually, e.g., #32236). |
@lrhn wasn't overriding |
No, I don't think that was ever planned. We were hoping to remove My recommendation still stands: Never use |
To allow It's possible to implement In general, we need to specify that for all objects that can be constant expressions and where the actual implementation class is platform specific. |
Type literals are now allowed as Map keys. The following works in the VM, dart2js, and analyzer:
I think this issue can be closed; the long discussion about runtimeType being usable in a switch seems like a separate issue. |
Agreed; we have separate threads about how to determine equality of reified types, and the title of this issue is a question which was resolved in 0808d29. |
Uh oh!
There was an error while loading. Please reload this page.
The spec as I read is does not tell us whether or not the following program is legal. It depends on whether the implementation of Type overrides
operator==()
. The VM and dart2js differ in this regard which is a problem for portability as programs developed on the VM don't work on dart2js (#17207)It would be helpful to have a ruling on whether this specific combination of features is supposed to work and then have it implemented uniformly.
Wrapping the type to avoid operator== as follows leads to surprising behaviour.
Related issues: #17123 #17207
The text was updated successfully, but these errors were encountered: