-
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
spec constraint "static type warning if a type parameter is a supertype of its upper bound" is wrong #23780
Comments
For the record, this issue surfaced during work on DEP #30, github.com/chalin/DEP-non-null. /cc @leafpetersen |
Is there a good reason for using |
It would be for the same reasons one might use Concretely, suppose that you want to declare that T extends A | B. But Dart doesn't support union types (yet), so the best compromise (that avoids false-positive static warnings) is to use |
Yes, my expectation (given the Dart design philosophy) would be that a type parameter bounded by dynamic would be legal, and would essentially behave as dynamic. I agree that the letter of the spec as written would seem to prohibit this. Your proposed text seems reasonable on brief review - I think the first clause is subsumed by the second (reflexivity). I think that there is more than just this one issue at play here though - I think the letter of the spec still doesn't really do what you would expect ehre. If we assume that an upper bound of class F<T extends dynamic> {
int anInt;
T aT;
void doer(T f) {
anInt = f;
aT = anInt;
f.hello();
}
} And indeed, the analyzer gives no warnings on this code. However, I don't see how the definition of assignment compatibility can be read to make I think this is actually more general than the question of something with a direct bound of class G<T extends List<dynamic>> {
List<int> aListOfInt;
T aT;
void doer(T f) {
aListOfInt = f;
aT = aListOfInt;
aT[0].hello();
}
} The analyzer accepts this code, and it seems reasonable from a certain perspective. But I don't see any way to justify it directly from the spec. It would seem to me that this would require something like replacing the text @bwilkerson, @gbracha - any comment? Am I missing anything? |
Right. But, if we keep them separate then the second clause can be phrased in terms of <:, or :> (as in the original spec prose). Here is a simplified version of class class F<T extends dynamic> { T o = 1; }
Making Leaf's derivation explicit we have: = int <: Tdynamic ∨ Tdynamic <: int, by def. of ⟺ As Leaf points out, the left disjunct is false since int and Tdynamic are incomparable. The key question then is whether we accept that [⊥/dynamic]Tdynamic simplifies to T⊥ (using this notation or any equivalent one e.g. using a typing context Γ ). A sure way to curb debate would be to formalize Dart's type system in Coq or Isabelle and prove various properties of it. If we do agree that such a simplification is reasonable then T⊥ << int follows from transitivity applied to
That could work too if we can't agree whether it is reasonable to consider [⊥/dynamic]Tdynamic simplifying to T⊥ is a derived property. |
At this point we are working on Dart 2 and the Dart 1 specification will not be further developed. In Dart 2 there is no In short, everything in this particular part of the language has changed, and hence it seems most reasonable to close this issue. @chalin, thanks for clarifying this area, sorry about not using the input in time! However, the area has been developed in an interesting and hopefully quite useful manner since then. With that, I'll close the issue. |
(Forgot to actually close it. Here we go.) |
According to the analyzer, the VM (and my intuition),
dynamic
is a valid type parameter bound (i.e., no problems are reported over):class C<T extends dynamic> { }
.Consider the following excerpts from the Dart Language Spec (DLS):
DLS 14, "Generics":
DLS 19.4, "Interface Types":
In the case of class
C
, a warning should be issued ifT
:>dynamic
=
dynamic
<:T
= [⊥/
dynamic
]dynamic
<<T
= ⊥ <<
T
which is true, hence, according to the spec, a warning should be issued. I think that the tools are correct and the spec needs tuning.
The purpose of the constraint documented in DLS 14 is to prevent
<<
cycles over type parameters (cf. @gbracha's comment in #17275), so the constraint might be better expressed as:Under this revised definition, no problem would be reported for class
C
above, but an issue would be reported for this example taken from #9555:class D<T extends S, S extends T> { ... }
.The text was updated successfully, but these errors were encountered: