-
Notifications
You must be signed in to change notification settings - Fork 1.7k
dart2js strong: issue with subtyping checks on js-interop types #32969
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
/sub: What is the expectation here? Last time I checked this doesn't work for DDC at all (it causes weird/bad behavior). /cc @jmesserly |
I thought we didn't support generic jsinterop classes. At runtime an |
You are correct. I talked with the DDC folks and they also don't reify the generic type arguments: type checks against these terms work as if you are checking against the raw types. @rakudrama and I brainstormed some ideas:
Option 1 has a disadvantage that it makes subtyping checks more expensive overall, while option 2 deals with this statically and keeps the runtime as lean as we can. WDYT? |
Yeah, it may happen to work. I don't know if JS interop really supports generic classes or if it's an accident of how things are implemented (the RTTI for JS interop classes completely ignores any type parameters/arguments). FWIW, there's also no static checks in Analyzer to ensure |
I prefer option 2: This is consistent with the current (Dart 1) behavior and the only scheme that we can consistently support at runtime. We should additionally warn about generic jsinterop types and maybe in time ban them. |
The problem also occurs if a jsinterop class implements a regular generic class: class A<T> {}
@JS()
class B implements A<int> {}
main() {
print(new B() is A<int>); // This prints false regardless of option 1/2 solution.
} |
A third option is to add new special RTI value that represents "any" type argument (i.e. the Dart 1 @JS()
class A<T> {}
class B<T> {}
class C implements B<int> {}
main() {
dynamic a = new A<int>(); // An `A<any>` instance at runtime.
print(a is A<int>); // Prints true because A<any> <: A<int>
print(a is A<String>); // Also prints true because A<any> <: A<String>
dynamic c = new C(); // A `C` instance that implements `B<any>` at runtime.
print(c is B<int>); // Prints true because B<any> <: B<int>
print(c is B<String>); // Also prints true because B<any> <: B<String>
} Note that we're already lax in type-tests on jsinterop classes. In the example above we have
We should probably warn about tests against jsinterop types. |
How do you suggest we replace class A<T> { T get value; }
class B implements A<int> {}
@JS
class C implements B {} Personally, I'd be OK with option-2 for now and not deal with the interface cases (I'd have to validate this, but I believe they are not used today) |
|
I think option 3 is actually easier to implement than option 2. |
Is implementing a Dart interface with a JS interop class actually supported? It will not work in DDC in general (simple examples may happen to work, but there are lots of ways it can go wrong). Especially if the Dart interface is generic, it seems very problematic. I added it to #32929 (we need errors for invalid use of CC @jacob314 ... not sure if we have a spec somewhere of what JS interop is intended to support? |
I don't think it is crucial if the goal of JS interop is limited to supporting creating good Dart facades for JS interfaces which I think it is at this point. There is no up to date spec of what we intend to support and what we don't. We need to ground up evaluate what we intend to support and what we don't intend to support based on the new world of what is easy and hard to support given Dart2. Specifically as you mentioned, generic methods make this much harder. |
repro:
This program prints
true
in legacy mode, butfalse
in strong mode.(example extracted from testing strong mode in customer apps)
The text was updated successfully, but these errors were encountered: