Skip to content

Commit dc34c02

Browse files
[model] Report error on void arguments of dynamic types in Analyzer
Closes flutter/flutter#161479 Change-Id: I6657e93dc609566fb5c11d85918e37e2da8744d4 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/448861 Reviewed-by: Paul Berry <[email protected]>
1 parent 62902d2 commit dc34c02

File tree

2 files changed

+73
-23
lines changed

2 files changed

+73
-23
lines changed

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

Lines changed: 40 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -69,14 +69,34 @@ mixin ErrorDetectionHelpers {
6969
bool promoteParameterToNullable = false,
7070
Map<SharedTypeView, NonPromotionReason> Function()? whyNotPromoted,
7171
}) {
72-
_checkForArgumentTypeNotAssignableForArgument(
73-
argument: argument is NamedExpressionImpl
74-
? argument.expression
75-
: argument,
76-
parameter: argument.correspondingParameter,
77-
promoteParameterToNullable: promoteParameterToNullable,
78-
whyNotPromoted: whyNotPromoted,
79-
);
72+
var parameter = argument.correspondingParameter;
73+
TypeImpl? correspondingParameterType;
74+
if (parameter != null) {
75+
correspondingParameterType = parameter.type;
76+
} else if (argument.parent
77+
case ArgumentListImpl(
78+
parent: FunctionExpressionInvocationImpl(
79+
function: Expression(:var staticType),
80+
),
81+
)
82+
when identical(staticType, DynamicTypeImpl.instance) ||
83+
identical(staticType, NeverTypeImpl.instance) ||
84+
staticType is InterfaceTypeImpl && staticType.isDartCoreFunction) {
85+
// Treat dynamic invocations as having function types where all formal
86+
// parameter types are 'dynamic'.
87+
correspondingParameterType = DynamicTypeImpl.instance;
88+
}
89+
90+
if (correspondingParameterType != null) {
91+
_checkForArgumentTypeNotAssignableForArgument(
92+
argument: argument is NamedExpressionImpl
93+
? argument.expression
94+
: argument,
95+
staticParameterType: correspondingParameterType,
96+
promoteParameterToNullable: promoteParameterToNullable,
97+
whyNotPromoted: whyNotPromoted,
98+
);
99+
}
80100
}
81101

82102
void checkForAssignableExpressionAtType(
@@ -297,7 +317,7 @@ mixin ErrorDetectionHelpers {
297317
if (parameters.isNotEmpty) {
298318
_checkForArgumentTypeNotAssignableForArgument(
299319
argument: index,
300-
parameter: parameters[0],
320+
staticParameterType: parameters[0].type,
301321
promoteParameterToNullable: false,
302322
whyNotPromoted: whyNotPromoted,
303323
);
@@ -309,7 +329,7 @@ mixin ErrorDetectionHelpers {
309329
if (parameters.isNotEmpty) {
310330
_checkForArgumentTypeNotAssignableForArgument(
311331
argument: index,
312-
parameter: parameters[0],
332+
staticParameterType: parameters[0].type,
313333
promoteParameterToNullable: false,
314334
whyNotPromoted: whyNotPromoted,
315335
);
@@ -389,22 +409,19 @@ mixin ErrorDetectionHelpers {
389409

390410
void _checkForArgumentTypeNotAssignableForArgument({
391411
required Expression argument,
392-
required InternalFormalParameterElement? parameter,
412+
required TypeImpl staticParameterType,
393413
required bool promoteParameterToNullable,
394414
Map<SharedTypeView, NonPromotionReason> Function()? whyNotPromoted,
395415
}) {
396-
var staticParameterType = parameter?.type;
397-
if (staticParameterType != null) {
398-
if (promoteParameterToNullable) {
399-
staticParameterType = typeSystem.makeNullable(staticParameterType);
400-
}
401-
checkForArgumentTypeNotAssignable(
402-
argument,
403-
staticParameterType,
404-
argument.typeOrThrow,
405-
CompileTimeErrorCode.argumentTypeNotAssignable,
406-
whyNotPromoted: whyNotPromoted,
407-
);
416+
if (promoteParameterToNullable) {
417+
staticParameterType = typeSystem.makeNullable(staticParameterType);
408418
}
419+
checkForArgumentTypeNotAssignable(
420+
argument,
421+
staticParameterType,
422+
argument.typeOrThrow,
423+
CompileTimeErrorCode.argumentTypeNotAssignable,
424+
whyNotPromoted: whyNotPromoted,
425+
);
409426
}
410427
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// Copyright (c) 2025, 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+
abstract class A {
6+
Function get fooFunction;
7+
dynamic get fooDynamic;
8+
void fooRegular(Object? arg);
9+
Never get fooNever;
10+
11+
void bar() {}
12+
13+
test() {
14+
fooFunction(bar());
15+
// ^^^
16+
// [analyzer] COMPILE_TIME_ERROR.USE_OF_VOID_RESULT
17+
// [cfe] This expression has type 'void' and can't be used.
18+
fooDynamic(bar());
19+
// ^^^
20+
// [analyzer] COMPILE_TIME_ERROR.USE_OF_VOID_RESULT
21+
// [cfe] This expression has type 'void' and can't be used.
22+
fooRegular(bar());
23+
// ^^^
24+
// [analyzer] COMPILE_TIME_ERROR.USE_OF_VOID_RESULT
25+
// [cfe] This expression has type 'void' and can't be used.
26+
fooNever(bar());
27+
// ^^^
28+
// [analyzer] COMPILE_TIME_ERROR.USE_OF_VOID_RESULT
29+
// [cfe] This expression has type 'void' and can't be used.
30+
}
31+
}
32+
33+
void main() {}

0 commit comments

Comments
 (0)