Skip to content

Commit 8e85492

Browse files
stereotype441Commit Queue
authored andcommitted
[analyzer] Re-work handling of null shorting using shared code.
In https://dart-review.googlesource.com/c/sdk/+/399480, a mechanism was introduced to `_fe_analyzer_shared` to support null-shorting. Sometime later, in https://dart-review.googlesource.com/c/sdk/+/427341, the CFE was changed to use this shared mechanism. This CL completes the arc of work by changing the analyzer to use the new shared mechanism. The public API class `NullShortableExpression`, which was part of the analyzer's old implementation of null shorting, is no longer used. It should never have been exposed through the analyzer public API in the first place, so it's been deprecated; I will update the pending changes for analyzer 9.0.0 to delete it. Change-Id: Ic711df6c537c454aa8a99861135e63c8dd277485 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/400021 Reviewed-by: Konstantin Shcheglov <[email protected]> Commit-Queue: Paul Berry <[email protected]> Reviewed-by: Brian Wilkerson <[email protected]>
1 parent e6f188b commit 8e85492

File tree

13 files changed

+411
-84
lines changed

13 files changed

+411
-84
lines changed

pkg/_fe_analyzer_shared/lib/src/type_inference/shared_inference_log.dart

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,13 @@ abstract interface class SharedInferenceLogWriter {
257257
required String methodName,
258258
});
259259

260+
/// Called when null shorting terminates, and so the type of an expression is
261+
/// made nullable.
262+
///
263+
/// [expression] is the expression whose type is changed, and [type] is the
264+
/// type it is changed to.
265+
void recordNullShortedType(Object expression, SharedType type);
266+
260267
/// Records the preliminary types chosen during either a downwards or a
261268
/// horizontal inference step.
262269
void recordPreliminaryTypes(List<SharedType> types);
@@ -788,6 +795,17 @@ abstract class SharedInferenceLogWriterImpl
788795
addEvent(new Event(message: 'LOOKUP $query FINDS $type'));
789796
}
790797

798+
@override
799+
void recordNullShortedType(Object expression, SharedType type) {
800+
addEvent(
801+
new Event(
802+
message:
803+
'STATIC TYPE OF ${describe(expression)} REFINED BY NULL SHORTING '
804+
'TO $type',
805+
),
806+
);
807+
}
808+
791809
@override
792810
void recordPreliminaryTypes(List<SharedType> types) {
793811
checkCall(

pkg/analyzer/CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
* Deprecate `InterfaceFragment.supertype`, use `InterfaceElement.supertype` instead.
1515
* Deprecate `ExtensionTypeFragment.primaryConstructor`, use `ExtensionTypeElement.primaryConstructor`.
1616
* Deprecate `ExtensionTypeFragment.representation`, use `ExtensionTypeElement.representation`.
17+
* Deprecate `NullShortableExpression`. This interface should not be needed by
18+
analyzer clients, and is no longer supported.
1719

1820
## 8.1.1
1921
* Fix for `EnumSet` usage when compiled to JavaScript.

pkg/analyzer/api.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1483,8 +1483,8 @@ package:analyzer/dart/ast/ast.dart:
14831483
pattern (getter: DartPattern)
14841484
NullLiteral (class extends Object implements Literal):
14851485
literal (getter: Token)
1486-
NullShortableExpression (class extends Object implements Expression):
1487-
nullShortingTermination (getter: Expression)
1486+
NullShortableExpression (class extends Object implements Expression, deprecated):
1487+
nullShortingTermination (getter: Expression, deprecated)
14881488
ObjectPattern (class extends Object implements DartPattern):
14891489
fields (getter: NodeList<PatternField>)
14901490
leftParenthesis (getter: Token)

pkg/analyzer/lib/dart/ast/ast.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,7 @@ export 'package:analyzer/src/dart/ast/ast.dart'
183183
NullAwareElement,
184184
NullCheckPattern,
185185
NullLiteral,
186+
// ignore: deprecated_member_use_from_same_package
186187
NullShortableExpression,
187188
ObjectPattern,
188189
ParenthesizedExpression,

pkg/analyzer/lib/src/dart/ast/ast.dart

Lines changed: 42 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1119,6 +1119,7 @@ final class AssignedVariablePatternImpl extends VariablePatternImpl
11191119
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
11201120
abstract final class AssignmentExpression
11211121
implements
1122+
// ignore: deprecated_member_use_from_same_package
11221123
NullShortableExpression,
11231124
MethodReferenceExpression,
11241125
CompoundAssignmentExpression {
@@ -2159,7 +2160,10 @@ final class BreakStatementImpl extends StatementImpl implements BreakStatement {
21592160
/// | identifier
21602161
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
21612162
abstract final class CascadeExpression
2162-
implements Expression, NullShortableExpression {
2163+
implements
2164+
Expression,
2165+
// ignore: deprecated_member_use_from_same_package
2166+
NullShortableExpression {
21632167
/// The cascade sections sharing the common target.
21642168
NodeList<Expression> get cascadeSections;
21652169

@@ -7977,6 +7981,15 @@ sealed class ExpressionImpl extends CollectionElementImpl
79777981
}
79787982
}
79797983

7984+
/// Called when null shorting terminates, and so the type of an expression
7985+
/// needs to be made nullable.
7986+
///
7987+
/// [type] is the new static type of the expression.
7988+
void recordNullShortedType(TypeImpl type) {
7989+
_staticType = type;
7990+
inferenceLogWriter?.recordNullShortedType(this, type);
7991+
}
7992+
79807993
/// Record that the static type of the given node is the given type.
79817994
///
79827995
/// @param expression the node whose type is to be recorded
@@ -11198,7 +11211,10 @@ final class FunctionExpressionImpl extends ExpressionImpl
1119811211
/// [Expression] [TypeArgumentList]? [ArgumentList]
1119911212
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
1120011213
abstract final class FunctionExpressionInvocation
11201-
implements NullShortableExpression, InvocationExpression {
11214+
implements
11215+
// ignore: deprecated_member_use_from_same_package
11216+
NullShortableExpression,
11217+
InvocationExpression {
1120211218
/// The element associated with the function being invoked based on static
1120311219
/// type information.
1120411220
///
@@ -13365,7 +13381,10 @@ final class ImportPrefixReferenceImpl extends AstNodeImpl
1336513381
/// [Expression] '[' [Expression] ']'
1336613382
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
1336713383
abstract final class IndexExpression
13368-
implements NullShortableExpression, MethodReferenceExpression {
13384+
implements
13385+
// ignore: deprecated_member_use_from_same_package
13386+
NullShortableExpression,
13387+
MethodReferenceExpression {
1336913388
/// The expression used to compute the index.
1337013389
Expression get index;
1337113390

@@ -16097,7 +16116,10 @@ final class MethodDeclarationImpl extends ClassMemberImpl
1609716116
/// [ArgumentList]
1609816117
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
1609916118
abstract final class MethodInvocation
16100-
implements NullShortableExpression, InvocationExpression {
16119+
implements
16120+
// ignore: deprecated_member_use_from_same_package
16121+
NullShortableExpression,
16122+
InvocationExpression {
1610116123
/// Whether this expression is cascaded.
1610216124
///
1610316125
/// If it is, then the target of this expression isn't stored locally but is
@@ -17866,7 +17888,12 @@ final class NullLiteralImpl extends LiteralImpl implements NullLiteral {
1786617888
}
1786717889

1786817890
/// Abstract interface for expressions that may participate in null-shorting.
17891+
///
17892+
/// This is an analyzer-internal interface that was exposed through the public
17893+
/// API by mistake. It is deprecated and will be removed in analyzer version
17894+
/// 9.0.0.
1786917895
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
17896+
@Deprecated('No longer supported.')
1787017897
abstract final class NullShortableExpression implements Expression {
1787117898
/// The expression that terminates any null shorting that might occur in this
1787217899
/// expression.
@@ -17883,10 +17910,14 @@ abstract final class NullShortableExpression implements Expression {
1788317910
/// Calling [nullShortingTermination] on any of these subexpressions yields
1788417911
/// the expression `a?.b[c] = d`, indicating that the null-shorting induced by
1788517912
/// the `?.` causes the rest of the subexpression `a?.b[c] = d` to be skipped.
17913+
@Deprecated('No longer supported.')
1788617914
Expression get nullShortingTermination;
1788717915
}
1788817916

17889-
base mixin NullShortableExpressionImpl implements NullShortableExpression {
17917+
base mixin NullShortableExpressionImpl
17918+
implements
17919+
// ignore: deprecated_member_use_from_same_package
17920+
NullShortableExpression {
1789017921
@override
1789117922
Expression get nullShortingTermination {
1789217923
var result = this;
@@ -19121,6 +19152,7 @@ final class PatternVariableDeclarationStatementImpl extends StatementImpl
1912119152
abstract final class PostfixExpression
1912219153
implements
1912319154
Expression,
19155+
// ignore: deprecated_member_use_from_same_package
1912419156
NullShortableExpression,
1912519157
MethodReferenceExpression,
1912619158
CompoundAssignmentExpression {
@@ -19398,6 +19430,7 @@ final class PrefixedIdentifierImpl extends IdentifierImpl
1939819430
abstract final class PrefixExpression
1939919431
implements
1940019432
Expression,
19433+
// ignore: deprecated_member_use_from_same_package
1940119434
NullShortableExpression,
1940219435
MethodReferenceExpression,
1940319436
CompoundAssignmentExpression {
@@ -19531,7 +19564,10 @@ final class PrefixExpressionImpl extends ExpressionImpl
1953119564
/// [Expression] '.' [SimpleIdentifier]
1953219565
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
1953319566
abstract final class PropertyAccess
19534-
implements NullShortableExpression, CommentReferableExpression {
19567+
implements
19568+
// ignore: deprecated_member_use_from_same_package
19569+
NullShortableExpression,
19570+
CommentReferableExpression {
1953519571
/// Whether this expression is cascaded.
1953619572
///
1953719573
/// If it is, then the target of this expression isn't stored locally but is

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

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -117,8 +117,6 @@ class AssignmentExpressionResolver {
117117
flow.ifNullExpression_end();
118118
}
119119
}
120-
121-
_resolver.nullShortingTermination(node);
122120
}
123121

124122
void _checkForInvalidAssignment(

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

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -204,8 +204,6 @@ class PostfixExpressionResolver {
204204
}
205205
node.recordStaticType(receiverType, resolver: _resolver);
206206
}
207-
208-
_resolver.nullShortingTermination(node);
209207
}
210208

211209
void _resolveNullCheck(
@@ -227,6 +225,7 @@ class PostfixExpressionResolver {
227225
_resolver.analyzeExpression(
228226
operand,
229227
SharedTypeSchemaView(_typeSystem.makeNullable(contextType)),
228+
continueNullShorting: true,
230229
);
231230
operand = _resolver.popRewrite()!;
232231

@@ -236,6 +235,5 @@ class PostfixExpressionResolver {
236235
node.recordStaticType(type, resolver: _resolver);
237236

238237
_resolver.flowAnalysis.flow?.nonNullAssert_end(operand);
239-
_resolver.nullShortingTermination(node);
240238
}
241239
}

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

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -249,7 +249,6 @@ class PrefixExpressionResolver {
249249
}
250250
node.recordStaticType(staticType, resolver: _resolver);
251251
}
252-
_resolver.nullShortingTermination(node);
253252
}
254253

255254
void _resolveNegation(PrefixExpressionImpl node) {

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

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
// BSD-style license that can be found in the LICENSE file.
44

55
import 'package:_fe_analyzer_shared/src/type_inference/shared_inference_log.dart';
6+
import 'package:_fe_analyzer_shared/src/types/shared_type.dart';
67
import 'package:analyzer/dart/ast/ast.dart';
78
import 'package:analyzer/src/dart/ast/ast.dart';
89
import 'package:analyzer/src/dart/element/type.dart';
@@ -223,6 +224,27 @@ final class _InferenceLogWriterImpl extends SharedInferenceLogWriterImpl
223224
_inBodyOrInitializer = false;
224225
}
225226

227+
@override
228+
void recordExpressionRewrite({
229+
Object? oldExpression,
230+
required Object newExpression,
231+
}) {
232+
if (oldExpression != null) {
233+
assertExpressionWasRecorded(oldExpression);
234+
}
235+
_recordedExpressions[newExpression] = true;
236+
super.recordExpressionRewrite(
237+
oldExpression: oldExpression,
238+
newExpression: newExpression,
239+
);
240+
}
241+
242+
@override
243+
void recordNullShortedType(Object expression, SharedType type) {
244+
assertExpressionWasRecorded(expression);
245+
super.recordNullShortedType(expression, type);
246+
}
247+
226248
@override
227249
void setExpressionVisitCodePath(
228250
Expression node,

0 commit comments

Comments
 (0)