Skip to content

Commit 74fd108

Browse files
johnniwinthercommit-bot@chromium.org
authored and
commit-bot@chromium.org
committed
[cfe] Handle nullable function types in explicit instantiation
Part of #46232 Change-Id: I390dc15a253cf0b335ed41bf945bbab2a3b2bdcc Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/215545 Reviewed-by: Chloe Stefantsova <dmitryas@google.com> Commit-Queue: Johnni Winther <johnniwinther@google.com>
1 parent cf1591f commit 74fd108

11 files changed

+689
-10
lines changed

pkg/front_end/lib/src/fasta/fasta_codes_cfe_generated.dart

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2100,6 +2100,37 @@ Message _withArgumentsInstantiationNonGenericFunctionType(
21002100
arguments: {'type': _type});
21012101
}
21022102

2103+
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
2104+
const Template<Message Function(DartType _type, bool isNonNullableByDefault)>
2105+
templateInstantiationNullableGenericFunctionType = const Template<
2106+
Message Function(DartType _type, bool isNonNullableByDefault)>(
2107+
problemMessageTemplate:
2108+
r"""The static type of the explicit instantiation operand must be a non-null generic function type but is '#type'.""",
2109+
correctionMessageTemplate:
2110+
r"""Try changing the operand or remove the type arguments.""",
2111+
withArguments: _withArgumentsInstantiationNullableGenericFunctionType);
2112+
2113+
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
2114+
const Code<Message Function(DartType _type, bool isNonNullableByDefault)>
2115+
codeInstantiationNullableGenericFunctionType =
2116+
const Code<Message Function(DartType _type, bool isNonNullableByDefault)>(
2117+
"InstantiationNullableGenericFunctionType",
2118+
analyzerCodes: <String>["DISALLOWED_TYPE_INSTANTIATION_EXPRESSION"]);
2119+
2120+
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
2121+
Message _withArgumentsInstantiationNullableGenericFunctionType(
2122+
DartType _type, bool isNonNullableByDefault) {
2123+
TypeLabeler labeler = new TypeLabeler(isNonNullableByDefault);
2124+
List<Object> typeParts = labeler.labelType(_type);
2125+
String type = typeParts.join();
2126+
return new Message(codeInstantiationNullableGenericFunctionType,
2127+
problemMessage:
2128+
"""The static type of the explicit instantiation operand must be a non-null generic function type but is '${type}'.""" +
2129+
labeler.originMessages,
2130+
correctionMessage: """Try changing the operand or remove the type arguments.""",
2131+
arguments: {'type': _type});
2132+
}
2133+
21032134
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
21042135
const Template<
21052136
Message Function(

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

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -412,12 +412,24 @@ class InferenceVisitor
412412
DartType resultType = const InvalidType();
413413
if (operandType is FunctionType) {
414414
if (operandType.typeParameters.length == node.typeArguments.length) {
415-
inferrer.checkBoundsInInstantiation(
416-
operandType, node.typeArguments, node.fileOffset,
417-
inferred: false);
418-
resultType = Substitution.fromPairs(
419-
operandType.typeParameters, node.typeArguments)
420-
.substituteType(operandType.withoutTypeParameters);
415+
if (!inferrer.isTopLevel) {
416+
inferrer.checkBoundsInInstantiation(
417+
operandType, node.typeArguments, node.fileOffset,
418+
inferred: false);
419+
}
420+
if (operandType.isPotentiallyNullable) {
421+
if (!inferrer.isTopLevel) {
422+
result = inferrer.helper!.buildProblem(
423+
templateInstantiationNullableGenericFunctionType.withArguments(
424+
operandType, inferrer.isNonNullableByDefault),
425+
node.fileOffset,
426+
noLength);
427+
}
428+
} else {
429+
resultType = Substitution.fromPairs(
430+
operandType.typeParameters, node.typeArguments)
431+
.substituteType(operandType.withoutTypeParameters);
432+
}
421433
} else {
422434
if (!inferrer.isTopLevel) {
423435
if (operandType.typeParameters.isEmpty) {

pkg/front_end/messages.yaml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5355,6 +5355,14 @@ InstantiationNonGenericFunctionType:
53555355
f() {}
53565356
main() => f<int>;
53575357
5358+
InstantiationNullableGenericFunctionType:
5359+
problemMessage: "The static type of the explicit instantiation operand must be a non-null generic function type but is '#type'."
5360+
correctionMessage: "Try changing the operand or remove the type arguments."
5361+
analyzerCode: DISALLOWED_TYPE_INSTANTIATION_EXPRESSION
5362+
experiments: constructor-tearoffs
5363+
script: |
5364+
test(void Function<T>()? f) => f<int>;
5365+
53585366
InstantiationTooFewArguments:
53595367
problemMessage: "Too few type arguments: #count required, #count2 given."
53605368
correctionMessage: "Try adding the missing type arguments."

pkg/front_end/testcases/constructor_tearoffs/callable_instantiation.dart

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,34 @@ test<T extends Class?, S extends int>(
4242
f3<int>; // error
4343
}
4444

45+
Class c1 = Class();
46+
Class? c2;
47+
GetterCall c3 = GetterCall();
48+
int i1 = 0;
49+
int? i2 = null;
50+
void Function<T>()? f1 = null;
51+
Never n = throw '';
52+
dynamic d = null;
53+
String a = '';
54+
double b = 0.5;
55+
bool c = true;
56+
FutureOr<Class> f2 = Class();
57+
Function f3 = () {};
58+
59+
var topLevel1 = c1<int>; // ok
60+
var topLevel2 = i1<int>; // ok
61+
var topLevel3 = c2<int>; // error
62+
var topLevel4 = c3<int>; // error
63+
var topLevel5 = i2<int>; // error
64+
var topLevel6 = f1<int>; // error
65+
var topLevel7 = n<int>; // error
66+
var topLevel8 = d<int>; // error
67+
var topLevel9 = a<int>; // error
68+
var topLevel10 = b<int>; // error
69+
var topLevel11 = c<int>; // error
70+
var topLevel12 = f2<int>; // error
71+
var topLevel13 = f3<int>; // error
72+
4573
class Class {
4674
call<T>() {}
4775
}

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

Lines changed: 131 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,11 @@ library /*isNonNullableByDefault*/;
3434
// s<int>; // error
3535
// ^
3636
//
37+
// pkg/front_end/testcases/constructor_tearoffs/callable_instantiation.dart:35:5: Error: The static type of the explicit instantiation operand must be a non-null generic function type but is 'void Function<T>()?'.
38+
// Try changing the operand or remove the type arguments.
39+
// f1<int>; // error
40+
// ^
41+
//
3742
// pkg/front_end/testcases/constructor_tearoffs/callable_instantiation.dart:36:4: Error: The static type of the explicit instantiation operand must be a generic function type but is 'Never'.
3843
// Try changing the operand or remove the type arguments.
3944
// n<int>; // error
@@ -71,6 +76,65 @@ library /*isNonNullableByDefault*/;
7176
// f3<int>; // error
7277
// ^
7378
//
79+
// pkg/front_end/testcases/constructor_tearoffs/callable_instantiation.dart:61:19: Error: The static type of the explicit instantiation operand must be a generic function type but is 'Class?'.
80+
// - 'Class' is from 'pkg/front_end/testcases/constructor_tearoffs/callable_instantiation.dart'.
81+
// Try changing the operand or remove the type arguments.
82+
// var topLevel3 = c2<int>; // error
83+
// ^
84+
//
85+
// pkg/front_end/testcases/constructor_tearoffs/callable_instantiation.dart:62:19: Error: The static type of the explicit instantiation operand must be a generic function type but is 'GetterCall'.
86+
// - 'GetterCall' is from 'pkg/front_end/testcases/constructor_tearoffs/callable_instantiation.dart'.
87+
// Try changing the operand or remove the type arguments.
88+
// var topLevel4 = c3<int>; // error
89+
// ^
90+
//
91+
// pkg/front_end/testcases/constructor_tearoffs/callable_instantiation.dart:63:19: Error: The static type of the explicit instantiation operand must be a generic function type but is 'int?'.
92+
// Try changing the operand or remove the type arguments.
93+
// var topLevel5 = i2<int>; // error
94+
// ^
95+
//
96+
// pkg/front_end/testcases/constructor_tearoffs/callable_instantiation.dart:64:19: Error: The static type of the explicit instantiation operand must be a non-null generic function type but is 'void Function<T>()?'.
97+
// Try changing the operand or remove the type arguments.
98+
// var topLevel6 = f1<int>; // error
99+
// ^
100+
//
101+
// pkg/front_end/testcases/constructor_tearoffs/callable_instantiation.dart:65:18: Error: The static type of the explicit instantiation operand must be a generic function type but is 'Never'.
102+
// Try changing the operand or remove the type arguments.
103+
// var topLevel7 = n<int>; // error
104+
// ^
105+
//
106+
// pkg/front_end/testcases/constructor_tearoffs/callable_instantiation.dart:66:18: Error: The static type of the explicit instantiation operand must be a generic function type but is 'dynamic'.
107+
// Try changing the operand or remove the type arguments.
108+
// var topLevel8 = d<int>; // error
109+
// ^
110+
//
111+
// pkg/front_end/testcases/constructor_tearoffs/callable_instantiation.dart:67:18: Error: The static type of the explicit instantiation operand must be a generic function type but is 'String'.
112+
// Try changing the operand or remove the type arguments.
113+
// var topLevel9 = a<int>; // error
114+
// ^
115+
//
116+
// pkg/front_end/testcases/constructor_tearoffs/callable_instantiation.dart:68:19: Error: The static type of the explicit instantiation operand must be a generic function type but is 'double'.
117+
// Try changing the operand or remove the type arguments.
118+
// var topLevel10 = b<int>; // error
119+
// ^
120+
//
121+
// pkg/front_end/testcases/constructor_tearoffs/callable_instantiation.dart:69:19: Error: The static type of the explicit instantiation operand must be a generic function type but is 'bool'.
122+
// Try changing the operand or remove the type arguments.
123+
// var topLevel11 = c<int>; // error
124+
// ^
125+
//
126+
// pkg/front_end/testcases/constructor_tearoffs/callable_instantiation.dart:70:20: Error: The static type of the explicit instantiation operand must be a generic function type but is 'FutureOr<Class>'.
127+
// - 'Class' is from 'pkg/front_end/testcases/constructor_tearoffs/callable_instantiation.dart'.
128+
// Try changing the operand or remove the type arguments.
129+
// var topLevel12 = f2<int>; // error
130+
// ^
131+
//
132+
// pkg/front_end/testcases/constructor_tearoffs/callable_instantiation.dart:71:20: Error: The static type of the explicit instantiation operand must be a generic function type but is 'Function'.
133+
// - 'Function' is from 'dart:core'.
134+
// Try changing the operand or remove the type arguments.
135+
// var topLevel13 = f3<int>; // error
136+
// ^
137+
//
74138
import self as self;
75139
import "dart:core" as core;
76140

@@ -107,6 +171,69 @@ extension Ambiguous2 on core::String {
107171
method call = self::Ambiguous2|call;
108172
tearoff call = self::Ambiguous2|get#call;
109173
}
174+
static field self::Class c1 = new self::Class::•();
175+
static field self::Class? c2;
176+
static field self::GetterCall c3 = new self::GetterCall::•();
177+
static field core::int i1 = 0;
178+
static field core::int? i2 = null;
179+
static field <T extends core::Object? = dynamic>() →? void f1 = null;
180+
static field Never n = throw "";
181+
static field dynamic d = null;
182+
static field core::String a = "";
183+
static field core::double b = 0.5;
184+
static field core::bool c = true;
185+
static field FutureOr<self::Class>f2 = new self::Class::•();
186+
static field core::Function f3 = () → Null {};
187+
static field () → dynamic topLevel1 = self::c1.{self::Class::call}{<T extends core::Object? = dynamic>() → dynamic}<core::int>;
188+
static field () → dynamic topLevel2 = self::Extension|get#call(self::i1)<core::int>;
189+
static field invalid-type topLevel3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/callable_instantiation.dart:61:19: Error: The static type of the explicit instantiation operand must be a generic function type but is 'Class?'.
190+
- 'Class' is from 'pkg/front_end/testcases/constructor_tearoffs/callable_instantiation.dart'.
191+
Try changing the operand or remove the type arguments.
192+
var topLevel3 = c2<int>; // error
193+
^";
194+
static field invalid-type topLevel4 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/callable_instantiation.dart:62:19: Error: The static type of the explicit instantiation operand must be a generic function type but is 'GetterCall'.
195+
- 'GetterCall' is from 'pkg/front_end/testcases/constructor_tearoffs/callable_instantiation.dart'.
196+
Try changing the operand or remove the type arguments.
197+
var topLevel4 = c3<int>; // error
198+
^";
199+
static field invalid-type topLevel5 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/callable_instantiation.dart:63:19: Error: The static type of the explicit instantiation operand must be a generic function type but is 'int?'.
200+
Try changing the operand or remove the type arguments.
201+
var topLevel5 = i2<int>; // error
202+
^";
203+
static field invalid-type topLevel6 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/callable_instantiation.dart:64:19: Error: The static type of the explicit instantiation operand must be a non-null generic function type but is 'void Function<T>()?'.
204+
Try changing the operand or remove the type arguments.
205+
var topLevel6 = f1<int>; // error
206+
^";
207+
static field invalid-type topLevel7 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/callable_instantiation.dart:65:18: Error: The static type of the explicit instantiation operand must be a generic function type but is 'Never'.
208+
Try changing the operand or remove the type arguments.
209+
var topLevel7 = n<int>; // error
210+
^";
211+
static field invalid-type topLevel8 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/callable_instantiation.dart:66:18: Error: The static type of the explicit instantiation operand must be a generic function type but is 'dynamic'.
212+
Try changing the operand or remove the type arguments.
213+
var topLevel8 = d<int>; // error
214+
^";
215+
static field invalid-type topLevel9 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/callable_instantiation.dart:67:18: Error: The static type of the explicit instantiation operand must be a generic function type but is 'String'.
216+
Try changing the operand or remove the type arguments.
217+
var topLevel9 = a<int>; // error
218+
^";
219+
static field invalid-type topLevel10 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/callable_instantiation.dart:68:19: Error: The static type of the explicit instantiation operand must be a generic function type but is 'double'.
220+
Try changing the operand or remove the type arguments.
221+
var topLevel10 = b<int>; // error
222+
^";
223+
static field invalid-type topLevel11 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/callable_instantiation.dart:69:19: Error: The static type of the explicit instantiation operand must be a generic function type but is 'bool'.
224+
Try changing the operand or remove the type arguments.
225+
var topLevel11 = c<int>; // error
226+
^";
227+
static field invalid-type topLevel12 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/callable_instantiation.dart:70:20: Error: The static type of the explicit instantiation operand must be a generic function type but is 'FutureOr<Class>'.
228+
- 'Class' is from 'pkg/front_end/testcases/constructor_tearoffs/callable_instantiation.dart'.
229+
Try changing the operand or remove the type arguments.
230+
var topLevel12 = f2<int>; // error
231+
^";
232+
static field invalid-type topLevel13 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/callable_instantiation.dart:71:20: Error: The static type of the explicit instantiation operand must be a generic function type but is 'Function'.
233+
- 'Function' is from 'dart:core'.
234+
Try changing the operand or remove the type arguments.
235+
var topLevel13 = f3<int>; // error
236+
^";
110237
static method method<T extends self::Class, S extends core::int>(self::Class c, core::int i, self::method::T t, self::method::S s) → dynamic {
111238
c.{self::Class::call}{<T extends core::Object? = dynamic>() → dynamic}<core::int>;
112239
self::Extension|get#call(i)<core::int>;
@@ -140,7 +267,10 @@ Try changing the operand or remove the type arguments.
140267
Try changing the operand or remove the type arguments.
141268
s<int>; // error
142269
^";
143-
f1<core::int>;
270+
invalid-expression "pkg/front_end/testcases/constructor_tearoffs/callable_instantiation.dart:35:5: Error: The static type of the explicit instantiation operand must be a non-null generic function type but is 'void Function<T>()?'.
271+
Try changing the operand or remove the type arguments.
272+
f1<int>; // error
273+
^";
144274
invalid-expression "pkg/front_end/testcases/constructor_tearoffs/callable_instantiation.dart:36:4: Error: The static type of the explicit instantiation operand must be a generic function type but is 'Never'.
145275
Try changing the operand or remove the type arguments.
146276
n<int>; // error

0 commit comments

Comments
 (0)