[beta] [tfa] Fix crash when building field guard summary with captured receiver
When building a field guard summary, field initializer is not included
into the body. So field initializer AST should not be visited to
calculate captured variables and field guard summary
should not have a captured reveiver.
TEST=pkg/vm/testcases/transformations/type_flow/transformer/regress_flutter147239.dart
Issue: https://github.com/flutter/flutter/issues/147239
Change-Id: Ibb4827edcfb253c13ac40e6167a447ad36d9eb5e
Cherry-pick: https://dart-review.googlesource.com/c/sdk/+/364203
Cherry-pick-request: https://github.com/dart-lang/sdk/issues/55557
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/364380
Commit-Queue: Alexander Markov <alexmarkov@google.com>
Reviewed-by: Siva Annamalai <asiva@google.com>
diff --git a/pkg/vm/lib/transformations/type_flow/summary_collector.dart b/pkg/vm/lib/transformations/type_flow/summary_collector.dart
index 369572a..8ffcb5a 100644
--- a/pkg/vm/lib/transformations/type_flow/summary_collector.dart
+++ b/pkg/vm/lib/transformations/type_flow/summary_collector.dart
@@ -302,9 +302,7 @@
LocalFunction? summaryFunction;
int numVariablesAtSummaryFunctionEntry = 0;
- _VariablesInfoCollector(Member member, this.summaryFunction) {
- member.accept(this);
- }
+ _VariablesInfoCollector(this.summaryFunction);
int get numVariables => varDeclarations.length;
@@ -638,7 +636,10 @@
}
_staticTypeContext = StaticTypeContext(member, _environment);
- _variablesInfo = _VariablesInfoCollector(member, localFunction);
+ _variablesInfo = _VariablesInfoCollector(localFunction);
+ if (fieldSummaryType != FieldSummaryType.kFieldGuard) {
+ member.accept(_variablesInfo);
+ }
_variableValues = List<TypeExpr?>.filled(_variablesInfo.numVariables, null);
_aggregateVariable = List<bool>.filled(_variablesInfo.numVariables, false);
_capturedVariableReads = null;
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/regress_flutter147239.dart b/pkg/vm/testcases/transformations/type_flow/transformer/regress_flutter147239.dart
new file mode 100644
index 0000000..98e93f6
--- /dev/null
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/regress_flutter147239.dart
@@ -0,0 +1,17 @@
+// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Regression test for https://github.com/flutter/flutter/issues/147239.
+// Verifies that TFA doesn't crash when creating a field guard summary
+// for a field which has initializer with closure and captured receiver.
+
+class Foo<T> {
+ late final aField = () {
+ return <T>[];
+ };
+}
+
+main() {
+ print(Foo<String>().aField);
+}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/regress_flutter147239.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/regress_flutter147239.dart.expect
new file mode 100644
index 0000000..6fe9759
--- /dev/null
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/regress_flutter147239.dart.expect
@@ -0,0 +1,19 @@
+library #lib;
+import self as self;
+import "dart:core" as core;
+
+class Foo<T extends core::Object? = dynamic> extends core::Object {
+
+ [@vm.inferred-type.metadata=dart.core::_Closure (closure 1 in #lib::Foo.aField)]
+ [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:1]
+ [@vm.closure-id=1]
+ late covariant-by-class final field () → core::List<self::Foo::T%> aField = [@vm.closure-id=1]() → core::List<self::Foo::T%> {
+ return [@vm.inferred-type.metadata=dart.core::_GrowableList<dart.core::String>] core::_GrowableList::•<self::Foo::T%>(0);
+ };
+ synthetic constructor •() → self::Foo<self::Foo::T%>
+ : super core::Object::•()
+ ;
+}
+static method main() → dynamic {
+ core::print([@vm.direct-call.metadata=#lib::Foo.aField] [@vm.inferred-type.metadata=dart.core::_Closure (closure 1 in #lib::Foo.aField)] new self::Foo::•<core::String>().{self::Foo::aField}{() → core::List<core::String>});
+}