Skip to content

Commit 2ea55d4

Browse files
chloestefantsovaCommit Queue
authored and
Commit Queue
committed
[cfe] Ensure reporting all supertype conflicts in extension types
Closes #53799 Part of #49731 Change-Id: Ic273541973de6377bb376f51850ec3d7d114c764 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/334180 Commit-Queue: Chloe Stefantsova <[email protected]> Reviewed-by: Johnni Winther <[email protected]>
1 parent de7e3b7 commit 2ea55d4

16 files changed

+1234
-16
lines changed

pkg/front_end/lib/src/fasta/kernel/hierarchy/hierarchy_node.dart

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,9 @@ abstract class HierarchyNodeBuilder {
6363
}
6464

6565
List<Supertype> _substSupertypes(
66-
Supertype supertype, List<Supertype> supertypes) {
67-
List<TypeParameter> typeVariables = supertype.classNode.typeParameters;
66+
TypeDeclarationType supertype, List<Supertype> supertypes) {
67+
List<TypeParameter> typeVariables =
68+
supertype.typeDeclaration.typeParameters;
6869
if (typeVariables.isEmpty) {
6970
return supertypes;
7071
}
@@ -166,7 +167,7 @@ class ClassHierarchyNodeBuilder extends HierarchyNodeBuilder {
166167
new Supertype(_hierarchy.coreTypes.objectClass, const <DartType>[]);
167168
}
168169
superclasses.setRange(0, superclasses.length - 1,
169-
_substSupertypes(supertype, supernode.superclasses));
170+
_substSupertypes(supertype.asInterfaceType, supernode.superclasses));
170171
superclasses[superclasses.length - 1] = supertype;
171172
if (!_classBuilder.libraryBuilder.isNonNullableByDefault &&
172173
supernode.classBuilder.libraryBuilder.isNonNullableByDefault) {
@@ -192,7 +193,7 @@ class ClassHierarchyNodeBuilder extends HierarchyNodeBuilder {
192193
List<Supertype> superclassInterfaces = supernode.interfaces;
193194
if (superclassInterfaces.isNotEmpty) {
194195
superclassInterfaces =
195-
_substSupertypes(supertype, superclassInterfaces);
196+
_substSupertypes(supertype.asInterfaceType, superclassInterfaces);
196197
}
197198

198199
if (directInterfaceBuilders != null) {
@@ -216,14 +217,14 @@ class ClassHierarchyNodeBuilder extends HierarchyNodeBuilder {
216217
maxInheritancePath = interfaceNode.maxInheritancePath + 1;
217218
}
218219

219-
List<Supertype> types =
220-
_substSupertypes(directInterface, interfaceNode.superclasses);
220+
List<Supertype> types = _substSupertypes(
221+
directInterface.asInterfaceType, interfaceNode.superclasses);
221222
for (int i = 0; i < types.length; i++) {
222223
_addInterface(interfaces, superclasses, types[i]);
223224
}
224225
if (interfaceNode.interfaces.isNotEmpty) {
225-
List<Supertype> types =
226-
_substSupertypes(directInterface, interfaceNode.interfaces);
226+
List<Supertype> types = _substSupertypes(
227+
directInterface.asInterfaceType, interfaceNode.interfaces);
227228
for (int i = 0; i < types.length; i++) {
228229
_addInterface(interfaces, superclasses, types[i]);
229230
}
@@ -448,14 +449,14 @@ class ExtensionTypeHierarchyNodeBuilder extends HierarchyNodeBuilder {
448449
maxInheritancePath = interfaceNode.maxInheritancePath + 1;
449450
}
450451

451-
List<Supertype> types =
452-
_substSupertypes(supertype, interfaceNode.superclasses);
452+
List<Supertype> types = _substSupertypes(
453+
supertype.asInterfaceType, interfaceNode.superclasses);
453454
for (int i = 0; i < types.length; i++) {
454455
_addSuperClass(superclasses, types[i]);
455456
}
456457
if (interfaceNode.interfaces.isNotEmpty) {
457-
List<Supertype> types =
458-
_substSupertypes(supertype, interfaceNode.interfaces);
458+
List<Supertype> types = _substSupertypes(
459+
supertype.asInterfaceType, interfaceNode.interfaces);
459460
for (int i = 0; i < types.length; i++) {
460461
_addSuperClass(superclasses, types[i]);
461462
}
@@ -476,11 +477,11 @@ class ExtensionTypeHierarchyNodeBuilder extends HierarchyNodeBuilder {
476477
for (int i = 0; i < types.length; i++) {
477478
_addSuperExtensionType(superExtensionTypes, types[i]);
478479
}
479-
if (interfaceNode.superExtensionTypes.isNotEmpty) {
480-
List<ExtensionType> types = _substSuperExtensionTypes(
481-
directInterface, interfaceNode.superExtensionTypes);
480+
if (interfaceNode.superclasses.isNotEmpty) {
481+
List<Supertype> types =
482+
_substSupertypes(directInterface, interfaceNode.superclasses);
482483
for (int i = 0; i < types.length; i++) {
483-
_addSuperExtensionType(superExtensionTypes, types[i]);
484+
_addSuperClass(superclasses, types[i]);
484485
}
485486
}
486487
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// Copyright (c) 2023, 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+
class A<X> {}
6+
class B<X> extends A<X> {}
7+
class C extends A<String> {}
8+
extension type E<X>(X it) {}
9+
10+
extension type E1(A<Never> it) implements A<String>, A<int> {} // Error.
11+
12+
extension type E2(B<Never> it) implements B<String>, A<double> {} // Error.
13+
14+
extension type E3(C it) implements C, A<num> {} // Error.
15+
16+
extension type E41(A<Never> it) implements A<String> {}
17+
extension type E42(A<Never> it) implements E41, A<int> {} // Error.
18+
19+
extension type E5(E<Never> it) implements E<String>, E<bool> {} // Error.
20+
21+
extension type E61(E<Never> it) implements E<num> {}
22+
extension type E62(E<Never> it) implements E61, E<String> {} // Error.
23+
24+
extension type E71(E<Never> it) implements E<double> {}
25+
extension type E72(E<Never> it) implements E<bool> {}
26+
extension type E73(E<Never> it) implements E71, E72 {} // Error.
Lines changed: 193 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,193 @@
1+
library;
2+
//
3+
// Problems in library:
4+
//
5+
// pkg/front_end/testcases/extension_types/issue53799.dart:10:16: Error: 'E1' can't implement both 'A<String>' and 'A<int>'
6+
// - 'A' is from 'pkg/front_end/testcases/extension_types/issue53799.dart'.
7+
// extension type E1(A<Never> it) implements A<String>, A<int> {} // Error.
8+
// ^
9+
//
10+
// pkg/front_end/testcases/extension_types/issue53799.dart:12:16: Error: 'E2' can't implement both 'A<String>' and 'A<double>'
11+
// - 'A' is from 'pkg/front_end/testcases/extension_types/issue53799.dart'.
12+
// extension type E2(B<Never> it) implements B<String>, A<double> {} // Error.
13+
// ^
14+
//
15+
// pkg/front_end/testcases/extension_types/issue53799.dart:14:16: Error: 'E3' can't implement both 'A<String>' and 'A<num>'
16+
// - 'A' is from 'pkg/front_end/testcases/extension_types/issue53799.dart'.
17+
// extension type E3(C it) implements C, A<num> {} // Error.
18+
// ^
19+
//
20+
// pkg/front_end/testcases/extension_types/issue53799.dart:17:16: Error: 'E42' can't implement both 'A<String>' and 'A<int>'
21+
// - 'A' is from 'pkg/front_end/testcases/extension_types/issue53799.dart'.
22+
// extension type E42(A<Never> it) implements E41, A<int> {} // Error.
23+
// ^
24+
//
25+
// pkg/front_end/testcases/extension_types/issue53799.dart:19:16: Error: 'E5' can't implement both 'E<String>' and 'E<bool>'
26+
// extension type E5(E<Never> it) implements E<String>, E<bool> {} // Error.
27+
// ^
28+
//
29+
// pkg/front_end/testcases/extension_types/issue53799.dart:22:16: Error: 'E62' can't implement both 'E<num>' and 'E<String>'
30+
// extension type E62(E<Never> it) implements E61, E<String> {} // Error.
31+
// ^
32+
//
33+
// pkg/front_end/testcases/extension_types/issue53799.dart:26:16: Error: 'E73' can't implement both 'E<double>' and 'E<bool>'
34+
// extension type E73(E<Never> it) implements E71, E72 {} // Error.
35+
// ^
36+
//
37+
// pkg/front_end/testcases/extension_types/issue53799.dart:14:39: Error: The implemented interface 'A<num>' must be a supertype of the representation type 'C' of extension type 'E3'.
38+
// - 'A' is from 'pkg/front_end/testcases/extension_types/issue53799.dart'.
39+
// - 'C' is from 'pkg/front_end/testcases/extension_types/issue53799.dart'.
40+
// Try changing the interface type to a supertype of 'C' or the representation type to a subtype of 'A<num>'.
41+
// extension type E3(C it) implements C, A<num> {} // Error.
42+
// ^
43+
//
44+
import self as self;
45+
import "dart:core" as core;
46+
47+
class A<X extends core::Object? = dynamic> extends core::Object {
48+
synthetic constructor •() → self::A<self::A::X%>
49+
: super core::Object::•()
50+
;
51+
}
52+
class B<X extends core::Object? = dynamic> extends self::A<self::B::X%> {
53+
synthetic constructor •() → self::B<self::B::X%>
54+
: super self::A::•()
55+
;
56+
}
57+
class C extends self::A<core::String> {
58+
synthetic constructor •() → self::C
59+
: super self::A::•()
60+
;
61+
}
62+
extension type E<X extends core::Object? = dynamic>(X% it) {
63+
abstract inline-class-member representation-field get it() → X%;
64+
constructor • = self::E|constructor#;
65+
constructor tearoff • = self::E|constructor#_#new#tearOff;
66+
}
67+
extension type E1(self::A<Never> it) implements self::A<core::String>, self::A<core::int> {
68+
abstract inline-class-member representation-field get it() → self::A<Never>;
69+
constructor • = self::E1|constructor#;
70+
constructor tearoff • = self::E1|constructor#_#new#tearOff;
71+
}
72+
extension type E2(self::B<Never> it) implements self::B<core::String>, self::A<core::double> {
73+
abstract inline-class-member representation-field get it() → self::B<Never>;
74+
constructor • = self::E2|constructor#;
75+
constructor tearoff • = self::E2|constructor#_#new#tearOff;
76+
}
77+
extension type E3(self::C it) implements self::C, self::A<core::num> {
78+
abstract inline-class-member representation-field get it() → self::C;
79+
constructor • = self::E3|constructor#;
80+
constructor tearoff • = self::E3|constructor#_#new#tearOff;
81+
}
82+
extension type E41(self::A<Never> it) implements self::A<core::String> {
83+
abstract inline-class-member representation-field get it() → self::A<Never>;
84+
constructor • = self::E41|constructor#;
85+
constructor tearoff • = self::E41|constructor#_#new#tearOff;
86+
}
87+
extension type E42(self::A<Never> it) implements self::E41 /* = self::A<Never> */, self::A<core::int> {
88+
abstract inline-class-member representation-field get it() → self::A<Never>;
89+
constructor • = self::E42|constructor#;
90+
constructor tearoff • = self::E42|constructor#_#new#tearOff;
91+
}
92+
extension type E5(self::E<Never> /* = Never */ it) implements self::E<core::String> /* = core::String */, self::E<core::bool> /* = core::bool */ {
93+
abstract inline-class-member representation-field get it() → self::E<Never> /* = Never */;
94+
constructor • = self::E5|constructor#;
95+
constructor tearoff • = self::E5|constructor#_#new#tearOff;
96+
}
97+
extension type E61(self::E<Never> /* = Never */ it) implements self::E<core::num> /* = core::num */ {
98+
abstract inline-class-member representation-field get it() → self::E<Never> /* = Never */;
99+
constructor • = self::E61|constructor#;
100+
constructor tearoff • = self::E61|constructor#_#new#tearOff;
101+
}
102+
extension type E62(self::E<Never> /* = Never */ it) implements self::E61 /* = Never */, self::E<core::String> /* = core::String */ {
103+
abstract inline-class-member representation-field get it() → self::E<Never> /* = Never */;
104+
constructor • = self::E62|constructor#;
105+
constructor tearoff • = self::E62|constructor#_#new#tearOff;
106+
}
107+
extension type E71(self::E<Never> /* = Never */ it) implements self::E<core::double> /* = core::double */ {
108+
abstract inline-class-member representation-field get it() → self::E<Never> /* = Never */;
109+
constructor • = self::E71|constructor#;
110+
constructor tearoff • = self::E71|constructor#_#new#tearOff;
111+
}
112+
extension type E72(self::E<Never> /* = Never */ it) implements self::E<core::bool> /* = core::bool */ {
113+
abstract inline-class-member representation-field get it() → self::E<Never> /* = Never */;
114+
constructor • = self::E72|constructor#;
115+
constructor tearoff • = self::E72|constructor#_#new#tearOff;
116+
}
117+
extension type E73(self::E<Never> /* = Never */ it) implements self::E71 /* = Never */, self::E72 /* = Never */ {
118+
abstract inline-class-member representation-field get it() → self::E<Never> /* = Never */;
119+
constructor • = self::E73|constructor#;
120+
constructor tearoff • = self::E73|constructor#_#new#tearOff;
121+
}
122+
static inline-class-member method E|constructor#<X extends core::Object? = dynamic>(self::E|constructor#::X% it) → self::E<self::E|constructor#::X%> /* = self::E|constructor#::X% */ {
123+
lowered final self::E<self::E|constructor#::X%> /* = self::E|constructor#::X% */ #this = it;
124+
return #this;
125+
}
126+
static inline-class-member method E|constructor#_#new#tearOff<X extends core::Object? = dynamic>(self::E|constructor#_#new#tearOff::X% it) → self::E<self::E|constructor#_#new#tearOff::X%>% /* = self::E|constructor#_#new#tearOff::X% */
127+
return self::E|constructor#<self::E|constructor#_#new#tearOff::X%>(it);
128+
static inline-class-member method E1|constructor#(self::A<Never> it) → self::E1 /* = self::A<Never> */ {
129+
lowered final self::E1 /* = self::A<Never> */ #this = it;
130+
return #this;
131+
}
132+
static inline-class-member method E1|constructor#_#new#tearOff(self::A<Never> it) → self::E1 /* = self::A<Never> */
133+
return self::E1|constructor#(it);
134+
static inline-class-member method E2|constructor#(self::B<Never> it) → self::E2 /* = self::B<Never> */ {
135+
lowered final self::E2 /* = self::B<Never> */ #this = it;
136+
return #this;
137+
}
138+
static inline-class-member method E2|constructor#_#new#tearOff(self::B<Never> it) → self::E2 /* = self::B<Never> */
139+
return self::E2|constructor#(it);
140+
static inline-class-member method E3|constructor#(self::C it) → self::E3 /* = self::C */ {
141+
lowered final self::E3 /* = self::C */ #this = it;
142+
return #this;
143+
}
144+
static inline-class-member method E3|constructor#_#new#tearOff(self::C it) → self::E3 /* = self::C */
145+
return self::E3|constructor#(it);
146+
static inline-class-member method E41|constructor#(self::A<Never> it) → self::E41 /* = self::A<Never> */ {
147+
lowered final self::E41 /* = self::A<Never> */ #this = it;
148+
return #this;
149+
}
150+
static inline-class-member method E41|constructor#_#new#tearOff(self::A<Never> it) → self::E41 /* = self::A<Never> */
151+
return self::E41|constructor#(it);
152+
static inline-class-member method E42|constructor#(self::A<Never> it) → self::E42 /* = self::A<Never> */ {
153+
lowered final self::E42 /* = self::A<Never> */ #this = it;
154+
return #this;
155+
}
156+
static inline-class-member method E42|constructor#_#new#tearOff(self::A<Never> it) → self::E42 /* = self::A<Never> */
157+
return self::E42|constructor#(it);
158+
static inline-class-member method E5|constructor#(self::E<Never> /* = Never */ it) → self::E5 /* = Never */ {
159+
lowered final self::E5 /* = Never */ #this = it;
160+
return #this;
161+
}
162+
static inline-class-member method E5|constructor#_#new#tearOff(self::E<Never> /* = Never */ it) → self::E5 /* = Never */
163+
return self::E5|constructor#(it);
164+
static inline-class-member method E61|constructor#(self::E<Never> /* = Never */ it) → self::E61 /* = Never */ {
165+
lowered final self::E61 /* = Never */ #this = it;
166+
return #this;
167+
}
168+
static inline-class-member method E61|constructor#_#new#tearOff(self::E<Never> /* = Never */ it) → self::E61 /* = Never */
169+
return self::E61|constructor#(it);
170+
static inline-class-member method E62|constructor#(self::E<Never> /* = Never */ it) → self::E62 /* = Never */ {
171+
lowered final self::E62 /* = Never */ #this = it;
172+
return #this;
173+
}
174+
static inline-class-member method E62|constructor#_#new#tearOff(self::E<Never> /* = Never */ it) → self::E62 /* = Never */
175+
return self::E62|constructor#(it);
176+
static inline-class-member method E71|constructor#(self::E<Never> /* = Never */ it) → self::E71 /* = Never */ {
177+
lowered final self::E71 /* = Never */ #this = it;
178+
return #this;
179+
}
180+
static inline-class-member method E71|constructor#_#new#tearOff(self::E<Never> /* = Never */ it) → self::E71 /* = Never */
181+
return self::E71|constructor#(it);
182+
static inline-class-member method E72|constructor#(self::E<Never> /* = Never */ it) → self::E72 /* = Never */ {
183+
lowered final self::E72 /* = Never */ #this = it;
184+
return #this;
185+
}
186+
static inline-class-member method E72|constructor#_#new#tearOff(self::E<Never> /* = Never */ it) → self::E72 /* = Never */
187+
return self::E72|constructor#(it);
188+
static inline-class-member method E73|constructor#(self::E<Never> /* = Never */ it) → self::E73 /* = Never */ {
189+
lowered final self::E73 /* = Never */ #this = it;
190+
return #this;
191+
}
192+
static inline-class-member method E73|constructor#_#new#tearOff(self::E<Never> /* = Never */ it) → self::E73 /* = Never */
193+
return self::E73|constructor#(it);

0 commit comments

Comments
 (0)