[vm/aot/tfa] Tree-shake unused late final instance fields with initializer

Previously, tree shaker conservatively treated such fields as used if
constructor of the class was used.

Tree shaker would still keep late final instance fields without
initializer as it doesn't track how many times the field was
assigned/initialized and repeatitive assignment to a late final field
without initializer throws an exception.

TEST=pkg/vm/testcases/transformations/type_flow/transformer/write_only_field3_nnbd.dart

Change-Id: I859a4e864e2186e754ba4387a50d1ad9a901e6ef
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/255542
Reviewed-by: Aske Simon Christensen <askesc@google.com>
Commit-Queue: Alexander Markov <alexmarkov@google.com>
This commit is contained in:
Alexander Markov 2022-08-22 16:24:19 +00:00 committed by Commit Bot
parent 65b7d62bf1
commit 8bd77bc510
3 changed files with 19 additions and 1 deletions

View file

@ -731,7 +731,10 @@ class SummaryCollector extends RecursiveResultVisitor<TypeExpr?> {
if (member is Constructor) {
// Make sure instance field initializers are visited.
for (var f in member.enclosingClass.members) {
if ((f is Field) && !f.isStatic && (f.initializer != null)) {
if ((f is Field) &&
!f.isStatic &&
!f.isLate &&
(f.initializer != null)) {
_entryPointsListener.addRawCall(
new DirectSelector(f, callKind: CallKind.FieldInitializer));
}

View file

@ -24,15 +24,24 @@ class B {
}
}
class C {
// Should be removed.
late final int x = int.parse("1");
}
// Should be removed.
late int staticLateA;
// Should be retained.
late final int staticLateB;
// Should be removed.
late final int staticLateC = int.parse("2");
void main() {
new A().use();
new B().use();
new C();
staticLateA = 4;
staticLateB = 4;

View file

@ -20,10 +20,16 @@ class B extends core::Object {
[@vm.direct-call.metadata=#lib::B.x] [@vm.inferred-type.metadata=!? (skip check)] this.{self::B::x} = 3;
}
}
class C extends core::Object {
synthetic constructor •() → self::C
: super core::Object::•()
;
}
[@vm.inferred-type.metadata=dart.core::_Smi (value: 4)] [@vm.unboxing-info.metadata=(i)->i]late static final [setter] field core::int staticLateB;
static method main() → void {
[@vm.direct-call.metadata=#lib::A.use] [@vm.inferred-type.metadata=!? (skip check)] new self::A::•().{self::A::use}(){() → dynamic};
[@vm.direct-call.metadata=#lib::B.use] [@vm.inferred-type.metadata=!? (skip check)] new self::B::•().{self::B::use}(){() → dynamic};
new self::C::•();
4;
self::staticLateB = 4;
}