Skip to content
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

[dart2js] Should type-variable erasure ignore type variable in type literals? #51894

Open
rakudrama opened this issue Mar 29, 2023 · 1 comment
Labels
area-web Use area-web for Dart web related issues, including the DDC and dart2js compilers and JS interop. dart2js-optimization web-dart2js

Comments

@rakudrama
Copy link
Member

I tried replacing JSArray.runtimeType with:

  Type get runtimeType => List<E>;

This defeats type erasure, even with --lax-runtime-types in small programs that use .runtimeType but don't otherwise use E.

Should we:

  • Add further complexity to the type erasure optimization to (1) ignore E in the context of a type literal inside an implementation of runtimeType and later (2) replace this with the 'erased' type.
  • Accept that it is inevitable that 'real' programs will need JSArray.E for some other purpose and go ahead with the change. This will make some micro-benchmarks slower, but more representative of real-world performance.
@rakudrama rakudrama added web-dart2js dart2js-optimization area-web Use area-web for Dart web related issues, including the DDC and dart2js compilers and JS interop. labels Mar 29, 2023
@fishythefish
Copy link
Member

fishythefish commented Mar 29, 2023

Some clarification: we don't have a general --lax-runtime-types flag; we have --lax-runtime-types-to-string. This flag has two big restrictions:

  1. It only applies to Object.runtimeType, not overrides.
  2. It only applies when .toString() is immediately invoked* on the result of .runtimeType. If the result is used in any other way, we do not erase types in order to preserve semantics of operations like ==.

* We do a little bit of work to ensure that string interpolation and certain patterns including foo?.runtimeType.toString() work as well. Since we're matching on the kernel AST early in the compilation pipeline, this analysis is not very sophisticated. It's fooled by inlinable functions like foo(x) => x.toString(); and print(x.runtimeType) doesn't work either.

Restriction 1 is the issue here. I don't think the issue is that we specifically check for Object anywhere; it's just that an override of .runtimeType looks like any other method. RTI need should be able to check for that easily enough.

For an example without lists, compile the following program with --lax-runtime-type-to-string and then again with the marked line commented out.

class Foo<T> {
  Type get runtimeType => Foo<T>; // comment me out
}

void main() {
  print(Foo<int>().runtimeType.toString());
}

It probably isn't too hard to ease the restriction, but we should probably just do it for TrustedGetRuntimeType. A user-defined .runtimeType could do e.g. typechecks with T in the body.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-web Use area-web for Dart web related issues, including the DDC and dart2js compilers and JS interop. dart2js-optimization web-dart2js
Projects
None yet
Development

No branches or pull requests

2 participants