Skip to content

Commit 2e2df71

Browse files
chloestefantsovaCommit Bot
authored and
Commit Bot
committed
[cfe] Account for static members when adding noSuchMethod forwarders
Closes #48402 Change-Id: I1f7d9d15af40b1ed2b0de327031953e46f932a28 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/233300 Reviewed-by: Johnni Winther <[email protected]> Commit-Queue: Chloe Stefantsova <[email protected]>
1 parent 90997b9 commit 2e2df71

8 files changed

+428
-7
lines changed

pkg/front_end/lib/src/fasta/source/source_class_builder.dart

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1387,6 +1387,22 @@ class SourceClassBuilder extends ClassBuilderImpl
13871387
return noSuchMethod != null && noSuchMethod.enclosingClass != objectClass;
13881388
}
13891389

1390+
List<Member> _getStaticMembers() {
1391+
List<Member> staticMembers = <Member>[];
1392+
for (Field field in cls.fields) {
1393+
if (field.isStatic) {
1394+
staticMembers.add(field);
1395+
}
1396+
}
1397+
for (Procedure procedure in cls.procedures) {
1398+
if (procedure.isStatic) {
1399+
staticMembers.add(procedure);
1400+
}
1401+
}
1402+
staticMembers.sort(ClassHierarchy.compareMembers);
1403+
return staticMembers;
1404+
}
1405+
13901406
bool _addMissingNoSuchMethodForwarders(
13911407
KernelTarget target, Set<Member> existingForwarders,
13921408
{required bool forSetters}) {
@@ -1401,6 +1417,7 @@ class SourceClassBuilder extends ClassBuilderImpl
14011417
hierarchy.getDispatchTargets(cls, setters: forSetters);
14021418
List<Member> declaredMembers =
14031419
hierarchy.getDeclaredMembers(cls, setters: forSetters);
1420+
List<Member> staticMembers = _getStaticMembers();
14041421

14051422
Procedure noSuchMethod = ClassHierarchy.findMemberByName(
14061423
hierarchy.getInterfaceMembers(cls), noSuchMethodName) as Procedure;
@@ -1426,8 +1443,8 @@ class SourceClassBuilder extends ClassBuilderImpl
14261443
forSetter: forSetters);
14271444
Member? member = combinedMemberSignature.canonicalMember;
14281445
if (member != null) {
1429-
if (_isForwarderRequired(
1430-
clsHasUserDefinedNoSuchMethod, member, cls, concreteMembers,
1446+
if (_isForwarderRequired(clsHasUserDefinedNoSuchMethod, member, cls,
1447+
concreteMembers, staticMembers,
14311448
isPatch: member.fileUri != member.enclosingClass!.fileUri) &&
14321449
!existingForwarders.contains(member)) {
14331450
assert(!combinedMemberSignature.needsCovarianceMerging,
@@ -1478,12 +1495,13 @@ class SourceClassBuilder extends ClassBuilderImpl
14781495
bool superHasUserDefinedNoSuchMethod = _hasUserDefinedNoSuchMethod(
14791496
nearestConcreteSuperclass, hierarchy, target.objectClass);
14801497
{
1481-
List<Member> concrete =
1498+
List<Member> concreteMembers =
14821499
hierarchy.getDispatchTargets(nearestConcreteSuperclass);
1500+
List<Member> staticMembers = _getStaticMembers();
14831501
for (Member member
14841502
in hierarchy.getInterfaceMembers(nearestConcreteSuperclass)) {
14851503
if (_isForwarderRequired(superHasUserDefinedNoSuchMethod, member,
1486-
nearestConcreteSuperclass, concrete,
1504+
nearestConcreteSuperclass, concreteMembers, staticMembers,
14871505
isPatch: member.fileUri != member.enclosingClass!.fileUri)) {
14881506
existingForwarders.add(member);
14891507
}
@@ -1493,10 +1511,11 @@ class SourceClassBuilder extends ClassBuilderImpl
14931511
{
14941512
List<Member> concreteSetters = hierarchy
14951513
.getDispatchTargets(nearestConcreteSuperclass, setters: true);
1514+
List<Member> staticSetters = _getStaticMembers();
14961515
for (Member member in hierarchy
14971516
.getInterfaceMembers(nearestConcreteSuperclass, setters: true)) {
14981517
if (_isForwarderRequired(superHasUserDefinedNoSuchMethod, member,
1499-
nearestConcreteSuperclass, concreteSetters)) {
1518+
nearestConcreteSuperclass, concreteSetters, staticSetters)) {
15001519
existingSetterForwarders.add(member);
15011520
}
15021521
}
@@ -1522,7 +1541,7 @@ class SourceClassBuilder extends ClassBuilderImpl
15221541

15231542
/// Tells if a noSuchMethod forwarder is required for [member] in [cls].
15241543
bool _isForwarderRequired(bool hasUserDefinedNoSuchMethod, Member member,
1525-
Class cls, List<Member> concreteMembers,
1544+
Class cls, List<Member> concreteMembers, List<Member> staticMembers,
15261545
{bool isPatch = false}) {
15271546
// A noSuchMethod forwarder is allowed for an abstract member if the class
15281547
// has a user-defined noSuchMethod or if the member is private and is
@@ -1536,7 +1555,8 @@ class SourceClassBuilder extends ClassBuilderImpl
15361555
// A noSuchMethod forwarder is required if it's allowed and if there's no
15371556
// concrete implementation or a forwarder already.
15381557
bool isForwarderRequired = isForwarderAllowed &&
1539-
ClassHierarchy.findMemberByName(concreteMembers, member.name) == null;
1558+
ClassHierarchy.findMemberByName(concreteMembers, member.name) == null &&
1559+
ClassHierarchy.findMemberByName(staticMembers, member.name) == null;
15401560
return isForwarderRequired;
15411561
}
15421562

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
abstract class I {
6+
String get member1;
7+
String get procedure;
8+
void set setter(String value);
9+
void set fieldSetter(String value);
10+
void set setterVsGetter(num value);
11+
double get getterVsSetter;
12+
}
13+
14+
class A implements I {
15+
// Check for unsorted names of members.
16+
static String member5 = "member5";
17+
static String member4 = "member4";
18+
static String member3 = "member3";
19+
static String member1 = "member1"; // Error.
20+
static String member2 = "member2";
21+
22+
static void procedure() {} // Error.
23+
24+
static void set setter(String value) {} // Error.
25+
26+
static String fieldSetter = "fieldSetter"; // Error.
27+
28+
static num get setterVsGetter => 0; // Error.
29+
30+
static void set getterVsSetter(double value) {} // Error.
31+
32+
dynamic noSuchMethod(Invocation i) => "foo";
33+
}
34+
35+
main() {}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
abstract class I {
2+
String get member1;
3+
String get procedure;
4+
void set setter(String value);
5+
void set fieldSetter(String value);
6+
void set setterVsGetter(num value);
7+
double get getterVsSetter;
8+
}
9+
10+
class A implements I {
11+
static String member5 = "member5";
12+
static String member4 = "member4";
13+
static String member3 = "member3";
14+
static String member1 = "member1";
15+
static String member2 = "member2";
16+
static void procedure() {}
17+
static void set setter(String value) {}
18+
static String fieldSetter = "fieldSetter";
19+
static num get setterVsGetter => 0;
20+
static void set getterVsSetter(double value) {}
21+
dynamic noSuchMethod(Invocation i) => "foo";
22+
}
23+
24+
main() {}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
abstract class I {
2+
String get member1;
3+
String get procedure;
4+
double get getterVsSetter;
5+
void set fieldSetter(String value);
6+
void set setter(String value);
7+
void set setterVsGetter(num value);
8+
}
9+
10+
class A implements I {
11+
dynamic noSuchMethod(Invocation i) => "foo";
12+
static String fieldSetter = "fieldSetter";
13+
static String member1 = "member1";
14+
static String member2 = "member2";
15+
static String member3 = "member3";
16+
static String member4 = "member4";
17+
static String member5 = "member5";
18+
static num get setterVsGetter => 0;
19+
static void procedure() {}
20+
static void set getterVsSetter(double value) {}
21+
static void set setter(String value) {}
22+
}
23+
24+
main() {}
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
library /*isNonNullableByDefault*/;
2+
//
3+
// Problems in library:
4+
//
5+
// pkg/front_end/testcases/general/issue48402.dart:19:17: Error: Can't declare a member that conflicts with an inherited one.
6+
// static String member1 = "member1"; // Error.
7+
// ^^^^^^^
8+
// pkg/front_end/testcases/general/issue48402.dart:6:14: Context: This is the inherited member.
9+
// String get member1;
10+
// ^^^^^^^
11+
//
12+
// pkg/front_end/testcases/general/issue48402.dart:22:15: Error: Can't declare a member that conflicts with an inherited one.
13+
// static void procedure() {} // Error.
14+
// ^^^^^^^^^
15+
// pkg/front_end/testcases/general/issue48402.dart:7:14: Context: This is the inherited member.
16+
// String get procedure;
17+
// ^^^^^^^^^
18+
//
19+
// pkg/front_end/testcases/general/issue48402.dart:26:17: Error: Can't declare a member that conflicts with an inherited one.
20+
// static String fieldSetter = "fieldSetter"; // Error.
21+
// ^^^^^^^^^^^
22+
// pkg/front_end/testcases/general/issue48402.dart:9:12: Context: This is the inherited member.
23+
// void set fieldSetter(String value);
24+
// ^^^^^^^^^^^
25+
//
26+
// pkg/front_end/testcases/general/issue48402.dart:28:18: Error: Can't declare a member that conflicts with an inherited one.
27+
// static num get setterVsGetter => 0; // Error.
28+
// ^^^^^^^^^^^^^^
29+
// pkg/front_end/testcases/general/issue48402.dart:10:12: Context: This is the inherited member.
30+
// void set setterVsGetter(num value);
31+
// ^^^^^^^^^^^^^^
32+
//
33+
// pkg/front_end/testcases/general/issue48402.dart:24:19: Error: Can't declare a member that conflicts with an inherited one.
34+
// static void set setter(String value) {} // Error.
35+
// ^^^^^^
36+
// pkg/front_end/testcases/general/issue48402.dart:8:12: Context: This is the inherited member.
37+
// void set setter(String value);
38+
// ^^^^^^
39+
//
40+
// pkg/front_end/testcases/general/issue48402.dart:30:19: Error: Can't declare a member that conflicts with an inherited one.
41+
// static void set getterVsSetter(double value) {} // Error.
42+
// ^^^^^^^^^^^^^^
43+
// pkg/front_end/testcases/general/issue48402.dart:11:14: Context: This is the inherited member.
44+
// double get getterVsSetter;
45+
// ^^^^^^^^^^^^^^
46+
//
47+
import self as self;
48+
import "dart:core" as core;
49+
50+
abstract class I extends core::Object {
51+
synthetic constructor •() → self::I
52+
: super core::Object::•()
53+
;
54+
abstract get member1() → core::String;
55+
abstract get procedure() → core::String;
56+
abstract set setter(core::String value) → void;
57+
abstract set fieldSetter(core::String value) → void;
58+
abstract set setterVsGetter(core::num value) → void;
59+
abstract get getterVsSetter() → core::double;
60+
}
61+
class A extends core::Object implements self::I {
62+
static field core::String member5 = "member5";
63+
static field core::String member4 = "member4";
64+
static field core::String member3 = "member3";
65+
static field core::String member1 = "member1";
66+
static field core::String member2 = "member2";
67+
static field core::String fieldSetter = "fieldSetter";
68+
synthetic constructor •() → self::A
69+
: super core::Object::•()
70+
;
71+
static method procedure() → void {}
72+
static set setter(core::String value) → void {}
73+
static get setterVsGetter() → core::num
74+
return 0;
75+
static set getterVsSetter(core::double value) → void {}
76+
method noSuchMethod(core::Invocation i) → dynamic
77+
return "foo";
78+
}
79+
static method main() → dynamic {}
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
library /*isNonNullableByDefault*/;
2+
//
3+
// Problems in library:
4+
//
5+
// pkg/front_end/testcases/general/issue48402.dart:19:17: Error: Can't declare a member that conflicts with an inherited one.
6+
// static String member1 = "member1"; // Error.
7+
// ^^^^^^^
8+
// pkg/front_end/testcases/general/issue48402.dart:6:14: Context: This is the inherited member.
9+
// String get member1;
10+
// ^^^^^^^
11+
//
12+
// pkg/front_end/testcases/general/issue48402.dart:22:15: Error: Can't declare a member that conflicts with an inherited one.
13+
// static void procedure() {} // Error.
14+
// ^^^^^^^^^
15+
// pkg/front_end/testcases/general/issue48402.dart:7:14: Context: This is the inherited member.
16+
// String get procedure;
17+
// ^^^^^^^^^
18+
//
19+
// pkg/front_end/testcases/general/issue48402.dart:26:17: Error: Can't declare a member that conflicts with an inherited one.
20+
// static String fieldSetter = "fieldSetter"; // Error.
21+
// ^^^^^^^^^^^
22+
// pkg/front_end/testcases/general/issue48402.dart:9:12: Context: This is the inherited member.
23+
// void set fieldSetter(String value);
24+
// ^^^^^^^^^^^
25+
//
26+
// pkg/front_end/testcases/general/issue48402.dart:28:18: Error: Can't declare a member that conflicts with an inherited one.
27+
// static num get setterVsGetter => 0; // Error.
28+
// ^^^^^^^^^^^^^^
29+
// pkg/front_end/testcases/general/issue48402.dart:10:12: Context: This is the inherited member.
30+
// void set setterVsGetter(num value);
31+
// ^^^^^^^^^^^^^^
32+
//
33+
// pkg/front_end/testcases/general/issue48402.dart:24:19: Error: Can't declare a member that conflicts with an inherited one.
34+
// static void set setter(String value) {} // Error.
35+
// ^^^^^^
36+
// pkg/front_end/testcases/general/issue48402.dart:8:12: Context: This is the inherited member.
37+
// void set setter(String value);
38+
// ^^^^^^
39+
//
40+
// pkg/front_end/testcases/general/issue48402.dart:30:19: Error: Can't declare a member that conflicts with an inherited one.
41+
// static void set getterVsSetter(double value) {} // Error.
42+
// ^^^^^^^^^^^^^^
43+
// pkg/front_end/testcases/general/issue48402.dart:11:14: Context: This is the inherited member.
44+
// double get getterVsSetter;
45+
// ^^^^^^^^^^^^^^
46+
//
47+
import self as self;
48+
import "dart:core" as core;
49+
50+
abstract class I extends core::Object {
51+
synthetic constructor •() → self::I
52+
: super core::Object::•()
53+
;
54+
abstract get member1() → core::String;
55+
abstract get procedure() → core::String;
56+
abstract set setter(core::String value) → void;
57+
abstract set fieldSetter(core::String value) → void;
58+
abstract set setterVsGetter(core::num value) → void;
59+
abstract get getterVsSetter() → core::double;
60+
}
61+
class A extends core::Object implements self::I {
62+
static field core::String member5 = "member5";
63+
static field core::String member4 = "member4";
64+
static field core::String member3 = "member3";
65+
static field core::String member1 = "member1";
66+
static field core::String member2 = "member2";
67+
static field core::String fieldSetter = "fieldSetter";
68+
synthetic constructor •() → self::A
69+
: super core::Object::•()
70+
;
71+
static method procedure() → void {}
72+
static set setter(core::String value) → void {}
73+
static get setterVsGetter() → core::num
74+
return 0;
75+
static set getterVsSetter(core::double value) → void {}
76+
method noSuchMethod(core::Invocation i) → dynamic
77+
return "foo";
78+
}
79+
static method main() → dynamic {}

0 commit comments

Comments
 (0)