Better context message on SyntheticForwarder in MissingImplementation
Previously we could get something like this:
```
regress_32660_test_06.dart:9:7: Context: 'foo' is defined here.
class I extends G implements H {
^^^
```
because a SyntheticForwarder was added with a file location of the
class.
It now instead goes to the forwarding stub target and says
```
regress_32660_test_06.dart:6:3: Context: 'foo' is defined here.
foo(int x, {int y}) => y;
^^^
```
Change-Id: I6fb1b958f58635c9afffa8e58cd49eb69df28afd
Reviewed-on: https://dart-review.googlesource.com/72680
Reviewed-by: Peter von der Ahé <ahe@google.com>
Commit-Queue: Jens Johansen <jensj@google.com>
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_class_builder.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_class_builder.dart
index 5463069..e277db1 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_class_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_class_builder.dart
@@ -529,6 +529,11 @@
if (hasProblem) {
Name name = interfaceMember.name;
String displayName = name.name + (setters ? "=" : "");
+ if (interfaceMember is Procedure &&
+ interfaceMember.isSyntheticForwarder) {
+ Procedure forwarder = interfaceMember;
+ interfaceMember = forwarder.forwardingStubInterfaceTarget;
+ }
context ??= <LocatedMessage>[];
context.add(templateMissingImplementationCause
.withArguments(displayName)
diff --git a/pkg/front_end/testcases/regress/issue_32660.dart b/pkg/front_end/testcases/regress/issue_32660.dart
new file mode 100644
index 0000000..ec799be
--- /dev/null
+++ b/pkg/front_end/testcases/regress/issue_32660.dart
@@ -0,0 +1,36 @@
+// Copyright (c) 2018, 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.
+
+class A {
+ foo(int x) => x;
+}
+
+class B {
+ foo(int x, {int y}) => y;
+}
+
+class C extends A implements B {
+ noSuchMethod(i) {
+ print("No such method!");
+ return 42;
+ }
+}
+
+class D {
+ foo(int x) => x;
+}
+
+class E extends D {
+ foo(int x, {int y});
+
+ noSuchMethod(i) {
+ print(i.namedArguments);
+ return 42;
+ }
+}
+
+main() {
+ C c = new C();
+ E e = new E();
+}
diff --git a/pkg/front_end/testcases/regress/issue_32660.dart.direct.expect b/pkg/front_end/testcases/regress/issue_32660.dart.direct.expect
new file mode 100644
index 0000000..7f42fe5
--- /dev/null
+++ b/pkg/front_end/testcases/regress/issue_32660.dart.direct.expect
@@ -0,0 +1,48 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+ synthetic constructor •() → void
+ : super core::Object::•()
+ ;
+ method foo(core::int x) → dynamic
+ return x;
+}
+class B extends core::Object {
+ synthetic constructor •() → void
+ : super core::Object::•()
+ ;
+ method foo(core::int x, {core::int y = null}) → dynamic
+ return y;
+}
+class C extends self::A implements self::B {
+ synthetic constructor •() → void
+ : super self::A::•()
+ ;
+ method noSuchMethod(dynamic i) → dynamic {
+ core::print("No such method!");
+ return 42;
+ }
+}
+class D extends core::Object {
+ synthetic constructor •() → void
+ : super core::Object::•()
+ ;
+ method foo(core::int x) → dynamic
+ return x;
+}
+class E extends self::D {
+ synthetic constructor •() → void
+ : super self::D::•()
+ ;
+ abstract method foo(core::int x, {core::int y = null}) → dynamic;
+ method noSuchMethod(dynamic i) → dynamic {
+ core::print(i.namedArguments);
+ return 42;
+ }
+}
+static method main() → dynamic {
+ self::C c = new self::C::•();
+ self::E e = new self::E::•();
+}
diff --git a/pkg/front_end/testcases/regress/issue_32660.dart.direct.transformed.expect b/pkg/front_end/testcases/regress/issue_32660.dart.direct.transformed.expect
new file mode 100644
index 0000000..7f42fe5
--- /dev/null
+++ b/pkg/front_end/testcases/regress/issue_32660.dart.direct.transformed.expect
@@ -0,0 +1,48 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+ synthetic constructor •() → void
+ : super core::Object::•()
+ ;
+ method foo(core::int x) → dynamic
+ return x;
+}
+class B extends core::Object {
+ synthetic constructor •() → void
+ : super core::Object::•()
+ ;
+ method foo(core::int x, {core::int y = null}) → dynamic
+ return y;
+}
+class C extends self::A implements self::B {
+ synthetic constructor •() → void
+ : super self::A::•()
+ ;
+ method noSuchMethod(dynamic i) → dynamic {
+ core::print("No such method!");
+ return 42;
+ }
+}
+class D extends core::Object {
+ synthetic constructor •() → void
+ : super core::Object::•()
+ ;
+ method foo(core::int x) → dynamic
+ return x;
+}
+class E extends self::D {
+ synthetic constructor •() → void
+ : super self::D::•()
+ ;
+ abstract method foo(core::int x, {core::int y = null}) → dynamic;
+ method noSuchMethod(dynamic i) → dynamic {
+ core::print(i.namedArguments);
+ return 42;
+ }
+}
+static method main() → dynamic {
+ self::C c = new self::C::•();
+ self::E e = new self::E::•();
+}
diff --git a/pkg/front_end/testcases/regress/issue_32660.dart.outline.expect b/pkg/front_end/testcases/regress/issue_32660.dart.outline.expect
new file mode 100644
index 0000000..e77621d
--- /dev/null
+++ b/pkg/front_end/testcases/regress/issue_32660.dart.outline.expect
@@ -0,0 +1,37 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+ synthetic constructor •() → void
+ ;
+ method foo(core::int x) → dynamic
+ ;
+}
+class B extends core::Object {
+ synthetic constructor •() → void
+ ;
+ method foo(core::int x, {core::int y}) → dynamic
+ ;
+}
+class C extends self::A implements self::B {
+ synthetic constructor •() → void
+ ;
+ method noSuchMethod(dynamic i) → dynamic
+ ;
+}
+class D extends core::Object {
+ synthetic constructor •() → void
+ ;
+ method foo(core::int x) → dynamic
+ ;
+}
+class E extends self::D {
+ synthetic constructor •() → void
+ ;
+ abstract method foo(core::int x, {core::int y}) → dynamic;
+ method noSuchMethod(dynamic i) → dynamic
+ ;
+}
+static method main() → dynamic
+ ;
diff --git a/pkg/front_end/testcases/regress/issue_32660.dart.strong.expect b/pkg/front_end/testcases/regress/issue_32660.dart.strong.expect
new file mode 100644
index 0000000..057aa3f
--- /dev/null
+++ b/pkg/front_end/testcases/regress/issue_32660.dart.strong.expect
@@ -0,0 +1,73 @@
+// Errors:
+//
+// pkg/front_end/testcases/regress/issue_32660.dart:13:7: Error: The non-abstract class 'C' is missing implementations for these members:
+// 'foo'.
+// Try to either
+// - provide an implementation,
+// - inherit an implementation from a superclass or mixin,
+// - mark the class as abstract, or
+// - provide a 'noSuchMethod' implementation.
+//
+// class C extends A implements B {
+// ^
+//
+// pkg/front_end/testcases/regress/issue_32660.dart:24:7: Error: The non-abstract class 'E' is missing implementations for these members:
+// 'foo'.
+// Try to either
+// - provide an implementation,
+// - inherit an implementation from a superclass or mixin,
+// - mark the class as abstract, or
+// - provide a 'noSuchMethod' implementation.
+//
+// class E extends D {
+// ^
+
+library;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+ synthetic constructor •() → void
+ : super core::Object::•()
+ ;
+ method foo(core::int x) → dynamic
+ return x;
+}
+class B extends core::Object {
+ synthetic constructor •() → void
+ : super core::Object::•()
+ ;
+ method foo(core::int x, {core::int y = null}) → dynamic
+ return y;
+}
+class C extends self::A implements self::B {
+ synthetic constructor •() → void
+ : super self::A::•()
+ ;
+ method noSuchMethod(core::Invocation i) → dynamic {
+ core::print("No such method!");
+ return 42;
+ }
+ abstract forwarding-stub method foo(core::int x, {core::int y = null}) → dynamic;
+}
+class D extends core::Object {
+ synthetic constructor •() → void
+ : super core::Object::•()
+ ;
+ method foo(core::int x) → dynamic
+ return x;
+}
+class E extends self::D {
+ synthetic constructor •() → void
+ : super self::D::•()
+ ;
+ abstract method foo(core::int x, {core::int y = null}) → dynamic;
+ method noSuchMethod(core::Invocation i) → dynamic {
+ core::print(i.{core::Invocation::namedArguments});
+ return 42;
+ }
+}
+static method main() → dynamic {
+ self::C c = new self::C::•();
+ self::E e = new self::E::•();
+}
diff --git a/pkg/front_end/testcases/strong.status b/pkg/front_end/testcases/strong.status
index ec7d1bd..3545194 100644
--- a/pkg/front_end/testcases/strong.status
+++ b/pkg/front_end/testcases/strong.status
@@ -201,6 +201,7 @@
regress/issue_31299: TypeCheckError
regress/issue_32972: TypeCheckError
regress/issue_33452: RuntimeError # Test has an intentional error
+regress/issue_32660: TypeCheckError # Test has an intentional error
runtime_checks_new/contravariant_generic_return_with_compound_assign_implicit_downcast: RuntimeError
runtime_checks_new/mixin_forwarding_stub_field: TypeCheckError