Introduce distinct subclasses for _SimpleContext.
Note that due to https://github.com/dart-lang/sdk/issues/43725 we
can't yet downcast to these subclasses in all cases; added a test case
that would fail if we did.
Change-Id: Idd498840484a6a4c60a0cf2f8e01092ba75e7d2e
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/166722
Reviewed-by: Johnni Winther <johnniwinther@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
diff --git a/pkg/_fe_analyzer_shared/lib/src/flow_analysis/flow_analysis.dart b/pkg/_fe_analyzer_shared/lib/src/flow_analysis/flow_analysis.dart
index de9e6cc..03877e4 100644
--- a/pkg/_fe_analyzer_shared/lib/src/flow_analysis/flow_analysis.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/flow_analysis/flow_analysis.dart
@@ -2938,7 +2938,7 @@
_assignedVariables._getInfoForNode(node);
++_functionNestingLevel;
_current = _current.conservativeJoin(const [], info._written);
- _stack.add(new _SimpleContext(_current));
+ _stack.add(new _FunctionExpressionContext(_current));
_current = _current.conservativeJoin(_assignedVariables._anywhere._written,
_assignedVariables._anywhere._captured);
}
@@ -2948,7 +2948,7 @@
--_functionNestingLevel;
assert(_functionNestingLevel >= 0);
_SimpleContext<Variable, Type> context =
- _stack.removeLast() as _SimpleContext<Variable, Type>;
+ _stack.removeLast() as _FunctionExpressionContext<Variable, Type>;
_current = context._previous;
}
@@ -2979,6 +2979,9 @@
@override
void ifNullExpression_end() {
+ // TODO(paulberry): CFE sometimes calls ifNullExpression_end and
+ // nullAwareAccess_end out of order, so as a workaround we cast to the
+ // common base class. See https://github.com/dart-lang/sdk/issues/43725.
_SimpleContext<Variable, Type> context =
_stack.removeLast() as _SimpleContext<Variable, Type>;
_current = _join(_current, context._previous);
@@ -2997,7 +3000,7 @@
} else {
promoted = _current;
}
- _stack.add(new _SimpleContext<Variable, Type>(promoted));
+ _stack.add(new _IfNullExpressionContext<Variable, Type>(promoted));
return true;
}
@@ -3148,6 +3151,9 @@
@override
void nullAwareAccess_end() {
+ // TODO(paulberry): CFE sometimes calls ifNullExpression_end and
+ // nullAwareAccess_end out of order, so as a workaround we cast to the
+ // common base class. See https://github.com/dart-lang/sdk/issues/43725.
_SimpleContext<Variable, Type> context =
_stack.removeLast() as _SimpleContext<Variable, Type>;
_current = _join(_current, context._previous);
@@ -3156,7 +3162,7 @@
@override
bool nullAwareAccess_rightBegin(Expression target, Type targetType) {
assert(targetType != null);
- _stack.add(new _SimpleContext<Variable, Type>(_current));
+ _stack.add(new _NullAwareAccessContext<Variable, Type>(_current));
if (target != null) {
ExpressionInfo<Variable, Type> targetInfo = _getExpressionInfo(target);
if (targetInfo is _VariableReadInfo<Variable, Type>) {
@@ -3406,6 +3412,16 @@
/// language for which flow analysis information needs to be tracked.
abstract class _FlowContext {}
+/// [_FlowContext] representing a function expression.
+class _FunctionExpressionContext<Variable, Type>
+ extends _SimpleContext<Variable, Type> {
+ _FunctionExpressionContext(FlowModel<Variable, Type> previous)
+ : super(previous);
+
+ @override
+ String toString() => '_FunctionExpressionContext(previous: $_previous)';
+}
+
/// [_FlowContext] representing an `if` statement.
class _IfContext<Variable, Type> extends _BranchContext<Variable, Type> {
/// Flow model associated with the state of program execution after the `if`
@@ -3420,6 +3436,25 @@
'_IfContext(conditionInfo: $_conditionInfo, afterThen: $_afterThen)';
}
+/// [_FlowContext] representing an "if-null" (`??`) expression.
+class _IfNullExpressionContext<Variable, Type>
+ extends _SimpleContext<Variable, Type> {
+ _IfNullExpressionContext(FlowModel<Variable, Type> previous)
+ : super(previous);
+
+ @override
+ String toString() => '_IfNullExpressionContext(previous: $_previous)';
+}
+
+/// [_FlowContext] representing a null aware access (`?.`).
+class _NullAwareAccessContext<Variable, Type>
+ extends _SimpleContext<Variable, Type> {
+ _NullAwareAccessContext(FlowModel<Variable, Type> previous) : super(previous);
+
+ @override
+ String toString() => '_NullAwareAccessContext(previous: $_previous)';
+}
+
/// [ExpressionInfo] representing a `null` literal.
class _NullInfo<Variable, Type> implements ExpressionInfo<Variable, Type> {
@override
@@ -3437,7 +3472,7 @@
/// [_FlowContext] representing a language construct for which flow analysis
/// must store a flow model state to be retrieved later, such as a `try`
/// statement, function expression, or "if-null" (`??`) expression.
-class _SimpleContext<Variable, Type> extends _FlowContext {
+abstract class _SimpleContext<Variable, Type> extends _FlowContext {
/// The stored state. For a `try` statement, this is the state from the
/// beginning of the `try` block. For a function expression, this is the
/// state at the point the function expression was created. For an "if-null"
@@ -3446,9 +3481,6 @@
final FlowModel<Variable, Type> _previous;
_SimpleContext(this._previous);
-
- @override
- String toString() => '_SimpleContext(previous: $_previous)';
}
/// [_FlowContext] representing a language construct that can be targeted by
diff --git a/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/mixed_if_null_and_null_aware.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/mixed_if_null_and_null_aware.dart
new file mode 100644
index 0000000..31091b0
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/mixed_if_null_and_null_aware.dart
@@ -0,0 +1,8 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// This test verifies that we don't crash when trying to analyze an expression
+// that combines if-null with null-aware access.
+
+f(int? i, List? l) => i ?? l?.length;
diff --git a/pkg/front_end/test/spell_checking_list_common.txt b/pkg/front_end/test/spell_checking_list_common.txt
index 47cfd38..62f6492 100644
--- a/pkg/front_end/test/spell_checking_list_common.txt
+++ b/pkg/front_end/test/spell_checking_list_common.txt
@@ -273,6 +273,7 @@
behaved
behaves
behavior
+behavioral
behaviors
behind
being
@@ -844,6 +845,7 @@
diet
differ
difference
+differences
different
differently
dig