When generating runtime code, AngularDart often builds a lot of classes, fields, and various other runtime support code that is not directly exposed to end users, and only needs to be valid Dart code in order to be compiled and executed as JavaScript:
// ... in runtime code ...
abstract class View {}
abstract class ChildView<P extends View> extends View {}
// ... in generated code ...
class ViewSomeComponent0 extends View {}
class ViewSomeComponent1 extends ChildView<ViewSomeComponent0> {}
This causes code-bloat in a number of occasions:
$asView and other RTTI.H.setRuntimeType when stored in a JSArray.The Dart2JS/DDC SDKs have access to such an annotation to use on their own runtime code where they are sure it doesn't impact user code and desire smaller/faster code:
If this was exposed to us (i.e. through package:meta/dart2js.dart), I think it could help a bit.
/cc @leonsenft @rakudrama
Semantics breaking behavior triggered by a simple annotation is not something I'd be particularly happy about.
Is this possibly a feature we could put into the language instead. What if you could declare a type variable as static:
class Box<static T> {
T value;
}
to make it not be reified at run-time.
It would mean that Box<Foo> x = Box<Bar>() as Box<Foo>; would always succeed. There would be no way for an is or as check to fail at run-time. It would be as if Box was simply not a generic class, all type arguments and parameters would be erased. So a List<Box<int>>() is List<Box<String>>.
Inside the class, T would act normally statically, and at run-time it would always act as if it had been passed its bound. We could make restrictions on how you use T, but it won't really matter.
Outside the class, it will be unsound.
Box<int> b = Box();
(b as Box<String>).value = "A";
int x = b.value; // type-checks, but fails.
so we'd need extra run-time type checks everywhere something of a static-only type is assigned to a run-time reified type.
A static (erased?) modifier or some equivalent mechanism for opting out of runtime reified types would be extremely useful for getting good performance out of custom generic data structures!
It is currently very easy to inadvertently cause the rti optimizer to retain types and the performance penalties can be massive when that happens. A language level opt-out like this, with well defined semantics and consequences, would make writing and maintaining performance sensitive generic code way more manageable.
An erased modifier with clear semantics would be useful for external classes and methods (e.g. JS-interop) that have type variables.
Most helpful comment
Semantics breaking behavior triggered by a simple annotation is not something I'd be particularly happy about.
Is this possibly a feature we could put into the language instead. What if you could declare a type variable as
static:to make it not be reified at run-time.
It would mean that
Box<Foo> x = Box<Bar>() as Box<Foo>;would always succeed. There would be no way for anisorascheck to fail at run-time. It would be as ifBoxwas simply not a generic class, all type arguments and parameters would be erased. So aList<Box<int>>() is List<Box<String>>.Inside the class,
Twould act normally statically, and at run-time it would always act as if it had been passed its bound. We could make restrictions on how you useT, but it won't really matter.Outside the class, it will be unsound.
so we'd need extra run-time type checks everywhere something of a static-only type is assigned to a run-time reified type.