Skip to content

Commit 20acfbc

Browse files
stereotype441commit-bot@chromium.org
authored andcommitted
Move checkIndexExpressionIndex checking to resolver.
In order to implement "why not promoted" functionality index expressions, we need to call checkIndexExpressionIndex from the resolver, so that we can pass it failed promotion information. So move it into the ErrorDetectionHelpers mixin. Bug: #44898 Change-Id: Idc70e3421142da1d3100c288c912b6483a91b28c Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/193087 Reviewed-by: Konstantin Shcheglov <[email protected]>
1 parent 4bd2787 commit 20acfbc

File tree

5 files changed

+92
-75
lines changed

5 files changed

+92
-75
lines changed

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

Lines changed: 47 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -55,32 +55,14 @@ mixin ErrorDetectionHelpers {
5555
void checkForArgumentTypeNotAssignableForArgument(Expression argument,
5656
{bool promoteParameterToNullable = false,
5757
Map<DartType, NonPromotionReason> Function()? whyNotPromoted}) {
58-
checkForArgumentTypeNotAssignableForArgument2(
58+
_checkForArgumentTypeNotAssignableForArgument2(
5959
argument: argument,
6060
parameter: argument.staticParameterElement,
6161
promoteParameterToNullable: promoteParameterToNullable,
6262
whyNotPromoted: whyNotPromoted,
6363
);
6464
}
6565

66-
void checkForArgumentTypeNotAssignableForArgument2({
67-
required Expression argument,
68-
required ParameterElement? parameter,
69-
required bool promoteParameterToNullable,
70-
Map<DartType, NonPromotionReason> Function()? whyNotPromoted,
71-
}) {
72-
var staticParameterType = parameter?.type;
73-
if (promoteParameterToNullable && staticParameterType != null) {
74-
staticParameterType =
75-
typeSystem.makeNullable(staticParameterType as TypeImpl);
76-
}
77-
_checkForArgumentTypeNotAssignableWithExpectedTypes(
78-
argument,
79-
staticParameterType,
80-
CompileTimeErrorCode.ARGUMENT_TYPE_NOT_ASSIGNABLE,
81-
whyNotPromoted);
82-
}
83-
8466
/// Verify that the given constructor field [initializer] has compatible field
8567
/// and initializer expression types. The [fieldElement] is the static element
8668
/// from the name in the [ConstructorFieldInitializer].
@@ -205,6 +187,34 @@ mixin ErrorDetectionHelpers {
205187
return true;
206188
}
207189

190+
void checkIndexExpressionIndex(
191+
Expression index, {
192+
required ExecutableElement? readElement,
193+
required ExecutableElement? writeElement,
194+
}) {
195+
if (readElement is MethodElement) {
196+
var parameters = readElement.parameters;
197+
if (parameters.isNotEmpty) {
198+
_checkForArgumentTypeNotAssignableForArgument2(
199+
argument: index,
200+
parameter: parameters[0],
201+
promoteParameterToNullable: false,
202+
);
203+
}
204+
}
205+
206+
if (writeElement is MethodElement) {
207+
var parameters = writeElement.parameters;
208+
if (parameters.isNotEmpty) {
209+
_checkForArgumentTypeNotAssignableForArgument2(
210+
argument: index,
211+
parameter: parameters[0],
212+
promoteParameterToNullable: false,
213+
);
214+
}
215+
}
216+
}
217+
208218
/// Computes the appropriate set of context messages to report along with an
209219
/// error that may have occurred because [expression] was not type promoted.
210220
///
@@ -233,6 +243,24 @@ mixin ErrorDetectionHelpers {
233243
return null;
234244
}
235245

246+
void _checkForArgumentTypeNotAssignableForArgument2({
247+
required Expression argument,
248+
required ParameterElement? parameter,
249+
required bool promoteParameterToNullable,
250+
Map<DartType, NonPromotionReason> Function()? whyNotPromoted,
251+
}) {
252+
var staticParameterType = parameter?.type;
253+
if (promoteParameterToNullable && staticParameterType != null) {
254+
staticParameterType =
255+
typeSystem.makeNullable(staticParameterType as TypeImpl);
256+
}
257+
_checkForArgumentTypeNotAssignableWithExpectedTypes(
258+
argument,
259+
staticParameterType,
260+
CompileTimeErrorCode.ARGUMENT_TYPE_NOT_ASSIGNABLE,
261+
whyNotPromoted);
262+
}
263+
236264
/// Verify that the given [expression] can be assigned to its corresponding
237265
/// parameters.
238266
///

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

Lines changed: 0 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -349,13 +349,6 @@ class ErrorVerifier extends RecursiveAstVisitor<void>
349349
_checkForDeadNullCoalesce(node.readType as TypeImpl, node.rightHandSide);
350350
}
351351
_checkForAssignmentToFinal(lhs);
352-
if (lhs is IndexExpression) {
353-
_checkIndexExpressionIndex(
354-
lhs.index,
355-
readElement: node.readElement as ExecutableElement?,
356-
writeElement: node.writeElement as ExecutableElement?,
357-
);
358-
}
359352
super.visitAssignmentExpression(node);
360353
}
361354

@@ -830,12 +823,6 @@ class ErrorVerifier extends RecursiveAstVisitor<void>
830823

831824
@override
832825
void visitIndexExpression(IndexExpression node) {
833-
_checkIndexExpressionIndex(
834-
node.index,
835-
readElement: node.staticElement,
836-
writeElement: null,
837-
);
838-
839826
if (node.isNullAware) {
840827
_checkForUnnecessaryNullAware(
841828
node.realTarget,
@@ -1006,13 +993,6 @@ class ErrorVerifier extends RecursiveAstVisitor<void>
1006993
_checkForAssignmentToFinal(operand);
1007994
_checkForIntNotAssignable(operand);
1008995
}
1009-
if (operand is IndexExpression) {
1010-
_checkIndexExpressionIndex(
1011-
operand.index,
1012-
readElement: node.readElement as ExecutableElement?,
1013-
writeElement: node.writeElement as ExecutableElement?,
1014-
);
1015-
}
1016996
super.visitPostfixExpression(node);
1017997
}
1018998

@@ -1038,13 +1018,6 @@ class ErrorVerifier extends RecursiveAstVisitor<void>
10381018
checkForUseOfVoidResult(operand);
10391019
_checkForIntNotAssignable(operand);
10401020
}
1041-
if (operand is IndexExpression) {
1042-
_checkIndexExpressionIndex(
1043-
operand.index,
1044-
readElement: node.readElement as ExecutableElement?,
1045-
writeElement: node.writeElement as ExecutableElement?,
1046-
);
1047-
}
10481021
super.visitPrefixExpression(node);
10491022
}
10501023

@@ -4594,34 +4567,6 @@ class ErrorVerifier extends RecursiveAstVisitor<void>
45944567
}
45954568
}
45964569

4597-
void _checkIndexExpressionIndex(
4598-
Expression index, {
4599-
required ExecutableElement? readElement,
4600-
required ExecutableElement? writeElement,
4601-
}) {
4602-
if (readElement is MethodElement) {
4603-
var parameters = readElement.parameters;
4604-
if (parameters.isNotEmpty) {
4605-
checkForArgumentTypeNotAssignableForArgument2(
4606-
argument: index,
4607-
parameter: parameters[0],
4608-
promoteParameterToNullable: false,
4609-
);
4610-
}
4611-
}
4612-
4613-
if (writeElement is MethodElement) {
4614-
var parameters = writeElement.parameters;
4615-
if (parameters.isNotEmpty) {
4616-
checkForArgumentTypeNotAssignableForArgument2(
4617-
argument: index,
4618-
parameter: parameters[0],
4619-
promoteParameterToNullable: false,
4620-
);
4621-
}
4622-
}
4623-
}
4624-
46254570
void _checkMixinInference(
46264571
NamedCompilationUnitMember node, WithClause? withClause) {
46274572
if (withClause == null) {

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -709,6 +709,11 @@ class ResolverVisitor extends ScopedVisitor with ErrorDetectionHelpers {
709709

710710
InferenceContext.setType(node.index, result.indexContextType);
711711
node.index.accept(this);
712+
checkIndexExpressionIndex(
713+
node.index,
714+
readElement: result.readElement as ExecutableElement?,
715+
writeElement: result.writeElement as ExecutableElement?,
716+
);
712717

713718
return result;
714719
} else if (node is PrefixedIdentifier) {
@@ -1702,6 +1707,11 @@ class ResolverVisitor extends ScopedVisitor with ErrorDetectionHelpers {
17021707

17031708
InferenceContext.setType(node.index, result.indexContextType);
17041709
node.index.accept(this);
1710+
checkIndexExpressionIndex(
1711+
node.index,
1712+
readElement: result.readElement as ExecutableElement?,
1713+
writeElement: null,
1714+
);
17051715

17061716
DartType type;
17071717
if (identical(node.realTarget.staticType, NeverTypeImpl.instance)) {

pkg/analyzer/lib/src/test_utilities/mock_sdk.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -459,7 +459,7 @@ abstract class Map<K, V> {
459459
int get length => 0;
460460
Iterable<V> get values;
461461
462-
V? operator [](K key);
462+
V? operator [](Object? key);
463463
void operator []=(K key, V value);
464464
465465
Map<RK, RV> cast<RK, RV>();

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

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -454,6 +454,40 @@ f(A a) {
454454
]);
455455
}
456456

457+
test_map_indexGet() async {
458+
// Any type may be passed to Map.operator[].
459+
await assertNoErrorsInCode('''
460+
main() {
461+
Map<int, int> m = <int, int>{};
462+
m['x'];
463+
}
464+
''');
465+
}
466+
467+
test_map_indexSet() async {
468+
// The type passed to Map.operator[]= must match the key type.
469+
await assertErrorsInCode('''
470+
main() {
471+
Map<int, int> m = <int, int>{};
472+
m['x'] = 0;
473+
}
474+
''', [
475+
error(CompileTimeErrorCode.ARGUMENT_TYPE_NOT_ASSIGNABLE, 47, 3),
476+
]);
477+
}
478+
479+
test_map_indexSet_ifNull() async {
480+
// The type passed to Map.operator[]= must match the key type.
481+
await assertErrorsInCode('''
482+
main() {
483+
Map<int, int> m = <int, int>{};
484+
m['x'] ??= 0;
485+
}
486+
''', [
487+
error(CompileTimeErrorCode.ARGUMENT_TYPE_NOT_ASSIGNABLE, 47, 3),
488+
]);
489+
}
490+
457491
test_new_generic() async {
458492
await assertErrorsInCode('''
459493
class A<T> {

0 commit comments

Comments
 (0)