Skip to content

Commit f9d6d89

Browse files
jensjohaCommit Queue
authored andcommitted
[CFE] Fix crash on type parameters on constructors in extension types
Change-Id: Icbab9924a69a965e2cb75a73d50cbfc95a2354d7 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/397160 Commit-Queue: Jens Johansen <[email protected]> Reviewed-by: Johnni Winther <[email protected]>
1 parent 5d70261 commit f9d6d89

8 files changed

+658
-9
lines changed

pkg/front_end/lib/src/source/source_builder_factory.dart

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1369,15 +1369,13 @@ class BuilderFactoryImpl implements BuilderFactory, BuilderFactoryResult {
13691369
instanceTypeParameterAccess:
13701370
InstanceTypeParameterAccessState.Allowed);
13711371

1372-
if (nominalVariableCopy != null) {
1373-
if (typeParameters != null) {
1374-
// Coverage-ignore-block(suite): Not run.
1375-
typeParameters = nominalVariableCopy.newParameterBuilders
1376-
..addAll(typeParameters);
1377-
} else {
1378-
typeParameters = nominalVariableCopy.newParameterBuilders;
1379-
}
1380-
}
1372+
// Discard type parameters declared on the constructor. It's not
1373+
// allowed, an error has already been issued and it will cause
1374+
// crashes later if they are kept/added to the ones from the parent.
1375+
// TODO(johnniwinther): This will cause us issuing errors about not
1376+
// knowing the names of what we discard here. Is there a way to
1377+
// preserve them?
1378+
typeParameters = nominalVariableCopy?.newParameterBuilders;
13811379
case ClassFragment():
13821380
case MixinFragment():
13831381
case EnumFragment():
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// Copyright (c) 2024, 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+
extension type FooOK<T>(int foo) {
6+
FooOK.bar(T theFoo) : foo = theFoo as int;
7+
}
8+
9+
extension type FooBad1(int foo) {
10+
FooBad1.bar<T>(T theFoo) : foo = theFoo as int;
11+
}
12+
13+
extension type FooBad2<T1>(int foo) {
14+
FooBad2.bar<T2>(T1 theFoo1, T2 theFoo2) : foo = (theFoo1 as int) + (theFoo2 as int);
15+
}
16+
17+
extension type FooBad3<T1>(int foo) {
18+
FooBad3.bar<T2, T3>(T1 theFoo1, T2 theFoo2, T3 theFoo3) : foo = (theFoo1 as int) + (theFoo2 as int) + (theFoo3 as int);
19+
}
20+
21+
extension type FooBad4<T1, T2>(int foo) {
22+
FooBad4.bar<T3>(T1 theFoo1, T2 theFoo2, T3 theFoo3) : foo = (theFoo1 as int) + (theFoo2 as int) + (theFoo3 as int);
23+
}
Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
library;
2+
//
3+
// Problems in library:
4+
//
5+
// pkg/front_end/testcases/regress/annotation_on_type_parameter_name_extension_type_constructor.dart:10:14: Error: Constructors can't have type parameters.
6+
// Try removing the type parameters.
7+
// FooBad1.bar<T>(T theFoo) : foo = theFoo as int;
8+
// ^^^
9+
//
10+
// pkg/front_end/testcases/regress/annotation_on_type_parameter_name_extension_type_constructor.dart:14:14: Error: Constructors can't have type parameters.
11+
// Try removing the type parameters.
12+
// FooBad2.bar<T2>(T1 theFoo1, T2 theFoo2) : foo = (theFoo1 as int) + (theFoo2 as int);
13+
// ^^^^
14+
//
15+
// pkg/front_end/testcases/regress/annotation_on_type_parameter_name_extension_type_constructor.dart:18:14: Error: Constructors can't have type parameters.
16+
// Try removing the type parameters.
17+
// FooBad3.bar<T2, T3>(T1 theFoo1, T2 theFoo2, T3 theFoo3) : foo = (theFoo1 as int) + (theFoo2 as int) + (theFoo3 as int);
18+
// ^^^^^^^^
19+
//
20+
// pkg/front_end/testcases/regress/annotation_on_type_parameter_name_extension_type_constructor.dart:22:14: Error: Constructors can't have type parameters.
21+
// Try removing the type parameters.
22+
// FooBad4.bar<T3>(T1 theFoo1, T2 theFoo2, T3 theFoo3) : foo = (theFoo1 as int) + (theFoo2 as int) + (theFoo3 as int);
23+
// ^^^^
24+
//
25+
// pkg/front_end/testcases/regress/annotation_on_type_parameter_name_extension_type_constructor.dart:10:18: Error: Type 'T' not found.
26+
// FooBad1.bar<T>(T theFoo) : foo = theFoo as int;
27+
// ^
28+
//
29+
// pkg/front_end/testcases/regress/annotation_on_type_parameter_name_extension_type_constructor.dart:14:31: Error: Type 'T2' not found.
30+
// FooBad2.bar<T2>(T1 theFoo1, T2 theFoo2) : foo = (theFoo1 as int) + (theFoo2 as int);
31+
// ^^
32+
//
33+
// pkg/front_end/testcases/regress/annotation_on_type_parameter_name_extension_type_constructor.dart:18:35: Error: Type 'T2' not found.
34+
// FooBad3.bar<T2, T3>(T1 theFoo1, T2 theFoo2, T3 theFoo3) : foo = (theFoo1 as int) + (theFoo2 as int) + (theFoo3 as int);
35+
// ^^
36+
//
37+
// pkg/front_end/testcases/regress/annotation_on_type_parameter_name_extension_type_constructor.dart:18:47: Error: Type 'T3' not found.
38+
// FooBad3.bar<T2, T3>(T1 theFoo1, T2 theFoo2, T3 theFoo3) : foo = (theFoo1 as int) + (theFoo2 as int) + (theFoo3 as int);
39+
// ^^
40+
//
41+
// pkg/front_end/testcases/regress/annotation_on_type_parameter_name_extension_type_constructor.dart:22:43: Error: Type 'T3' not found.
42+
// FooBad4.bar<T3>(T1 theFoo1, T2 theFoo2, T3 theFoo3) : foo = (theFoo1 as int) + (theFoo2 as int) + (theFoo3 as int);
43+
// ^^
44+
//
45+
// pkg/front_end/testcases/regress/annotation_on_type_parameter_name_extension_type_constructor.dart:10:18: Error: 'T' isn't a type.
46+
// FooBad1.bar<T>(T theFoo) : foo = theFoo as int;
47+
// ^
48+
//
49+
// pkg/front_end/testcases/regress/annotation_on_type_parameter_name_extension_type_constructor.dart:14:31: Error: 'T2' isn't a type.
50+
// FooBad2.bar<T2>(T1 theFoo1, T2 theFoo2) : foo = (theFoo1 as int) + (theFoo2 as int);
51+
// ^^
52+
//
53+
// pkg/front_end/testcases/regress/annotation_on_type_parameter_name_extension_type_constructor.dart:18:35: Error: 'T2' isn't a type.
54+
// FooBad3.bar<T2, T3>(T1 theFoo1, T2 theFoo2, T3 theFoo3) : foo = (theFoo1 as int) + (theFoo2 as int) + (theFoo3 as int);
55+
// ^^
56+
//
57+
// pkg/front_end/testcases/regress/annotation_on_type_parameter_name_extension_type_constructor.dart:18:47: Error: 'T3' isn't a type.
58+
// FooBad3.bar<T2, T3>(T1 theFoo1, T2 theFoo2, T3 theFoo3) : foo = (theFoo1 as int) + (theFoo2 as int) + (theFoo3 as int);
59+
// ^^
60+
//
61+
// pkg/front_end/testcases/regress/annotation_on_type_parameter_name_extension_type_constructor.dart:22:43: Error: 'T3' isn't a type.
62+
// FooBad4.bar<T3>(T1 theFoo1, T2 theFoo2, T3 theFoo3) : foo = (theFoo1 as int) + (theFoo2 as int) + (theFoo3 as int);
63+
// ^^
64+
//
65+
import self as self;
66+
import "dart:core" as core;
67+
68+
extension type FooOK<T extends core::Object? = dynamic>(core::int foo) {
69+
abstract extension-type-member representation-field get foo() → core::int;
70+
constructor • = self::FooOK|constructor#;
71+
constructor tearoff • = self::FooOK|constructor#_#new#tearOff;
72+
constructor bar = self::FooOK|constructor#bar;
73+
constructor tearoff bar = self::FooOK|constructor#_#bar#tearOff;
74+
}
75+
extension type FooBad1(core::int foo) {
76+
abstract extension-type-member representation-field get foo() → core::int;
77+
constructor • = self::FooBad1|constructor#;
78+
constructor tearoff • = self::FooBad1|constructor#_#new#tearOff;
79+
constructor bar = self::FooBad1|constructor#bar;
80+
constructor tearoff bar = self::FooBad1|constructor#_#bar#tearOff;
81+
}
82+
extension type FooBad2<T1 extends core::Object? = dynamic>(core::int foo) {
83+
abstract extension-type-member representation-field get foo() → core::int;
84+
constructor • = self::FooBad2|constructor#;
85+
constructor tearoff • = self::FooBad2|constructor#_#new#tearOff;
86+
constructor bar = self::FooBad2|constructor#bar;
87+
constructor tearoff bar = self::FooBad2|constructor#_#bar#tearOff;
88+
}
89+
extension type FooBad3<T1 extends core::Object? = dynamic>(core::int foo) {
90+
abstract extension-type-member representation-field get foo() → core::int;
91+
constructor • = self::FooBad3|constructor#;
92+
constructor tearoff • = self::FooBad3|constructor#_#new#tearOff;
93+
constructor bar = self::FooBad3|constructor#bar;
94+
constructor tearoff bar = self::FooBad3|constructor#_#bar#tearOff;
95+
}
96+
extension type FooBad4<T1 extends core::Object? = dynamic, T2 extends core::Object? = dynamic>(core::int foo) {
97+
abstract extension-type-member representation-field get foo() → core::int;
98+
constructor • = self::FooBad4|constructor#;
99+
constructor tearoff • = self::FooBad4|constructor#_#new#tearOff;
100+
constructor bar = self::FooBad4|constructor#bar;
101+
constructor tearoff bar = self::FooBad4|constructor#_#bar#tearOff;
102+
}
103+
static extension-type-member method FooOK|constructor#<T extends core::Object? = dynamic>(core::int foo) → self::FooOK<self::FooOK|constructor#::T%>% /* erasure=core::int, declared=! */ {
104+
lowered final self::FooOK<self::FooOK|constructor#::T%>% /* erasure=core::int, declared=! */ #this = foo;
105+
return #this;
106+
}
107+
static extension-type-member method FooOK|constructor#_#new#tearOff<T extends core::Object? = dynamic>(core::int foo) → self::FooOK<self::FooOK|constructor#_#new#tearOff::T%>% /* erasure=core::int, declared=! */
108+
return self::FooOK|constructor#<self::FooOK|constructor#_#new#tearOff::T%>(foo);
109+
static extension-type-member method FooOK|constructor#bar<T extends core::Object? = dynamic>(self::FooOK|constructor#bar::T% theFoo) → self::FooOK<self::FooOK|constructor#bar::T%>% /* erasure=core::int, declared=! */ {
110+
lowered final self::FooOK<self::FooOK|constructor#bar::T%>% /* erasure=core::int, declared=! */ #this = theFoo as core::int;
111+
return #this;
112+
}
113+
static extension-type-member method FooOK|constructor#_#bar#tearOff<T extends core::Object? = dynamic>(self::FooOK|constructor#_#bar#tearOff::T% theFoo) → self::FooOK<self::FooOK|constructor#_#bar#tearOff::T%>% /* erasure=core::int, declared=! */
114+
return self::FooOK|constructor#bar<self::FooOK|constructor#_#bar#tearOff::T%>(theFoo);
115+
static extension-type-member method FooBad1|constructor#(core::int foo) → self::FooBad1% /* erasure=core::int, declared=! */ {
116+
lowered final self::FooBad1% /* erasure=core::int, declared=! */ #this = foo;
117+
return #this;
118+
}
119+
static extension-type-member method FooBad1|constructor#_#new#tearOff(core::int foo) → self::FooBad1% /* erasure=core::int, declared=! */
120+
return self::FooBad1|constructor#(foo);
121+
static extension-type-member method FooBad1|constructor#bar(invalid-type theFoo) → self::FooBad1% /* erasure=core::int, declared=! */ {
122+
lowered final self::FooBad1% /* erasure=core::int, declared=! */ #this = theFoo as core::int;
123+
return #this;
124+
}
125+
static extension-type-member method FooBad1|constructor#_#bar#tearOff(invalid-type theFoo) → self::FooBad1% /* erasure=core::int, declared=! */
126+
return self::FooBad1|constructor#bar(theFoo);
127+
static extension-type-member method FooBad2|constructor#<T1 extends core::Object? = dynamic>(core::int foo) → self::FooBad2<self::FooBad2|constructor#::T1%>% /* erasure=core::int, declared=! */ {
128+
lowered final self::FooBad2<self::FooBad2|constructor#::T1%>% /* erasure=core::int, declared=! */ #this = foo;
129+
return #this;
130+
}
131+
static extension-type-member method FooBad2|constructor#_#new#tearOff<T1 extends core::Object? = dynamic>(core::int foo) → self::FooBad2<self::FooBad2|constructor#_#new#tearOff::T1%>% /* erasure=core::int, declared=! */
132+
return self::FooBad2|constructor#<self::FooBad2|constructor#_#new#tearOff::T1%>(foo);
133+
static extension-type-member method FooBad2|constructor#bar<T1 extends core::Object? = dynamic>(self::FooBad2|constructor#bar::T1% theFoo1, invalid-type theFoo2) → self::FooBad2<self::FooBad2|constructor#bar::T1%>% /* erasure=core::int, declared=! */ {
134+
lowered final self::FooBad2<self::FooBad2|constructor#bar::T1%>% /* erasure=core::int, declared=! */ #this = (theFoo1 as core::int).{core::num::+}(theFoo2 as core::int){(core::num) → core::int};
135+
return #this;
136+
}
137+
static extension-type-member method FooBad2|constructor#_#bar#tearOff<T1 extends core::Object? = dynamic>(self::FooBad2|constructor#_#bar#tearOff::T1% theFoo1, invalid-type theFoo2) → self::FooBad2<self::FooBad2|constructor#_#bar#tearOff::T1%>% /* erasure=core::int, declared=! */
138+
return self::FooBad2|constructor#bar<self::FooBad2|constructor#_#bar#tearOff::T1%>(theFoo1, theFoo2);
139+
static extension-type-member method FooBad3|constructor#<T1 extends core::Object? = dynamic>(core::int foo) → self::FooBad3<self::FooBad3|constructor#::T1%>% /* erasure=core::int, declared=! */ {
140+
lowered final self::FooBad3<self::FooBad3|constructor#::T1%>% /* erasure=core::int, declared=! */ #this = foo;
141+
return #this;
142+
}
143+
static extension-type-member method FooBad3|constructor#_#new#tearOff<T1 extends core::Object? = dynamic>(core::int foo) → self::FooBad3<self::FooBad3|constructor#_#new#tearOff::T1%>% /* erasure=core::int, declared=! */
144+
return self::FooBad3|constructor#<self::FooBad3|constructor#_#new#tearOff::T1%>(foo);
145+
static extension-type-member method FooBad3|constructor#bar<T1 extends core::Object? = dynamic>(self::FooBad3|constructor#bar::T1% theFoo1, invalid-type theFoo2, invalid-type theFoo3) → self::FooBad3<self::FooBad3|constructor#bar::T1%>% /* erasure=core::int, declared=! */ {
146+
lowered final self::FooBad3<self::FooBad3|constructor#bar::T1%>% /* erasure=core::int, declared=! */ #this = (theFoo1 as core::int).{core::num::+}(theFoo2 as core::int){(core::num) → core::int}.{core::num::+}(theFoo3 as core::int){(core::num) → core::int};
147+
return #this;
148+
}
149+
static extension-type-member method FooBad3|constructor#_#bar#tearOff<T1 extends core::Object? = dynamic>(self::FooBad3|constructor#_#bar#tearOff::T1% theFoo1, invalid-type theFoo2, invalid-type theFoo3) → self::FooBad3<self::FooBad3|constructor#_#bar#tearOff::T1%>% /* erasure=core::int, declared=! */
150+
return self::FooBad3|constructor#bar<self::FooBad3|constructor#_#bar#tearOff::T1%>(theFoo1, theFoo2, theFoo3);
151+
static extension-type-member method FooBad4|constructor#<T1 extends core::Object? = dynamic, T2 extends core::Object? = dynamic>(core::int foo) → self::FooBad4<self::FooBad4|constructor#::T1%, self::FooBad4|constructor#::T2%>% /* erasure=core::int, declared=! */ {
152+
lowered final self::FooBad4<self::FooBad4|constructor#::T1%, self::FooBad4|constructor#::T2%>% /* erasure=core::int, declared=! */ #this = foo;
153+
return #this;
154+
}
155+
static extension-type-member method FooBad4|constructor#_#new#tearOff<T1 extends core::Object? = dynamic, T2 extends core::Object? = dynamic>(core::int foo) → self::FooBad4<self::FooBad4|constructor#_#new#tearOff::T1%, self::FooBad4|constructor#_#new#tearOff::T2%>% /* erasure=core::int, declared=! */
156+
return self::FooBad4|constructor#<self::FooBad4|constructor#_#new#tearOff::T1%, self::FooBad4|constructor#_#new#tearOff::T2%>(foo);
157+
static extension-type-member method FooBad4|constructor#bar<T1 extends core::Object? = dynamic, T2 extends core::Object? = dynamic>(self::FooBad4|constructor#bar::T1% theFoo1, self::FooBad4|constructor#bar::T2% theFoo2, invalid-type theFoo3) → self::FooBad4<self::FooBad4|constructor#bar::T1%, self::FooBad4|constructor#bar::T2%>% /* erasure=core::int, declared=! */ {
158+
lowered final self::FooBad4<self::FooBad4|constructor#bar::T1%, self::FooBad4|constructor#bar::T2%>% /* erasure=core::int, declared=! */ #this = (theFoo1 as core::int).{core::num::+}(theFoo2 as core::int){(core::num) → core::int}.{core::num::+}(theFoo3 as core::int){(core::num) → core::int};
159+
return #this;
160+
}
161+
static extension-type-member method FooBad4|constructor#_#bar#tearOff<T1 extends core::Object? = dynamic, T2 extends core::Object? = dynamic>(self::FooBad4|constructor#_#bar#tearOff::T1% theFoo1, self::FooBad4|constructor#_#bar#tearOff::T2% theFoo2, invalid-type theFoo3) → self::FooBad4<self::FooBad4|constructor#_#bar#tearOff::T1%, self::FooBad4|constructor#_#bar#tearOff::T2%>% /* erasure=core::int, declared=! */
162+
return self::FooBad4|constructor#bar<self::FooBad4|constructor#_#bar#tearOff::T1%, self::FooBad4|constructor#_#bar#tearOff::T2%>(theFoo1, theFoo2, theFoo3);

0 commit comments

Comments
 (0)