Skip to content

Commit c66ae00

Browse files
johnniwinthercommit-bot@chromium.org
authored andcommitted
[cfe] Handle invalid typedefs and redirecting factories in lowering
Change-Id: I61d776434621fd7022d034f17e228ec553a7ff47 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/209108 Reviewed-by: Dmitry Stefantsov <[email protected]> Commit-Queue: Johnni Winther <[email protected]>
1 parent 0f04dc6 commit c66ae00

34 files changed

+899
-112
lines changed

pkg/front_end/lib/src/fasta/kernel/constructor_tearoff_lowering.dart

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -253,7 +253,19 @@ SynthesizedFunctionNode buildRedirectingFactoryTearOffBody(
253253
FreshTypeParameters freshTypeParameters) {
254254
int fileOffset = tearOff.fileOffset;
255255

256+
List<TypeParameter> typeParameters;
257+
if (target is Constructor) {
258+
typeParameters = target.enclosingClass.typeParameters;
259+
} else {
260+
typeParameters = target.function!.typeParameters;
261+
}
262+
256263
if (!freshTypeParameters.substitution.isEmpty) {
264+
if (typeArguments.length != typeParameters.length) {
265+
// Error case: Use default types as type arguments.
266+
typeArguments = new List<DartType>.generate(typeParameters.length,
267+
(int index) => typeParameters[index].defaultType);
268+
}
257269
if (typeArguments.isNotEmpty) {
258270
// Translate [typeArgument] into the context of the synthesized procedure.
259271
typeArguments = new List<DartType>.generate(
@@ -262,14 +274,21 @@ SynthesizedFunctionNode buildRedirectingFactoryTearOffBody(
262274
.substituteType(typeArguments[index]));
263275
}
264276
}
265-
277+
Map<TypeParameter, DartType> substitutionMap;
278+
if (typeParameters.length == typeArguments.length) {
279+
substitutionMap = new Map<TypeParameter, DartType>.fromIterables(
280+
typeParameters, typeArguments);
281+
} else {
282+
// Error case: Substitute type parameters with `dynamic`.
283+
substitutionMap = new Map<TypeParameter, DartType>.fromIterables(
284+
typeParameters,
285+
new List<DartType>.generate(
286+
typeParameters.length, (int index) => const DynamicType()));
287+
}
266288
Arguments arguments = _createArguments(tearOff, typeArguments, fileOffset);
267289
_createTearOffBody(tearOff, target, arguments);
268290
return new SynthesizedFunctionNode(
269-
new Map<TypeParameter, DartType>.fromIterables(
270-
target.enclosingClass!.typeParameters, typeArguments),
271-
target.function!,
272-
tearOff.function,
291+
substitutionMap, target.function!, tearOff.function,
273292
identicalSignatures: false);
274293
}
275294

pkg/front_end/lib/src/fasta/kernel/expression_generator.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3218,8 +3218,8 @@ class TypeUseGenerator extends AbstractReadOnlyAccessGenerator {
32183218
_helper.buildDartTypeArguments(typeArguments);
32193219
}
32203220
if (isGenericTypedefTearOff) {
3221-
if (isProperRenameForClass(
3222-
_helper.typeEnvironment, aliasBuilder!.typedef)) {
3221+
if (isProperRenameForClass(_helper.typeEnvironment,
3222+
aliasBuilder!.typedef, aliasBuilder.library.library)) {
32233223
return tearOffExpression;
32243224
}
32253225
Procedure? tearOffLowering =

pkg/front_end/lib/src/fasta/kernel/expression_generator_helper.dart

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ import 'kernel_ast_api.dart'
3333
FunctionNode,
3434
Initializer,
3535
InterfaceType,
36+
Library,
3637
Member,
3738
Name,
3839
Procedure,
@@ -186,7 +187,8 @@ abstract class ExpressionGeneratorHelper implements InferenceHelper {
186187
}
187188

188189
/// Checks that a generic [typedef] for a generic class.
189-
bool isProperRenameForClass(TypeEnvironment typeEnvironment, Typedef typedef) {
190+
bool isProperRenameForClass(
191+
TypeEnvironment typeEnvironment, Typedef typedef, Library typedefLibrary) {
190192
DartType? rhsType = typedef.type;
191193
if (rhsType is! InterfaceType) {
192194
return false;
@@ -201,7 +203,7 @@ bool isProperRenameForClass(TypeEnvironment typeEnvironment, Typedef typedef) {
201203
for (int i = 0; i < fromParameters.length; ++i) {
202204
if (typeArguments[i] !=
203205
new TypeParameterType.withDefaultNullabilityForLibrary(
204-
fromParameters[i], typedef.enclosingLibrary)) {
206+
fromParameters[i], typedefLibrary)) {
205207
return false;
206208
}
207209
}

pkg/front_end/lib/src/fasta/kernel/kernel_helper.dart

Lines changed: 39 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -59,32 +59,54 @@ class SynthesizedFunctionNode {
5959

6060
// For mixin application constructors, the argument count is the same, but
6161
// for redirecting tear off lowerings, the argument count of the tear off
62-
// can be less than that of the redirection target.
63-
64-
assert(_synthesized.positionalParameters.length <=
65-
_original.positionalParameters.length);
66-
for (int i = 0; i < _synthesized.positionalParameters.length; i++) {
67-
cloneInitializer(_original.positionalParameters[i],
68-
_synthesized.positionalParameters[i]);
69-
}
62+
// can be less than that of the redirection target or, in errors cases, be
63+
// unrelated.
7064

7165
if (identicalSignatures) {
66+
assert(_synthesized.positionalParameters.length ==
67+
_original.positionalParameters.length);
68+
for (int i = 0; i < _synthesized.positionalParameters.length; i++) {
69+
cloneInitializer(_original.positionalParameters[i],
70+
_synthesized.positionalParameters[i]);
71+
}
7272
assert(_synthesized.namedParameters.length ==
7373
_original.namedParameters.length);
7474
for (int i = 0; i < _synthesized.namedParameters.length; i++) {
7575
cloneInitializer(
7676
_original.namedParameters[i], _synthesized.namedParameters[i]);
7777
}
78-
} else if (_synthesized.namedParameters.isNotEmpty) {
79-
Map<String, VariableDeclaration> originalParameters = {};
80-
for (int i = 0; i < _original.namedParameters.length; i++) {
81-
originalParameters[_original.namedParameters[i].name!] =
82-
_original.namedParameters[i];
78+
} else {
79+
for (int i = 0; i < _synthesized.positionalParameters.length; i++) {
80+
VariableDeclaration synthesizedParameter =
81+
_synthesized.positionalParameters[i];
82+
if (i < _original.positionalParameters.length) {
83+
cloneInitializer(
84+
_original.positionalParameters[i], synthesizedParameter);
85+
} else {
86+
// Error case: use `null` as initializer.
87+
synthesizedParameter.initializer = new NullLiteral()
88+
..parent = synthesizedParameter;
89+
}
8390
}
84-
for (int i = 0; i < _synthesized.namedParameters.length; i++) {
85-
cloneInitializer(
86-
originalParameters[_synthesized.namedParameters[i].name!]!,
87-
_synthesized.namedParameters[i]);
91+
if (_synthesized.namedParameters.isNotEmpty) {
92+
Map<String, VariableDeclaration> originalParameters = {};
93+
for (int i = 0; i < _original.namedParameters.length; i++) {
94+
originalParameters[_original.namedParameters[i].name!] =
95+
_original.namedParameters[i];
96+
}
97+
for (int i = 0; i < _synthesized.namedParameters.length; i++) {
98+
VariableDeclaration synthesizedParameter =
99+
_synthesized.namedParameters[i];
100+
VariableDeclaration? originalParameter =
101+
originalParameters[synthesizedParameter.name!];
102+
if (originalParameter != null) {
103+
cloneInitializer(originalParameter, synthesizedParameter);
104+
} else {
105+
// Error case: use `null` as initializer.
106+
synthesizedParameter.initializer = new NullLiteral()
107+
..parent = synthesizedParameter;
108+
}
109+
}
88110
}
89111
}
90112
}

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -282,7 +282,8 @@ class SourceTypeAliasBuilder extends TypeAliasBuilderImpl {
282282
if (declaration is ClassBuilder &&
283283
targetType is InterfaceType &&
284284
typedef.typeParameters.isNotEmpty &&
285-
!isProperRenameForClass(library.loader.typeEnvironment, typedef)) {
285+
!isProperRenameForClass(
286+
library.loader.typeEnvironment, typedef, library.library)) {
286287
tearOffs = {};
287288
_tearOffDependencies = {};
288289
declaration

pkg/front_end/test/spell_checking_list_tests.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,8 @@ c6c
144144
c7a
145145
c8a
146146
c8b
147+
c8c
148+
c8d
147149
ca
148150
cafebabe
149151
calloc
@@ -386,6 +388,7 @@ f6a
386388
f6b
387389
f7a
388390
f8a
391+
f8b
389392
fac
390393
faking
391394
falling
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// Copyright (c) 2021, 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+
// From co19/Language/Types/Type_Aliases/scope_t02
6+
7+
class A {}
8+
9+
class C<T> {}
10+
11+
typedef AAlias = A;
12+
typedef CAlias<T> = C<T>;
13+
14+
typedef AAlias = A; // error
15+
typedef AAlias = C<String>; // error
16+
typedef CAlias<T> = C<T>; // error
17+
typedef CAlias = C<String>; // error
18+
typedef CAlias<T1, T2> = C<T1>; // error
19+
20+
main() {}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
library /*isNonNullableByDefault*/;
2+
//
3+
// Problems in library:
4+
//
5+
// pkg/front_end/testcases/constructor_tearoffs/lowering/duplicate_typedefs.dart:14:9: Error: 'AAlias' is already declared in this scope.
6+
// typedef AAlias = A; // error
7+
// ^^^^^^
8+
// pkg/front_end/testcases/constructor_tearoffs/lowering/duplicate_typedefs.dart:11:9: Context: Previous declaration of 'AAlias'.
9+
// typedef AAlias = A;
10+
// ^^^^^^
11+
//
12+
// pkg/front_end/testcases/constructor_tearoffs/lowering/duplicate_typedefs.dart:15:9: Error: 'AAlias' is already declared in this scope.
13+
// typedef AAlias = C<String>; // error
14+
// ^^^^^^
15+
// pkg/front_end/testcases/constructor_tearoffs/lowering/duplicate_typedefs.dart:14:9: Context: Previous declaration of 'AAlias'.
16+
// typedef AAlias = A; // error
17+
// ^^^^^^
18+
//
19+
// pkg/front_end/testcases/constructor_tearoffs/lowering/duplicate_typedefs.dart:16:9: Error: 'CAlias' is already declared in this scope.
20+
// typedef CAlias<T> = C<T>; // error
21+
// ^^^^^^
22+
// pkg/front_end/testcases/constructor_tearoffs/lowering/duplicate_typedefs.dart:12:9: Context: Previous declaration of 'CAlias'.
23+
// typedef CAlias<T> = C<T>;
24+
// ^^^^^^
25+
//
26+
// pkg/front_end/testcases/constructor_tearoffs/lowering/duplicate_typedefs.dart:17:9: Error: 'CAlias' is already declared in this scope.
27+
// typedef CAlias = C<String>; // error
28+
// ^^^^^^
29+
// pkg/front_end/testcases/constructor_tearoffs/lowering/duplicate_typedefs.dart:16:9: Context: Previous declaration of 'CAlias'.
30+
// typedef CAlias<T> = C<T>; // error
31+
// ^^^^^^
32+
//
33+
// pkg/front_end/testcases/constructor_tearoffs/lowering/duplicate_typedefs.dart:18:9: Error: 'CAlias' is already declared in this scope.
34+
// typedef CAlias<T1, T2> = C<T1>; // error
35+
// ^^^^^^
36+
// pkg/front_end/testcases/constructor_tearoffs/lowering/duplicate_typedefs.dart:17:9: Context: Previous declaration of 'CAlias'.
37+
// typedef CAlias = C<String>; // error
38+
// ^^^^^^
39+
//
40+
import self as self;
41+
import "dart:core" as core;
42+
43+
typedef AAlias = self::A;
44+
typedef CAlias<T extends core::Object? = dynamic> = self::C<T%>;
45+
class A extends core::Object {
46+
synthetic constructor •() → self::A
47+
: super core::Object::•()
48+
;
49+
static method _#new#tearOff() → self::A
50+
return new self::A::•();
51+
}
52+
class C<T extends core::Object? = dynamic> extends core::Object {
53+
synthetic constructor •() → self::C<self::C::T%>
54+
: super core::Object::•()
55+
;
56+
static method _#new#tearOff<T extends core::Object? = dynamic>() → self::C<self::C::_#new#tearOff::T%>
57+
return new self::C::•<self::C::_#new#tearOff::T%>();
58+
}
59+
static method main() → dynamic {}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
library /*isNonNullableByDefault*/;
2+
//
3+
// Problems in library:
4+
//
5+
// pkg/front_end/testcases/constructor_tearoffs/lowering/duplicate_typedefs.dart:14:9: Error: 'AAlias' is already declared in this scope.
6+
// typedef AAlias = A; // error
7+
// ^^^^^^
8+
// pkg/front_end/testcases/constructor_tearoffs/lowering/duplicate_typedefs.dart:11:9: Context: Previous declaration of 'AAlias'.
9+
// typedef AAlias = A;
10+
// ^^^^^^
11+
//
12+
// pkg/front_end/testcases/constructor_tearoffs/lowering/duplicate_typedefs.dart:15:9: Error: 'AAlias' is already declared in this scope.
13+
// typedef AAlias = C<String>; // error
14+
// ^^^^^^
15+
// pkg/front_end/testcases/constructor_tearoffs/lowering/duplicate_typedefs.dart:14:9: Context: Previous declaration of 'AAlias'.
16+
// typedef AAlias = A; // error
17+
// ^^^^^^
18+
//
19+
// pkg/front_end/testcases/constructor_tearoffs/lowering/duplicate_typedefs.dart:16:9: Error: 'CAlias' is already declared in this scope.
20+
// typedef CAlias<T> = C<T>; // error
21+
// ^^^^^^
22+
// pkg/front_end/testcases/constructor_tearoffs/lowering/duplicate_typedefs.dart:12:9: Context: Previous declaration of 'CAlias'.
23+
// typedef CAlias<T> = C<T>;
24+
// ^^^^^^
25+
//
26+
// pkg/front_end/testcases/constructor_tearoffs/lowering/duplicate_typedefs.dart:17:9: Error: 'CAlias' is already declared in this scope.
27+
// typedef CAlias = C<String>; // error
28+
// ^^^^^^
29+
// pkg/front_end/testcases/constructor_tearoffs/lowering/duplicate_typedefs.dart:16:9: Context: Previous declaration of 'CAlias'.
30+
// typedef CAlias<T> = C<T>; // error
31+
// ^^^^^^
32+
//
33+
// pkg/front_end/testcases/constructor_tearoffs/lowering/duplicate_typedefs.dart:18:9: Error: 'CAlias' is already declared in this scope.
34+
// typedef CAlias<T1, T2> = C<T1>; // error
35+
// ^^^^^^
36+
// pkg/front_end/testcases/constructor_tearoffs/lowering/duplicate_typedefs.dart:17:9: Context: Previous declaration of 'CAlias'.
37+
// typedef CAlias = C<String>; // error
38+
// ^^^^^^
39+
//
40+
import self as self;
41+
import "dart:core" as core;
42+
43+
typedef AAlias = self::A;
44+
typedef CAlias<T extends core::Object? = dynamic> = self::C<T%>;
45+
class A extends core::Object {
46+
synthetic constructor •() → self::A
47+
: super core::Object::•()
48+
;
49+
static method _#new#tearOff() → self::A
50+
return new self::A::•();
51+
}
52+
class C<T extends core::Object? = dynamic> extends core::Object {
53+
synthetic constructor •() → self::C<self::C::T%>
54+
: super core::Object::•()
55+
;
56+
static method _#new#tearOff<T extends core::Object? = dynamic>() → self::C<self::C::_#new#tearOff::T%>
57+
return new self::C::•<self::C::_#new#tearOff::T%>();
58+
}
59+
static method main() → dynamic {}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
class A {}
2+
3+
class C<T> {}
4+
5+
typedef AAlias = A;
6+
typedef CAlias<T> = C<T>;
7+
typedef AAlias = A;
8+
typedef AAlias = C<String>;
9+
typedef CAlias<T> = C<T>;
10+
typedef CAlias = C<String>;
11+
typedef CAlias<T1, T2> = C<T1>;
12+
main() {}

0 commit comments

Comments
 (0)