[vm/compiler] Do not use interface target for calls via getters
For calls via getters and fields front-end generates MethodInvocation
node with interface target pointing to a getter/field.
Such target doesn't fully represent what is being called - it should
be implicitly chained by call(), so it is incorrect to use such
interface target for type propagation.
Change-Id: I76198b443474fdcb383671fbc9946b4938a4e1df
Reviewed-on: https://dart-review.googlesource.com/c/88260
Auto-Submit: Alexander Markov <alexmarkov@google.com>
Reviewed-by: Régis Crelier <regis@google.com>
Commit-Queue: Régis Crelier <regis@google.com>
diff --git a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
index e9435cf..73ff36d 100644
--- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
+++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
@@ -3639,13 +3639,13 @@
const Function* interface_target = &Function::null_function();
const NameIndex itarget_name =
ReadCanonicalNameReference(); // read interface_target_reference.
- if (!H.IsRoot(itarget_name) && !H.IsField(itarget_name)) {
+ if (!H.IsRoot(itarget_name) && !H.IsField(itarget_name) &&
+ !H.IsGetter(itarget_name)) {
interface_target = &Function::ZoneHandle(
Z, H.LookupMethodByMember(itarget_name,
H.DartProcedureName(itarget_name)));
- ASSERT((name.raw() == interface_target->name()) ||
- (interface_target->IsGetterFunction() &&
- Field::GetterSymbol(name) == interface_target->name()));
+ ASSERT(name.raw() == interface_target->name());
+ ASSERT(!interface_target->IsGetterFunction());
}
// TODO(sjindel): Avoid the check for null on unchecked closure calls if TFA
diff --git a/tests/language_2/vm/type_of_call_via_getter_test.dart b/tests/language_2/vm/type_of_call_via_getter_test.dart
new file mode 100644
index 0000000..bd246bb
--- /dev/null
+++ b/tests/language_2/vm/type_of_call_via_getter_test.dart
@@ -0,0 +1,30 @@
+// Copyright (c) 2019, 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.
+
+// This test verifies that compiler infers correct type from call via getter.
+
+// VMOptions=--no_background_compilation --optimization_counter_threshold=10
+
+import "package:expect/expect.dart";
+
+typedef String IntFunctionType(int _);
+
+String functionImpl(int a) => 'abc';
+
+class Box {
+ IntFunctionType get fun => functionImpl;
+}
+
+var box = new Box();
+
+void foo() {
+ Expect.isFalse(box.fun(42) is Function);
+ Expect.isTrue(box.fun(42) is String);
+}
+
+void main() {
+ for (int i = 0; i < 20; ++i) {
+ foo();
+ }
+}