Skip to content

Commit 42f0e9a

Browse files
srawlinsCommit Queue
authored andcommitted
analyzer: Report bad type arg on implicit call
Fixes #49671 Also adds many more test cases for bad implicit 'call' calls. Change-Id: I87a50c1b527c66e6a75b07087ccdb195a862b1fd Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/400744 Commit-Queue: Samuel Rawlins <[email protected]> Reviewed-by: Brian Wilkerson <[email protected]> Reviewed-by: Konstantin Shcheglov <[email protected]>
1 parent 8cc449a commit 42f0e9a

File tree

5 files changed

+113
-10
lines changed

5 files changed

+113
-10
lines changed

pkg/analyzer/lib/src/error/type_arguments_verifier.dart

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,9 +155,15 @@ class TypeArgumentsVerifier {
155155
}
156156

157157
void checkFunctionExpressionInvocation(FunctionExpressionInvocation node) {
158+
// For some function expressions, like an implicit 'call' invocation, the
159+
// function type is on `node`'s `element`. For anonymous function
160+
// expressions, the function is on `node`'s `function`.
161+
// TODO(srawlins): It seems that `node.function`, the Expression, should
162+
// always have the static type of the `call` method.
163+
var functionType = node.element?.type ?? node.function.staticType;
158164
_checkInvocationTypeArguments(
159165
node.typeArguments?.arguments,
160-
node.function.staticType,
166+
functionType,
161167
node.staticInvokeType,
162168
);
163169
}

pkg/analyzer/lib/src/generated/error_verifier.dart

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1011,16 +1011,13 @@ class ErrorVerifier extends RecursiveAstVisitor<void>
10111011

10121012
@override
10131013
void visitFunctionExpressionInvocation(FunctionExpressionInvocation node) {
1014-
Expression functionExpression = node.function;
1014+
var functionExpression = node.function;
10151015

10161016
if (functionExpression is ExtensionOverride) {
10171017
return super.visitFunctionExpressionInvocation(node);
10181018
}
10191019

1020-
DartType expressionType = functionExpression.typeOrThrow;
1021-
if (expressionType is FunctionType) {
1022-
_typeArgumentsVerifier.checkFunctionExpressionInvocation(node);
1023-
}
1020+
_typeArgumentsVerifier.checkFunctionExpressionInvocation(node);
10241021
_requiredParametersVerifier.visitFunctionExpressionInvocation(node);
10251022
_constArgumentsVerifier.visitFunctionExpressionInvocation(node);
10261023
_checkUseVerifier.checkFunctionExpressionInvocation(node);

pkg/analyzer/lib/src/generated/resolver.dart

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1799,14 +1799,14 @@ class ResolverVisitor extends ThrowingAstVisitor<void>
17991799
}
18001800
}
18011801

1802-
/// Returns the result of an implicit `this.` lookup for the identifier string
1803-
/// [id] in a getter context, or `null` if no match was found.
1802+
/// Returns the result of an implicit `this.` lookup for the identifier [node]
1803+
/// in a getter context, or `null` if no match was found.
18041804
LexicalLookupResult? thisLookupGetter(SimpleIdentifier node) {
18051805
return ThisLookup.lookupGetter(this, node);
18061806
}
18071807

1808-
/// Returns the result of an implicit `this.` lookup for the identifier string
1809-
/// [id] in a setter context, or `null` if no match was found.
1808+
/// Returns the result of an implicit `this.` lookup for the identifier [node]
1809+
/// in a setter context, or `null` if no match was found.
18101810
LexicalLookupResult? thisLookupSetter(SimpleIdentifier node) {
18111811
return ThisLookup.lookupSetter(this, node);
18121812
}

pkg/analyzer/test/src/diagnostics/type_argument_not_matching_bounds_test.dart

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,30 @@ class C {
166166
]);
167167
}
168168

169+
test_functionExpressionInvocation() async {
170+
await assertErrorsInCode(r'''
171+
void f() {
172+
(<T extends num>() {})<String>();
173+
}
174+
''', [
175+
error(CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, 36, 6),
176+
]);
177+
}
178+
179+
test_functionExpressionInvocation_implicitCall() async {
180+
await assertErrorsInCode(r'''
181+
class C {
182+
void call<T extends num>() {}
183+
}
184+
185+
void f(C c) {
186+
c<String>();
187+
}
188+
''', [
189+
error(CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, 63, 6),
190+
]);
191+
}
192+
169193
test_functionReference() async {
170194
await assertErrorsInCode('''
171195
void foo<T extends num>(T a) {}

pkg/analyzer/test/src/diagnostics/wrong_number_of_type_arguments_test.dart

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,56 @@ dynamic<int> v;
9494
]);
9595
}
9696

97+
test_functionInvocation_tooFew() async {
98+
await assertErrorsInCode('''
99+
void f() {
100+
g<int>();
101+
}
102+
void g<T, U>() {}
103+
''', [
104+
error(CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS_METHOD, 14, 5),
105+
]);
106+
}
107+
108+
test_functionInvocation_tooMany() async {
109+
await assertErrorsInCode('''
110+
void f() {
111+
g<int, String>();
112+
}
113+
void g<T>() {}
114+
''', [
115+
error(CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS_METHOD, 14, 13),
116+
]);
117+
}
118+
119+
test_functionReference_implicitCallTearoff_tooFew() async {
120+
await assertErrorsInCode('''
121+
f(C c) {
122+
c<int>;
123+
}
124+
class C {
125+
void call<T, U>() {}
126+
}
127+
''', [
128+
error(
129+
CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS_FUNCTION, 12, 5),
130+
]);
131+
}
132+
133+
test_functionReference_implicitCallTearoff_tooMany() async {
134+
await assertErrorsInCode('''
135+
f(C c) {
136+
c<int, String>;
137+
}
138+
class C {
139+
void call<T>() {}
140+
}
141+
''', [
142+
error(
143+
CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS_FUNCTION, 12, 13),
144+
]);
145+
}
146+
97147
test_functionReference_tooFew() async {
98148
await assertErrorsInCode('''
99149
f() {
@@ -227,6 +277,32 @@ void f() {}
227277
]);
228278
}
229279

280+
test_methodInvocation_tooFew() async {
281+
await assertErrorsInCode('''
282+
void f(C c) {
283+
c.g<int>();
284+
}
285+
class C {
286+
void g<T, U>() {}
287+
}
288+
''', [
289+
error(CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS_METHOD, 19, 5),
290+
]);
291+
}
292+
293+
test_methodInvocation_tooMany() async {
294+
await assertErrorsInCode('''
295+
void f(C c) {
296+
c.g<int, String>();
297+
}
298+
class C {
299+
void g<T>() {}
300+
}
301+
''', [
302+
error(CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS_METHOD, 19, 13),
303+
]);
304+
}
305+
230306
test_new_nonGeneric() async {
231307
await assertErrorsInCode('''
232308
class C {}

0 commit comments

Comments
 (0)