Skip to content

Commit ff2be51

Browse files
Dmitry Stefantsovcommit-bot@chromium.org
authored andcommitted
[cfe] Generate TypedefTearOff nodes on the output
Change-Id: I4b4a25137bffb0fa284a94908b05fef9b9e5c5da Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/206370 Commit-Queue: Johnni Winther <[email protected]> Reviewed-by: Johnni Winther <[email protected]>
1 parent 298777c commit ff2be51

14 files changed

+231
-115
lines changed

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

Lines changed: 41 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import 'package:_fe_analyzer_shared/src/parser/parser.dart'
1111
import 'package:_fe_analyzer_shared/src/scanner/token.dart' show Token;
1212

1313
import 'package:kernel/ast.dart';
14+
import 'package:kernel/type_algebra.dart';
1415

1516
import '../builder/builder.dart';
1617
import '../builder/class_builder.dart';
@@ -24,6 +25,7 @@ import '../builder/prefix_builder.dart';
2425
import '../builder/type_alias_builder.dart';
2526
import '../builder/type_builder.dart';
2627
import '../builder/type_declaration_builder.dart';
28+
import '../builder/type_variable_builder.dart';
2729
import '../builder/unresolved_type.dart';
2830

2931
import '../constant_context.dart' show ConstantContext;
@@ -3099,6 +3101,7 @@ class TypeUseGenerator extends AbstractReadOnlyAccessGenerator {
30993101
TypeDeclarationBuilder? declarationBuilder = declaration;
31003102
TypeAliasBuilder? aliasBuilder;
31013103
List<TypeBuilder>? unaliasedTypeArguments;
3104+
bool isGenericTypedefTearOff = false;
31023105
if (declarationBuilder is TypeAliasBuilder) {
31033106
aliasBuilder = declarationBuilder;
31043107
declarationBuilder = aliasBuilder.unaliasDeclaration(null,
@@ -3129,6 +3132,19 @@ class TypeUseGenerator extends AbstractReadOnlyAccessGenerator {
31293132
..fileUri = _uri
31303133
..offset = fileOffset);
31313134
}
3135+
if (aliasedTypeArguments == null &&
3136+
aliasBuilder.typeVariablesCount != 0) {
3137+
isGenericTypedefTearOff = true;
3138+
aliasedTypeArguments = <TypeBuilder>[];
3139+
for (TypeVariableBuilder typeVariable
3140+
in aliasBuilder.typeVariables!) {
3141+
aliasedTypeArguments.add(new NamedTypeBuilder(typeVariable.name,
3142+
const NullabilityBuilder.omitted(), null, _uri, fileOffset)
3143+
..bind(typeVariable));
3144+
}
3145+
}
3146+
unaliasedTypeArguments =
3147+
aliasBuilder.unaliasTypeArguments(aliasedTypeArguments);
31323148
}
31333149
}
31343150
}
@@ -3177,10 +3193,31 @@ class TypeUseGenerator extends AbstractReadOnlyAccessGenerator {
31773193
builtTypeArguments =
31783194
_helper.buildDartTypeArguments(typeArguments);
31793195
}
3180-
return builtTypeArguments != null && builtTypeArguments.isNotEmpty
3181-
? _helper.forest.createInstantiation(
3182-
token.charOffset, tearOffExpression, builtTypeArguments)
3183-
: tearOffExpression;
3196+
if (isGenericTypedefTearOff) {
3197+
FreshTypeParameters freshTypeParameters =
3198+
getFreshTypeParameters(
3199+
aliasBuilder!.typedef.typeParameters);
3200+
List<DartType>? substitutedTypeArguments;
3201+
if (builtTypeArguments != null) {
3202+
substitutedTypeArguments = <DartType>[];
3203+
for (DartType builtTypeArgument in builtTypeArguments) {
3204+
substitutedTypeArguments
3205+
.add(freshTypeParameters.substitute(builtTypeArgument));
3206+
}
3207+
}
3208+
tearOffExpression = _helper.forest.createTypedefTearOff(
3209+
token.charOffset,
3210+
freshTypeParameters.freshTypeParameters,
3211+
tearOffExpression,
3212+
substitutedTypeArguments ?? const <DartType>[]);
3213+
} else {
3214+
if (builtTypeArguments != null &&
3215+
builtTypeArguments.isNotEmpty) {
3216+
tearOffExpression = _helper.forest.createInstantiation(
3217+
token.charOffset, tearOffExpression, builtTypeArguments);
3218+
}
3219+
}
3220+
return tearOffExpression;
31843221
}
31853222
}
31863223
generator = new UnresolvedNameGenerator(_helper, send.token, name);

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

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -846,6 +846,17 @@ class Forest {
846846
return new Instantiation(expression, typeArguments)
847847
..fileOffset = fileOffset;
848848
}
849+
850+
TypedefTearOff createTypedefTearOff(
851+
int fileOffset,
852+
List<TypeParameter> typeParameters,
853+
Expression expression,
854+
List<DartType> typeArguments) {
855+
// ignore: unnecessary_null_comparison
856+
assert(fileOffset != null);
857+
return new TypedefTearOff(typeParameters, expression, typeArguments)
858+
..fileOffset = fileOffset;
859+
}
849860
}
850861

851862
class _VariablesDeclaration extends Statement {

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

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import 'package:_fe_analyzer_shared/src/util/link.dart';
77
import 'package:front_end/src/api_prototype/lowering_predicates.dart';
88
import 'package:kernel/ast.dart';
99
import 'package:kernel/src/legacy_erasure.dart';
10-
import 'package:kernel/type_algebra.dart' show Substitution;
10+
import 'package:kernel/type_algebra.dart';
1111
import 'package:kernel/type_environment.dart';
1212

1313
import '../../base/instrumentation.dart'
@@ -225,7 +225,37 @@ class InferenceVisitor
225225
@override
226226
ExpressionInferenceResult visitTypedefTearOff(
227227
TypedefTearOff node, DartType typeContext) {
228-
return _unhandledExpression(node, typeContext);
228+
ExpressionInferenceResult expressionResult = inferrer.inferExpression(
229+
node.expression, const UnknownType(), true,
230+
isVoidAllowed: true);
231+
node.expression = expressionResult.expression..parent = node;
232+
233+
assert(
234+
expressionResult.inferredType is FunctionType,
235+
"Expected a FunctionType from tearing off a constructor from "
236+
"a typedef, but got '${expressionResult.inferredType.runtimeType}'.");
237+
FunctionType expressionType = expressionResult.inferredType as FunctionType;
238+
239+
assert(expressionType.typeParameters.length == node.typeArguments.length);
240+
Substitution substitution = Substitution.fromPairs(
241+
expressionType.typeParameters, node.typeArguments);
242+
FunctionType resultType = substitution
243+
.substituteType(expressionType.withoutTypeParameters) as FunctionType;
244+
FreshTypeParameters freshTypeParameters =
245+
getFreshTypeParameters(node.typeParameters);
246+
resultType = freshTypeParameters.substitute(resultType) as FunctionType;
247+
resultType = new FunctionType(resultType.positionalParameters,
248+
resultType.returnType, resultType.declaredNullability,
249+
namedParameters: resultType.namedParameters,
250+
typeParameters: freshTypeParameters.freshTypeParameters,
251+
requiredParameterCount: resultType.requiredParameterCount,
252+
typedefType: null);
253+
ExpressionInferenceResult inferredResult =
254+
inferrer.instantiateTearOff(resultType, typeContext, node);
255+
Expression ensuredResultExpression =
256+
inferrer.ensureAssignableResult(typeContext, inferredResult);
257+
return new ExpressionInferenceResult(
258+
inferredResult.inferredType, ensuredResultExpression);
229259
}
230260

231261
@override

pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,9 @@ B<num> Function() test18() => DB3<num, String>.new; // Ok.
4545
B<num> Function() test19() => DB3<num, String>.foo; // Ok.
4646
B<num> Function() test20() => DB3<num, String>.bar; // Ok.
4747
B<num> Function() test21() => DB3.new; // Ok.
48-
B<Y> Function<Y extends num, Z extends String>() test22() => DB2.new; // Ok.
49-
B<Y> Function<Y, Z>() test23() => DB2.new; // Error.
48+
B<Y> Function<Y extends num, Z extends String>() test22() => DB3.new; // Ok.
49+
B<Y> Function<Y, Z>() test23() => DB3.new; // Error.
50+
51+
B<String> Function() test24() => DB2.new; // Ok.
5052

5153
main() {}

pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart.strong.expect

Lines changed: 28 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -15,24 +15,24 @@ library /*isNonNullableByDefault*/;
1515
// B<num> Function() test9() => DB1.new; // Error.
1616
// ^
1717
//
18-
// pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:41:44: Error: A value of type 'B<num> Function()' can't be returned from a function with return type 'B<Y> Function<Y extends num>()'.
18+
// pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:42:32: Error: A value of type 'B<X> Function<X extends num>()' can't be assigned to a variable of type 'B<Y> Function<Y>()'.
1919
// - 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
20-
// B<Y> Function<Y extends num>() test16() => DB2.new; // Ok.
21-
// ^
20+
// B<Y> Function<Y>() test17() => DB2.new; // Error.
21+
// ^
2222
//
23-
// pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:42:32: Error: A value of type 'B<num> Function()' can't be returned from a function with return type 'B<Y> Function<Y>()'.
23+
// pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:42:32: Error: A value of type 'B<X> Function<X extends num>()' can't be returned from a function with return type 'B<Y> Function<Y>()'.
2424
// - 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
2525
// B<Y> Function<Y>() test17() => DB2.new; // Error.
2626
// ^
2727
//
28-
// pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:48:62: Error: A value of type 'B<num> Function()' can't be returned from a function with return type 'B<Y> Function<Y extends num, Z extends String>()'.
28+
// pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:49:35: Error: A value of type 'B<X> Function<X extends num, Y extends String>()' can't be assigned to a variable of type 'B<Y> Function<Y, Z>()'.
2929
// - 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
30-
// B<Y> Function<Y extends num, Z extends String>() test22() => DB2.new; // Ok.
31-
// ^
30+
// B<Y> Function<Y, Z>() test23() => DB3.new; // Error.
31+
// ^
3232
//
33-
// pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:49:35: Error: A value of type 'B<num> Function()' can't be returned from a function with return type 'B<Y> Function<Y, Z>()'.
33+
// pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:49:35: Error: A value of type 'B<X> Function<X extends num, Y extends String>()' can't be returned from a function with return type 'B<Y> Function<Y, Z>()'.
3434
// - 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
35-
// B<Y> Function<Y, Z>() test23() => DB2.new; // Error.
35+
// B<Y> Function<Y, Z>() test23() => DB3.new; // Error.
3636
// ^
3737
//
3838
import self as self;
@@ -63,9 +63,9 @@ static method test1() → () → self::A
6363
static method test2() → () → self::A
6464
return self::A::•;
6565
static method test3() → () → self::A
66-
return self::A::•;
66+
return <unrelated X extends core::num>.(self::A::•)<core::num>;
6767
static method test4() → () → self::A
68-
return self::A::•;
68+
return <unrelated X extends core::num>.(self::A::•)<core::num>;
6969
static method test5() → () → self::A
7070
return self::A::•;
7171
static method test6() → () → self::A
@@ -90,33 +90,35 @@ static method test13() → () → self::B<core::num>
9090
static method test14() → () → self::B<core::num>
9191
return self::B::bar<core::num>;
9292
static method test15() → () → self::B<core::num>
93-
return self::B::•<core::num>;
93+
return <X extends core::num>.(self::B::•<X>)<core::num>;
9494
static method test16() → <Y extends core::num = dynamic>() → self::B<Y>
95-
return let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:41:44: Error: A value of type 'B<num> Function()' can't be returned from a function with return type 'B<Y> Function<Y extends num>()'.
96-
- 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
97-
B<Y> Function<Y extends num>() test16() => DB2.new; // Ok.
98-
^" in (self::B::•<core::num>) as{TypeError,ForNonNullableByDefault} <Y extends core::num = dynamic>() → self::B<Y>;
95+
return <X extends core::num>.(self::B::•<X>);
9996
static method test17() → <Y extends core::Object? = dynamic>() → self::B<Y%>
100-
return let final Never #t3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:42:32: Error: A value of type 'B<num> Function()' can't be returned from a function with return type 'B<Y> Function<Y>()'.
97+
return let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:42:32: Error: A value of type 'B<X> Function<X extends num>()' can't be returned from a function with return type 'B<Y> Function<Y>()'.
98+
- 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
99+
B<Y> Function<Y>() test17() => DB2.new; // Error.
100+
^" in (let final Never #t3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:42:32: Error: A value of type 'B<X> Function<X extends num>()' can't be assigned to a variable of type 'B<Y> Function<Y>()'.
101101
- 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
102102
B<Y> Function<Y>() test17() => DB2.new; // Error.
103-
^" in (self::B::•<core::num>) as{TypeError,ForNonNullableByDefault} <Y extends core::Object? = dynamic>() → self::B<Y%>;
103+
^" in (<X extends core::num>.(self::B::•<X>)) as{TypeError,ForNonNullableByDefault} <Y extends core::Object? = dynamic>() → self::B<Y%>) as{TypeError,ForNonNullableByDefault} <Y extends core::Object? = dynamic>() → self::B<Y%>;
104104
static method test18() → () → self::B<core::num>
105105
return self::B::•<core::num>;
106106
static method test19() → () → self::B<core::num>
107107
return self::B::foo<core::num>;
108108
static method test20() → () → self::B<core::num>
109109
return self::B::bar<core::num>;
110110
static method test21() → () → self::B<core::num>
111-
return self::B::•<core::num>;
111+
return <X extends core::num, unrelated Y extends core::String>.(self::B::•<X>)<core::num, core::String>;
112112
static method test22() → <Y extends core::num = dynamic, Z extends core::String = dynamic>() → self::B<Y>
113-
return let final Never #t4 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:48:62: Error: A value of type 'B<num> Function()' can't be returned from a function with return type 'B<Y> Function<Y extends num, Z extends String>()'.
114-
- 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
115-
B<Y> Function<Y extends num, Z extends String>() test22() => DB2.new; // Ok.
116-
^" in (self::B::•<core::num>) as{TypeError,ForNonNullableByDefault} <Y extends core::num = dynamic, Z extends core::String = dynamic>() → self::B<Y>;
113+
return <X extends core::num, unrelated Y extends core::String>.(self::B::•<X>);
117114
static method test23() → <Y extends core::Object? = dynamic, Z extends core::Object? = dynamic>() → self::B<Y%>
118-
return let final Never #t5 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:49:35: Error: A value of type 'B<num> Function()' can't be returned from a function with return type 'B<Y> Function<Y, Z>()'.
115+
return let final Never #t4 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:49:35: Error: A value of type 'B<X> Function<X extends num, Y extends String>()' can't be returned from a function with return type 'B<Y> Function<Y, Z>()'.
116+
- 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
117+
B<Y> Function<Y, Z>() test23() => DB3.new; // Error.
118+
^" in (let final Never #t5 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:49:35: Error: A value of type 'B<X> Function<X extends num, Y extends String>()' can't be assigned to a variable of type 'B<Y> Function<Y, Z>()'.
119119
- 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
120-
B<Y> Function<Y, Z>() test23() => DB2.new; // Error.
121-
^" in (self::B::•<core::num>) as{TypeError,ForNonNullableByDefault} <Y extends core::Object? = dynamic, Z extends core::Object? = dynamic>() → self::B<Y%>;
120+
B<Y> Function<Y, Z>() test23() => DB3.new; // Error.
121+
^" in (<X extends core::num, unrelated Y extends core::String>.(self::B::•<X>)) as{TypeError,ForNonNullableByDefault} <Y extends core::Object? = dynamic, Z extends core::Object? = dynamic>() → self::B<Y%>) as{TypeError,ForNonNullableByDefault} <Y extends core::Object? = dynamic, Z extends core::Object? = dynamic>() → self::B<Y%>;
122+
static method test24() → () → self::B<core::String>
123+
return <X extends core::num>.(self::B::•<X>)<Never>;
122124
static method main() → dynamic {}

0 commit comments

Comments
 (0)