[fasta] Fix override-based type inference for setters
If both the getter and the setter are present in the superclass, the type should
be taken from the setter.
Change-Id: Ie0d84e45d15341151af4a688c508da0f1d7b522d
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/101988
Reviewed-by: Aske Simon Christensen <askesc@google.com>
diff --git a/pkg/front_end/lib/src/fasta/kernel/class_hierarchy_builder.dart b/pkg/front_end/lib/src/fasta/kernel/class_hierarchy_builder.dart
index f433d38..dafd56c3 100644
--- a/pkg/front_end/lib/src/fasta/kernel/class_hierarchy_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/class_hierarchy_builder.dart
@@ -771,7 +771,7 @@
VariableDeclaration bParameter =
bTarget.function.positionalParameters.single;
bType = bParameter.type;
- if (!hasExplictlyTypedFormalParameter(b, 0)) {
+ if (!hasExplicitlyTypedFormalParameter(b, 0)) {
debug?.log("Giving up (type may be inferred)");
return false;
}
@@ -794,7 +794,7 @@
bool inferSetterType(KernelProcedureBuilder a, Declaration b) {
debug?.log(
- "Inferring getter types for ${fullName(a)} based on ${fullName(b)}");
+ "Inferring setter types for ${fullName(a)} based on ${fullName(b)}");
Member bTarget = b.target;
Procedure aProcedure = a.target;
VariableDeclaration aParameter =
@@ -810,7 +810,8 @@
bTarget.function.positionalParameters.single;
bType = bParameter.type;
copyParameterCovariance(a.parent, aParameter, bParameter);
- if (!hasExplictlyTypedFormalParameter(b, 0)) {
+ if (!hasExplicitlyTypedFormalParameter(b, 0) ||
+ !hasExplicitlyTypedFormalParameter(a, 0)) {
debug?.log("Giving up (type may be inferred)");
return false;
}
@@ -876,7 +877,7 @@
bTarget.function.positionalParameters.single;
// inheritedType = parameter.type;
copyFieldCovarianceFromParameter(a.parent, a.target, parameter);
- if (!hasExplictlyTypedFormalParameter(b, 0)) {
+ if (!hasExplicitlyTypedFormalParameter(b, 0)) {
debug?.log("Giving up (type may be inferred)");
return false;
}
@@ -2012,7 +2013,7 @@
inferReturnType(cls, a, type, a.hadTypesInferred, hierarchy);
}
}
- } else if (a.isSetter && !hasExplictlyTypedFormalParameter(a, 0)) {
+ } else if (a.isSetter && !hasExplicitlyTypedFormalParameter(a, 0)) {
DartType type;
if (b.isGetter) {
Procedure bTarget = b.target;
@@ -2448,11 +2449,14 @@
}
String fullName(Declaration declaration) {
- if (declaration is DelayedMember) return declaration.fullNameForErrors;
+ String suffix = declaration.isSetter ? "=" : "";
+ if (declaration is DelayedMember) {
+ return "${declaration.fullNameForErrors}$suffix";
+ }
Declaration parent = declaration.parent;
return parent == null
- ? declaration.fullNameForErrors
- : "${parent.fullNameForErrors}.${declaration.fullNameForErrors}";
+ ? "${declaration.fullNameForErrors}$suffix"
+ : "${parent.fullNameForErrors}.${declaration.fullNameForErrors}$suffix";
}
int compareNamedParameters(VariableDeclaration a, VariableDeclaration b) {
@@ -2594,7 +2598,7 @@
: true;
}
-bool hasExplictlyTypedFormalParameter(Declaration declaration, int index) {
+bool hasExplicitlyTypedFormalParameter(Declaration declaration, int index) {
assert(
declaration is KernelProcedureBuilder || declaration is DillMemberBuilder,
"${declaration.runtimeType}");
diff --git a/pkg/front_end/testcases/issue129167943.dart.hierarchy.expect b/pkg/front_end/testcases/issue129167943.dart.hierarchy.expect
index 5b7b04e..a8b24514 100644
--- a/pkg/front_end/testcases/issue129167943.dart.hierarchy.expect
+++ b/pkg/front_end/testcases/issue129167943.dart.hierarchy.expect
@@ -387,7 +387,7 @@
Object._simpleInstanceOfTrue
Object.==
interfaceSetters:
- H3.E.foo%G.foo
+ H3.E.foo=%G.foo=
H4:
Longest path to Object: 3
diff --git a/pkg/front_end/testcases/mixin_application_override.dart.hierarchy.expect b/pkg/front_end/testcases/mixin_application_override.dart.hierarchy.expect
index 426ba18..2d41275 100644
--- a/pkg/front_end/testcases/mixin_application_override.dart.hierarchy.expect
+++ b/pkg/front_end/testcases/mixin_application_override.dart.hierarchy.expect
@@ -115,7 +115,7 @@
Object.runtimeType
Object._simpleInstanceOf
Object._instanceOf
- A0.M.foo%S.foo%M.foo
+ A0.M.foo%S.foo
Object.noSuchMethod
Object._identityHashCode
Object.hashCode
@@ -128,7 +128,7 @@
Object.runtimeType
Object._simpleInstanceOf
Object._instanceOf
- A0.M.foo%S.foo%M.foo
+ A0.M.foo%S.foo
Object.noSuchMethod
Object._identityHashCode
Object.hashCode
@@ -311,7 +311,7 @@
Object.runtimeType
Object._simpleInstanceOf
Object._instanceOf
- S with M.M.foo%S.foo%M.foo
+ S with M.M.foo%S.foo
Object.noSuchMethod
Object._identityHashCode
Object.hashCode
@@ -324,7 +324,7 @@
Object.runtimeType
Object._simpleInstanceOf
Object._instanceOf
- S with M.M.foo%S.foo%M.foo
+ S with M.M.foo%S.foo
Object.noSuchMethod
Object._identityHashCode
Object.hashCode
@@ -344,7 +344,7 @@
Object.runtimeType
Object._simpleInstanceOf
Object._instanceOf
- S with M.M.foo%S.foo%M.foo
+ S with M.M.foo%S.foo
Object.noSuchMethod
Object._identityHashCode
Object.hashCode
@@ -357,7 +357,7 @@
Object.runtimeType
Object._simpleInstanceOf
Object._instanceOf
- S with M.M.foo%S.foo%M.foo
+ S with M.M.foo%S.foo
Object.noSuchMethod
Object._identityHashCode
Object.hashCode
@@ -609,7 +609,7 @@
Object.runtimeType
Object._simpleInstanceOf
Object._instanceOf
- S with M.M.foo%S.foo%M.foo
+ S with M.M.foo%S.foo
Object.noSuchMethod
Object._identityHashCode
Object.hashCode
@@ -622,7 +622,7 @@
Object.runtimeType
Object._simpleInstanceOf
Object._instanceOf
- S with M.M.foo%S.foo%M.foo
+ S with M.M.foo%S.foo
Object.noSuchMethod
Object._identityHashCode
Object.hashCode
@@ -642,7 +642,7 @@
Object.runtimeType
Object._simpleInstanceOf
Object._instanceOf
- S with M.M.foo%S.foo%M.foo
+ S with M.M.foo%S.foo
Object.noSuchMethod
Object._identityHashCode
Object.hashCode
@@ -655,7 +655,7 @@
Object.runtimeType
Object._simpleInstanceOf
Object._instanceOf
- S with M.M.foo%S.foo%M.foo
+ S with M.M.foo%S.foo
Object.noSuchMethod
Object._identityHashCode
Object.hashCode
@@ -907,7 +907,7 @@
Object.runtimeType
Object._simpleInstanceOf
Object._instanceOf
- S with M.M.foo%S.foo%M.foo
+ S with M.M.foo%S.foo
Object.noSuchMethod
Object._identityHashCode
Object.hashCode
@@ -920,7 +920,7 @@
Object.runtimeType
Object._simpleInstanceOf
Object._instanceOf
- S with M.M.foo%S.foo%M.foo
+ S with M.M.foo%S.foo
Object.noSuchMethod
Object._identityHashCode
Object.hashCode
@@ -940,7 +940,7 @@
Object.runtimeType
Object._simpleInstanceOf
Object._instanceOf
- S with M.M.foo%S.foo%M.foo
+ S with M.M.foo%S.foo
Object.noSuchMethod
Object._identityHashCode
Object.hashCode
@@ -953,7 +953,7 @@
Object.runtimeType
Object._simpleInstanceOf
Object._instanceOf
- S with M.M.foo%S.foo%M.foo
+ S with M.M.foo%S.foo
Object.noSuchMethod
Object._identityHashCode
Object.hashCode
@@ -974,7 +974,7 @@
Object.runtimeType
Object._simpleInstanceOf
Object._instanceOf
- S with M.M.foo%S.foo%M.foo
+ S with M.M.foo%S.foo
Object.noSuchMethod
Object._identityHashCode
Object.hashCode
@@ -987,7 +987,7 @@
Object.runtimeType
Object._simpleInstanceOf
Object._instanceOf
- S with M.M.foo%S.foo%M.foo
+ S with M.M.foo%S.foo
Object.noSuchMethod
Object._identityHashCode
Object.hashCode
diff --git a/pkg/front_end/testcases/override_inference_for_setters.dart b/pkg/front_end/testcases/override_inference_for_setters.dart
new file mode 100644
index 0000000..0da2cf9
--- /dev/null
+++ b/pkg/front_end/testcases/override_inference_for_setters.dart
@@ -0,0 +1,14 @@
+// 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.
+
+class B {
+ num get foo => null;
+ set foo(dynamic newFoo) {}
+}
+
+class A extends B {
+ set foo(newFoo) {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/override_inference_for_setters.dart.hierarchy.expect b/pkg/front_end/testcases/override_inference_for_setters.dart.hierarchy.expect
new file mode 100644
index 0000000..b1e3c8a
--- /dev/null
+++ b/pkg/front_end/testcases/override_inference_for_setters.dart.hierarchy.expect
@@ -0,0 +1,58 @@
+Object:
+ superclasses:
+ interfaces:
+ classMembers:
+ Object._haveSameRuntimeType
+ Object.toString
+ Object.runtimeType
+ Object._toString
+ Object._simpleInstanceOf
+ Object._hashCodeRnd
+ Object._instanceOf
+ Object.noSuchMethod
+ Object._objectHashCode
+ Object._identityHashCode
+ Object.hashCode
+ Object._simpleInstanceOfFalse
+ Object._simpleInstanceOfTrue
+ Object.==
+ classSetters:
+
+B:
+ superclasses:
+ Object
+ interfaces:
+ classMembers:
+ Object.toString
+ Object.runtimeType
+ Object._simpleInstanceOf
+ Object._instanceOf
+ B.foo
+ Object.noSuchMethod
+ Object._identityHashCode
+ Object.hashCode
+ Object._simpleInstanceOfFalse
+ Object._simpleInstanceOfTrue
+ Object.==
+ classSetters:
+ B.foo
+
+A:
+ superclasses:
+ Object
+ -> B
+ interfaces:
+ classMembers:
+ Object.toString
+ Object.runtimeType
+ Object._simpleInstanceOf
+ Object._instanceOf
+ B.foo
+ Object.noSuchMethod
+ Object._identityHashCode
+ Object.hashCode
+ Object._simpleInstanceOfFalse
+ Object._simpleInstanceOfTrue
+ Object.==
+ classSetters:
+ A.foo
diff --git a/pkg/front_end/testcases/override_inference_for_setters.dart.legacy.expect b/pkg/front_end/testcases/override_inference_for_setters.dart.legacy.expect
new file mode 100644
index 0000000..fd832da
--- /dev/null
+++ b/pkg/front_end/testcases/override_inference_for_setters.dart.legacy.expect
@@ -0,0 +1,19 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class B extends core::Object {
+ synthetic constructor •() → self::B
+ : super core::Object::•()
+ ;
+ get foo() → core::num
+ return null;
+ set foo(dynamic newFoo) → void {}
+}
+class A extends self::B {
+ synthetic constructor •() → self::A
+ : super self::B::•()
+ ;
+ set foo(dynamic newFoo) → void {}
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/override_inference_for_setters.dart.legacy.transformed.expect b/pkg/front_end/testcases/override_inference_for_setters.dart.legacy.transformed.expect
new file mode 100644
index 0000000..fd832da
--- /dev/null
+++ b/pkg/front_end/testcases/override_inference_for_setters.dart.legacy.transformed.expect
@@ -0,0 +1,19 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class B extends core::Object {
+ synthetic constructor •() → self::B
+ : super core::Object::•()
+ ;
+ get foo() → core::num
+ return null;
+ set foo(dynamic newFoo) → void {}
+}
+class A extends self::B {
+ synthetic constructor •() → self::A
+ : super self::B::•()
+ ;
+ set foo(dynamic newFoo) → void {}
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/override_inference_for_setters.dart.outline.expect b/pkg/front_end/testcases/override_inference_for_setters.dart.outline.expect
new file mode 100644
index 0000000..1c22d1f
--- /dev/null
+++ b/pkg/front_end/testcases/override_inference_for_setters.dart.outline.expect
@@ -0,0 +1,20 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class B extends core::Object {
+ synthetic constructor •() → self::B
+ ;
+ get foo() → core::num
+ ;
+ set foo(dynamic newFoo) → void
+ ;
+}
+class A extends self::B {
+ synthetic constructor •() → self::A
+ ;
+ set foo(dynamic newFoo) → void
+ ;
+}
+static method main() → dynamic
+ ;
diff --git a/pkg/front_end/testcases/override_inference_for_setters.dart.strong.expect b/pkg/front_end/testcases/override_inference_for_setters.dart.strong.expect
new file mode 100644
index 0000000..fd832da
--- /dev/null
+++ b/pkg/front_end/testcases/override_inference_for_setters.dart.strong.expect
@@ -0,0 +1,19 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class B extends core::Object {
+ synthetic constructor •() → self::B
+ : super core::Object::•()
+ ;
+ get foo() → core::num
+ return null;
+ set foo(dynamic newFoo) → void {}
+}
+class A extends self::B {
+ synthetic constructor •() → self::A
+ : super self::B::•()
+ ;
+ set foo(dynamic newFoo) → void {}
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/override_inference_for_setters.dart.strong.transformed.expect b/pkg/front_end/testcases/override_inference_for_setters.dart.strong.transformed.expect
new file mode 100644
index 0000000..fd832da
--- /dev/null
+++ b/pkg/front_end/testcases/override_inference_for_setters.dart.strong.transformed.expect
@@ -0,0 +1,19 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class B extends core::Object {
+ synthetic constructor •() → self::B
+ : super core::Object::•()
+ ;
+ get foo() → core::num
+ return null;
+ set foo(dynamic newFoo) → void {}
+}
+class A extends self::B {
+ synthetic constructor •() → self::A
+ : super self::B::•()
+ ;
+ set foo(dynamic newFoo) → void {}
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/rasta/issue_000048.dart.hierarchy.expect b/pkg/front_end/testcases/rasta/issue_000048.dart.hierarchy.expect
index 7b077f3..953dad2 100644
--- a/pkg/front_end/testcases/rasta/issue_000048.dart.hierarchy.expect
+++ b/pkg/front_end/testcases/rasta/issue_000048.dart.hierarchy.expect
@@ -67,7 +67,7 @@
Object.toString
Object.runtimeType
Object._simpleInstanceOf
- C.M1.v2%A.v2%M1.v2
+ C.M1.v2%A.v2
Object._instanceOf
Object.noSuchMethod
Object._identityHashCode
@@ -77,13 +77,13 @@
Object._simpleInstanceOfTrue
Object.==
classSetters:
- C.M1.v2%A.v2%M1.v2
+ C.M1.v2%A.v2
A.v1
interfaceMembers:
Object.toString
Object.runtimeType
Object._simpleInstanceOf
- C.M1.v2%A.v2%M1.v2
+ C.M1.v2%A.v2
Object._instanceOf
Object.noSuchMethod
Object._identityHashCode
@@ -93,5 +93,5 @@
Object._simpleInstanceOfTrue
Object.==
interfaceSetters:
- C.M1.v2%A.v2%M1.v2
+ C.M1.v2%A.v2
A.v1
diff --git a/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_field.dart.hierarchy.expect b/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_field.dart.hierarchy.expect
index edbfd6d..9a9e066 100644
--- a/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_field.dart.hierarchy.expect
+++ b/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_field.dart.hierarchy.expect
@@ -100,8 +100,8 @@
Object._simpleInstanceOfTrue
Object.==
classSetters:
- C.M.y%B.y%I.y
- C.M.x%B.x%I.x
+ C.M.y%B.y=%I.y=
+ C.M.x%B.x=%I.x=
interfaceMembers:
C.M.y%B.y%I.y
Object.toString
@@ -116,8 +116,8 @@
Object._simpleInstanceOfTrue
Object.==
interfaceSetters:
- C.M.y%B.y%I.y
- C.M.x%B.x%I.x
+ C.M.y%B.y=%I.y=
+ C.M.x%B.x=%I.x=
Comparable:
superclasses:
diff --git a/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_setter.dart.hierarchy.expect b/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_setter.dart.hierarchy.expect
index df047dc..e23589d 100644
--- a/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_setter.dart.hierarchy.expect
+++ b/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_setter.dart.hierarchy.expect
@@ -116,8 +116,8 @@
Object._simpleInstanceOfTrue
Object.==
interfaceSetters:
- C.M.y%I.y
- C.M.x%I.x
+ C.M.y=%I.y=
+ C.M.x=%I.x=
Comparable:
superclasses:
diff --git a/pkg/front_end/testcases/text_serialization.status b/pkg/front_end/testcases/text_serialization.status
index 1e7266a..820f52c 100644
--- a/pkg/front_end/testcases/text_serialization.status
+++ b/pkg/front_end/testcases/text_serialization.status
@@ -753,6 +753,7 @@
override_check_generic_method_f_bounded: TextSerializationFailure # Was: Pass
override_check_two_substitutions: TextSerializationFailure # Was: Pass
override_check_with_covariant_modifier: TypeCheckError # Issue #31620
+override_inference_for_setters: TextSerializationFailure
part_as_entry_point: TextSerializationFailure # Was: Pass
part_as_entry_point_lib: TextSerializationFailure # Was: Pass
part_not_part_of: TextSerializationFailure