Open
Description
Right now we only build unchecked entries for closures in AOT mode. With NNBD type checks might become more expensive, so we should evaluate possibilities of reducing type checks.
We should
- ensure TFA annotates interface calls if those call sites guarantee that the type checks of covariant parameters in the callee will succeed (non-covariant parameters don't need to be checked anyways, due to the static guarantee)
- build a policy which decides for which functions we want to generate an unchecked entry (where perf would benefit and code size wouldn't hurt too much)
Here's an example
final List<Foo<A>> all = <Foo<A>>[Foo<A1>(), Foo<A11>(), Foo<A2>()];
main() {
print(A21());
// Needs to check, because `x` could e.g. be `Foo<A2>()`.
final Foo<A> x = all[0];
x.foo(A1());
// Does not need to check, because there are no subtypes of `A11` used
// as type argument for Foo::T
final Foo<A11> x2 = all[1];
x2.foo(A11());
// Does not need to check, because there are no subtypes of `A2` used
// as type argument for Foo::T
// Class `A21` is allocated and is a subtype of `A2` but is never used as
// a type argument to Foo::T
final Foo<A2> x3 = all[2];
x3.foo(A2());
}
class Foo<T> {
foo(T a) {}
}
class A {}
class A1 extends A {}
class A11 extends A1 {}
class A2 extends A {}
class A21 extends A2 {}
Right now TFA seems to produce this:
static method main() → dynamic {
core::print(new tes::A21::•());
final tes::Foo<tes::A*>* x = ...;
[@vm.direct-call.metadata=#lib1::Foo::foo??]
[@vm.call-site-attributes.metadata=receiverType:#lib1::Foo<#lib1::A*>*]
x.{tes::Foo::foo}(new tes::A1::•());
final tes::Foo<tes::A11*>* x2 = ...;
[@vm.direct-call.metadata=#lib1::Foo::foo??]
[@vm.call-site-attributes.metadata=receiverType:#lib1::Foo<#lib1::A11*>*]
x2.{tes::Foo::foo}(new tes::A11::•());
final tes::Foo<tes::A2*>* x3 = ...;
[@vm.direct-call.metadata=#lib1::Foo::foo??]
[@vm.call-site-attributes.metadata=receiverType:#lib1::Foo<#lib1::A2*>*]
x3.{tes::Foo::foo}(new tes::A2::•());
}
/cc @sjindel-google