[vm/aot] Handle FieldInitializer pointing to a Field's Reference which is reused for a getter

This is a follow-up to https://dart-review.googlesource.com/c/sdk/+/186680.
After that change, tree shaker started reusing Reference to a Field
when it is replaced with a getter. As a side-effect, this makes
FieldInitializer.field to crash as Reference is now pointing to Procedure,
not a Field.

The fix is to carefully use 'node.fieldReference.asMember' instead of
'node.field' and then retrieve original Field node if it was replaced
with a getter.

TEST=pkg/vm/testcases/transformations/type_flow/transformer/regress_45324_2.dart
Fixes https://github.com/dart-lang/sdk/issues/45324

Change-Id: Ic34e8b9933b00997cd350a4ad93f798c86ac60ad
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/191323
Auto-Submit: Alexander Markov <alexmarkov@google.com>
Commit-Queue: Johnni Winther <johnniwinther@google.com>
Reviewed-by: Johnni Winther <johnniwinther@google.com>
diff --git a/pkg/vm/lib/transformations/type_flow/transformer.dart b/pkg/vm/lib/transformations/type_flow/transformer.dart
index ff602a2..221cb64 100644
--- a/pkg/vm/lib/transformations/type_flow/transformer.dart
+++ b/pkg/vm/lib/transformations/type_flow/transformer.dart
@@ -1185,9 +1185,11 @@
     if (_isUnreachable(node)) {
       return _makeUnreachableInitializer([node.value]);
     } else {
-      assert(shaker.isMemberBodyReachable(node.field),
-          "Field should be reachable: ${node.field}");
-      if (!shaker.retainField(node.field)) {
+      final field =
+          fieldMorpher.getOriginalMember(node.fieldReference.asMember) as Field;
+      assert(shaker.isMemberBodyReachable(field),
+          "Field should be reachable: ${field}");
+      if (!shaker.retainField(field)) {
         if (mayHaveSideEffects(node.value)) {
           return LocalInitializer(
               VariableDeclaration(null, initializer: node.value));
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/regress_45324_2.dart b/pkg/vm/testcases/transformations/type_flow/transformer/regress_45324_2.dart
new file mode 100644
index 0000000..6c4d972
--- /dev/null
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/regress_45324_2.dart
@@ -0,0 +1,27 @@
+// Copyright (c) 2021, 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.
+
+// @dart = 2.12
+
+class A {
+  void doTest(Z a) {
+    print(a.appName);
+  }
+}
+
+class Z {
+  final String? appName;
+  Z({this.appName});
+}
+
+class X extends Base implements Z {}
+
+class Base {
+  String get appName => 'x';
+}
+
+void main() {
+  Z();
+  A().doTest(X());
+}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/regress_45324_2.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/regress_45324_2.dart.expect
new file mode 100644
index 0000000..2ef7c98
--- /dev/null
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/regress_45324_2.dart.expect
@@ -0,0 +1,34 @@
+library #lib /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  synthetic constructor •() → self::A
+    : super core::Object::•()
+    ;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2]  method doTest([@vm.inferred-type.metadata=#lib::X] self::Z a) → void {
+    core::print([@vm.direct-call.metadata=#lib::Base.appName] [@vm.inferred-type.metadata=dart.core::_OneByteString (value: "x")] a.{self::Z::appName});
+  }
+}
+class Z extends core::Object {
+  constructor •() → self::Z
+    : super core::Object::•()
+    ;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:3]  abstract get /*isLegacy*/ appName() → core::String?;
+}
+class X extends self::Base implements self::Z {
+  synthetic constructor •() → self::X
+    : super self::Base::•()
+    ;
+}
+abstract class Base extends core::Object {
+  synthetic constructor •() → self::Base
+    : super core::Object::•()
+    ;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:3]  get appName() → core::String
+    return "x";
+}
+static method main() → void {
+  new self::Z::•();
+  [@vm.direct-call.metadata=#lib::A.doTest] [@vm.inferred-type.metadata=!? (skip check)] new self::A::•().{self::A::doTest}(new self::X::•());
+}