Skip to content

Commit b5e1ef4

Browse files
johnniwintherCommit Queue
authored andcommitted
[model] Update handling of ?.length in constants
This adds reporting of an error in CFE for ?.length in constant expressions and improves the message for the analyzer in the same case. The error in the analyzer was previously the invalid claim that The property 'length' can't be accessed on the type 'Null' in a constant expression. Closes #60509 Change-Id: Ibbe0fa1ace3bea9d83efea2ccf3ea9716a125d74 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/421841 Reviewed-by: Konstantin Shcheglov <[email protected]> Commit-Queue: Johnni Winther <[email protected]> Reviewed-by: Brian Wilkerson <[email protected]>
1 parent 1504dc6 commit b5e1ef4

25 files changed

+214
-0
lines changed

pkg/_fe_analyzer_shared/lib/src/messages/codes_generated.dart

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2112,6 +2112,17 @@ const MessageCode messageConstEvalNotMapInSpread = const MessageCode(
21122112
problemMessage: r"""Only maps can be used in spreads in constant maps.""",
21132113
);
21142114

2115+
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
2116+
const Code<Null> codeConstEvalNullAwareAccess = messageConstEvalNullAwareAccess;
2117+
2118+
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
2119+
const MessageCode messageConstEvalNullAwareAccess = const MessageCode(
2120+
"ConstEvalNullAwareAccess",
2121+
analyzerCodes: <String>["CONST_EVAL_NULL_AWARE_ACCESS"],
2122+
problemMessage:
2123+
r"""Null-aware property access can't be used in a constant expression.""",
2124+
);
2125+
21152126
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
21162127
const Code<Null> codeConstEvalNullValue = messageConstEvalNullValue;
21172128

pkg/analysis_server/lib/src/services/correction/error_fix_status.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -426,6 +426,8 @@ CompileTimeErrorCode.CONST_EVAL_FOR_ELEMENT:
426426
status: needsEvaluation
427427
CompileTimeErrorCode.CONST_EVAL_METHOD_INVOCATION:
428428
status: needsEvaluation
429+
CompileTimeErrorCode.CONST_EVAL_NULL_AWARE_ACCESS:
430+
status: needsEvaluation
429431
CompileTimeErrorCode.CONST_EVAL_PRIMITIVE_EQUALITY:
430432
status: needsEvaluation
431433
CompileTimeErrorCode.CONST_EVAL_PROPERTY_ACCESS:

pkg/analyzer/lib/src/dart/constant/constant_verifier.dart

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -705,6 +705,10 @@ class ConstantVerifier extends RecursiveAstVisitor<void> {
705705
diagnosticCode,
706706
CompileTimeErrorCode.CONST_EVAL_METHOD_INVOCATION,
707707
) ||
708+
identical(
709+
diagnosticCode,
710+
CompileTimeErrorCode.CONST_EVAL_NULL_AWARE_ACCESS,
711+
) ||
708712
identical(
709713
diagnosticCode,
710714
CompileTimeErrorCode.CONST_EVAL_PRIMITIVE_EQUALITY,

pkg/analyzer/lib/src/dart/constant/evaluation.dart

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1289,6 +1289,13 @@ class ConstantVisitor extends UnifyingAstVisitor<Constant> {
12891289
return prefixResult;
12901290
}
12911291

1292+
if (node.isNullAware) {
1293+
return InvalidConstant.forEntity(
1294+
entity: node,
1295+
diagnosticCode: CompileTimeErrorCode.CONST_EVAL_NULL_AWARE_ACCESS,
1296+
);
1297+
}
1298+
12921299
var propertyAccessResult = _evaluatePropertyAccess(
12931300
prefixResult,
12941301
node.propertyName,

pkg/analyzer/lib/src/error/codes.g.dart

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1025,6 +1025,12 @@ class CompileTimeErrorCode extends ErrorCode {
10251025
"Methods can't be invoked in constant expressions.",
10261026
);
10271027

1028+
static const CompileTimeErrorCode CONST_EVAL_NULL_AWARE_ACCESS =
1029+
CompileTimeErrorCode(
1030+
'CONST_EVAL_NULL_AWARE_ACCESS',
1031+
"Null-aware property access can't be used in a constant expression.",
1032+
);
1033+
10281034
/// See https://spec.dart.dev/DartLangSpecDraft.pdf#constants, "Constants",
10291035
/// for text about "An expression of the form e1 == e2".
10301036
static const CompileTimeErrorCode CONST_EVAL_PRIMITIVE_EQUALITY =

pkg/analyzer/lib/src/error/error_code_values.g.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,7 @@ const List<ErrorCode> errorCodeValues = [
136136
CompileTimeErrorCode.CONST_EVAL_EXTENSION_TYPE_METHOD,
137137
CompileTimeErrorCode.CONST_EVAL_FOR_ELEMENT,
138138
CompileTimeErrorCode.CONST_EVAL_METHOD_INVOCATION,
139+
CompileTimeErrorCode.CONST_EVAL_NULL_AWARE_ACCESS,
139140
CompileTimeErrorCode.CONST_EVAL_PRIMITIVE_EQUALITY,
140141
CompileTimeErrorCode.CONST_EVAL_PROPERTY_ACCESS,
141142
CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION,

pkg/analyzer/lib/src/lint/constants.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ class _ConstantAnalysisErrorListener extends AnalysisErrorListener {
4949
case CompileTimeErrorCode.CONST_EVAL_EXTENSION_METHOD:
5050
case CompileTimeErrorCode.CONST_EVAL_EXTENSION_TYPE_METHOD:
5151
case CompileTimeErrorCode.CONST_EVAL_METHOD_INVOCATION:
52+
case CompileTimeErrorCode.CONST_EVAL_NULL_AWARE_ACCESS:
5253
case CompileTimeErrorCode.CONST_EVAL_PROPERTY_ACCESS:
5354
case CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL:
5455
case CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL_INT:

pkg/analyzer/messages.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2824,6 +2824,9 @@ CompileTimeErrorCode:
28242824
problemMessage: "Constant expressions don't support 'for' elements."
28252825
correctionMessage: "Try replacing the 'for' element with a spread, or removing 'const'."
28262826
hasPublishedDocs: false
2827+
CONST_EVAL_NULL_AWARE_ACCESS:
2828+
problemMessage: "Null-aware property access can't be used in a constant expression."
2829+
hasPublishedDocs: false
28272830
CONST_EVAL_PROPERTY_ACCESS:
28282831
problemMessage: "The property '{0}' can't be accessed on the type '{1}' in a constant expression."
28292832
hasPublishedDocs: false

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

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,4 +90,13 @@ const x = const C().t;
9090
[error(CompileTimeErrorCode.CONST_EVAL_PROPERTY_ACCESS, 59, 11)],
9191
);
9292
}
93+
94+
test_null_aware_property_access() async {
95+
await assertErrorsInCode(
96+
r'''
97+
const String? s = null;
98+
const int? c = s?.length;''',
99+
[error(CompileTimeErrorCode.CONST_EVAL_NULL_AWARE_ACCESS, 39, 9)],
100+
);
101+
}
93102
}

pkg/front_end/lib/src/kernel/body_builder.dart

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2872,6 +2872,10 @@ class BodyBuilder extends StackListenerImpl
28722872
]));
28732873
Object? send = pop();
28742874
if (send is Selector) {
2875+
if (send is PropertySelector && constantContext != ConstantContext.none) {
2876+
addProblem(
2877+
cfe.messageConstEvalNullAwareAccess, token.charOffset, noLength);
2878+
}
28752879
push(send.withReceiver(pop(), token.charOffset, isNullAware: true));
28762880
} else {
28772881
pop();

0 commit comments

Comments
 (0)