@@ -2566,8 +2566,12 @@ class _EqualityOpContext<Variable, Type> extends _BranchContext {
25662566 /// The type of the expression on the LHS of `==` or `!=` .
25672567 final Type _leftOperandType;
25682568
2569- _EqualityOpContext (
2570- ExpressionInfo <Variable , Type > conditionInfo, this ._leftOperandType)
2569+ /// If the LHS of `==` or `!=` is a variable reference, the variable.
2570+ /// Otherwise `null` .
2571+ final Variable _leftOperandVariable;
2572+
2573+ _EqualityOpContext (ExpressionInfo <Variable , Type > conditionInfo,
2574+ this ._leftOperandType, this ._leftOperandVariable)
25712575 : super (conditionInfo);
25722576
25732577 @override
@@ -2602,6 +2606,14 @@ class _FlowAnalysisImpl<Node, Statement extends Node, Expression, Variable,
26022606 /// corresponding to it. Otherwise `null` .
26032607 ExpressionInfo <Variable , Type > _expressionInfo;
26042608
2609+ /// The most recently visited expression which was a variable reference, or
2610+ /// `null` if no expression has been visited that was a variable reference.
2611+ Expression _expressionWithVariable;
2612+
2613+ /// If [_expressionVariable] is not `null` , the variable corresponding to it.
2614+ /// Otherwise `null` .
2615+ Variable _expressionVariable;
2616+
26052617 int _functionNestingLevel = 0 ;
26062618
26072619 final AssignedVariables <Node , Variable > _assignedVariables;
@@ -2615,14 +2627,8 @@ class _FlowAnalysisImpl<Node, Statement extends Node, Expression, Variable,
26152627
26162628 @override
26172629 void asExpression_end (Expression subExpression, Type type) {
2618- ExpressionInfo <Variable , Type > subExpressionInfo =
2619- _getExpressionInfo (subExpression);
2620- Variable variable;
2621- if (subExpressionInfo is _VariableReadInfo <Variable , Type >) {
2622- variable = subExpressionInfo._variable;
2623- } else {
2624- return ;
2625- }
2630+ Variable variable = _getExpressionVariable (subExpression);
2631+ if (variable == null ) return ;
26262632 _current = _current.tryPromoteForTypeCast (typeOperations, variable, type);
26272633 }
26282634
@@ -2730,8 +2736,10 @@ class _FlowAnalysisImpl<Node, Statement extends Node, Expression, Variable,
27302736 _EqualityOpContext <Variable , Type > context =
27312737 _stack.removeLast () as _EqualityOpContext <Variable , Type >;
27322738 ExpressionInfo <Variable , Type > lhsInfo = context._conditionInfo;
2739+ Variable lhsVariable = context._leftOperandVariable;
27332740 Type leftOperandType = context._leftOperandType;
27342741 ExpressionInfo <Variable , Type > rhsInfo = _getExpressionInfo (rightOperand);
2742+ Variable rhsVariable = _getExpressionVariable (rightOperand);
27352743 TypeClassification leftOperandTypeClassification =
27362744 typeOperations.classifyType (leftOperandType);
27372745 TypeClassification rightOperandTypeClassification =
@@ -2749,18 +2757,16 @@ class _FlowAnalysisImpl<Node, Statement extends Node, Expression, Variable,
27492757 // but weak mode it might produce an "equal" result. We don't want flow
27502758 // analysis behavior to depend on mode, so we conservatively assume that
27512759 // either result is possible.
2752- } else if (lhsInfo is _NullInfo <Variable , Type > &&
2753- rhsInfo is _VariableReadInfo <Variable , Type >) {
2760+ } else if (lhsInfo is _NullInfo <Variable , Type > && rhsVariable != null ) {
27542761 assert (
27552762 leftOperandTypeClassification == TypeClassification .nullOrEquivalent);
27562763 ExpressionInfo <Variable , Type > equalityInfo =
2757- _current.tryMarkNonNullable (typeOperations, rhsInfo._variable );
2764+ _current.tryMarkNonNullable (typeOperations, rhsVariable );
27582765 _storeExpressionInfo (wholeExpression,
27592766 notEqual ? equalityInfo : ExpressionInfo .invert (equalityInfo));
2760- } else if (rhsInfo is _NullInfo <Variable , Type > &&
2761- lhsInfo is _VariableReadInfo <Variable , Type >) {
2767+ } else if (rhsInfo is _NullInfo <Variable , Type > && lhsVariable != null ) {
27622768 ExpressionInfo <Variable , Type > equalityInfo =
2763- _current.tryMarkNonNullable (typeOperations, lhsInfo._variable );
2769+ _current.tryMarkNonNullable (typeOperations, lhsVariable );
27642770 _storeExpressionInfo (wholeExpression,
27652771 notEqual ? equalityInfo : ExpressionInfo .invert (equalityInfo));
27662772 }
@@ -2769,7 +2775,9 @@ class _FlowAnalysisImpl<Node, Statement extends Node, Expression, Variable,
27692775 @override
27702776 void equalityOp_rightBegin (Expression leftOperand, Type leftOperandType) {
27712777 _stack.add (new _EqualityOpContext <Variable , Type >(
2772- _getExpressionInfo (leftOperand), leftOperandType));
2778+ _getExpressionInfo (leftOperand),
2779+ leftOperandType,
2780+ _getExpressionVariable (leftOperand)));
27732781 }
27742782
27752783 @override
@@ -2844,6 +2852,9 @@ class _FlowAnalysisImpl<Node, Statement extends Node, Expression, Variable,
28442852 if (identical (_expressionWithInfo, oldExpression)) {
28452853 _expressionWithInfo = newExpression;
28462854 }
2855+ if (identical (_expressionWithVariable, oldExpression)) {
2856+ _expressionWithVariable = newExpression;
2857+ }
28472858 }
28482859
28492860 @override
@@ -2901,12 +2912,12 @@ class _FlowAnalysisImpl<Node, Statement extends Node, Expression, Variable,
29012912 @override
29022913 void ifNullExpression_rightBegin (
29032914 Expression leftHandSide, Type leftHandSideType) {
2904- ExpressionInfo < Variable , Type > lhsInfo = _getExpressionInfo (leftHandSide);
2915+ Variable lhsVariable = _getExpressionVariable (leftHandSide);
29052916 FlowModel <Variable , Type > promoted;
29062917 _current = _current.split ();
2907- if (lhsInfo is _VariableReadInfo < Variable , Type > ) {
2918+ if (lhsVariable != null ) {
29082919 ExpressionInfo <Variable , Type > promotionInfo =
2909- _current.tryMarkNonNullable (typeOperations, lhsInfo._variable );
2920+ _current.tryMarkNonNullable (typeOperations, lhsVariable );
29102921 _current = promotionInfo.ifFalse;
29112922 promoted = promotionInfo.ifTrue;
29122923 } else {
@@ -2959,12 +2970,10 @@ class _FlowAnalysisImpl<Node, Statement extends Node, Expression, Variable,
29592970 @override
29602971 void isExpression_end (Expression isExpression, Expression subExpression,
29612972 bool isNot, Type type) {
2962- ExpressionInfo <Variable , Type > subExpressionInfo =
2963- _getExpressionInfo (subExpression);
2964- if (subExpressionInfo is _VariableReadInfo <Variable , Type >) {
2965- ExpressionInfo <Variable , Type > expressionInfo =
2966- _current.tryPromoteForTypeCheck (
2967- typeOperations, subExpressionInfo._variable, type);
2973+ Variable subExpressionVariable = _getExpressionVariable (subExpression);
2974+ if (subExpressionVariable != null ) {
2975+ ExpressionInfo <Variable , Type > expressionInfo = _current
2976+ .tryPromoteForTypeCheck (typeOperations, subExpressionVariable, type);
29682977 _storeExpressionInfo (isExpression,
29692978 isNot ? ExpressionInfo .invert (expressionInfo) : expressionInfo);
29702979 }
@@ -3054,11 +3063,10 @@ class _FlowAnalysisImpl<Node, Statement extends Node, Expression, Variable,
30543063
30553064 @override
30563065 void nonNullAssert_end (Expression operand) {
3057- ExpressionInfo <Variable , Type > operandInfo = _getExpressionInfo (operand);
3058- if (operandInfo is _VariableReadInfo <Variable , Type >) {
3059- _current = _current
3060- .tryMarkNonNullable (typeOperations, operandInfo._variable)
3061- .ifTrue;
3066+ Variable operandVariable = _getExpressionVariable (operand);
3067+ if (operandVariable != null ) {
3068+ _current =
3069+ _current.tryMarkNonNullable (typeOperations, operandVariable).ifTrue;
30623070 }
30633071 }
30643072
@@ -3075,11 +3083,10 @@ class _FlowAnalysisImpl<Node, Statement extends Node, Expression, Variable,
30753083 _current = _current.split ();
30763084 _stack.add (new _NullAwareAccessContext <Variable , Type >(_current));
30773085 if (target != null ) {
3078- ExpressionInfo <Variable , Type > targetInfo = _getExpressionInfo (target);
3079- if (targetInfo is _VariableReadInfo <Variable , Type >) {
3080- _current = _current
3081- .tryMarkNonNullable (typeOperations, targetInfo._variable)
3082- .ifTrue;
3086+ Variable targetVariable = _getExpressionVariable (target);
3087+ if (targetVariable != null ) {
3088+ _current =
3089+ _current.tryMarkNonNullable (typeOperations, targetVariable).ifTrue;
30833090 }
30843091 }
30853092 }
@@ -3226,7 +3233,7 @@ class _FlowAnalysisImpl<Node, Statement extends Node, Expression, Variable,
32263233
32273234 @override
32283235 Type variableRead (Expression expression, Variable variable) {
3229- _storeExpressionInfo (expression, new _VariableReadInfo (_current, variable) );
3236+ _storeExpressionVariable (expression, variable);
32303237 return _current.infoFor (variable).promotedTypes? .last;
32313238 }
32323239
@@ -3273,6 +3280,8 @@ class _FlowAnalysisImpl<Node, Statement extends Node, Expression, Variable,
32733280 print (' current: $_current ' );
32743281 print (' expressionWithInfo: $_expressionWithInfo ' );
32753282 print (' expressionInfo: $_expressionInfo ' );
3283+ print (' expressionWithVariable: $_expressionWithVariable ' );
3284+ print (' expressionVariable: $_expressionVariable ' );
32763285 print (' stack:' );
32773286 for (_FlowContext stackEntry in _stack.reversed) {
32783287 print (' $stackEntry ' );
@@ -3301,6 +3310,19 @@ class _FlowAnalysisImpl<Node, Statement extends Node, Expression, Variable,
33013310 }
33023311 }
33033312
3313+ /// Gets the [Variable] associated with the [expression] (which should be the
3314+ /// last expression that was traversed). If there is no [Variable] associated
3315+ /// with the [expression] , then `null` is returned.
3316+ Variable _getExpressionVariable (Expression expression) {
3317+ if (identical (expression, _expressionWithVariable)) {
3318+ Variable expressionVariable = _expressionVariable;
3319+ _expressionVariable = null ;
3320+ return expressionVariable;
3321+ } else {
3322+ return null ;
3323+ }
3324+ }
3325+
33043326 FlowModel <Variable , Type > _join (
33053327 FlowModel <Variable , Type > first, FlowModel <Variable , Type > second) =>
33063328 FlowModel .join (typeOperations, first, second, _current._emptyVariableMap);
@@ -3319,6 +3341,14 @@ class _FlowAnalysisImpl<Node, Statement extends Node, Expression, Variable,
33193341 _expressionInfo = expressionInfo;
33203342 _current = expressionInfo.after;
33213343 }
3344+
3345+ /// Associates [expression] , which should be the most recently visited
3346+ /// expression, with the given [Variable] object.
3347+ void _storeExpressionVariable (
3348+ Expression expression, Variable expressionVariable) {
3349+ _expressionWithVariable = expression;
3350+ _expressionVariable = expressionVariable;
3351+ }
33223352}
33233353
33243354/// Base class for objects representing constructs in the Dart programming
@@ -3437,28 +3467,6 @@ class _TryContext<Variable, Type> extends _SimpleContext<Variable, Type> {
34373467 'afterBodyAndCatches: $_afterBodyAndCatches )' ;
34383468}
34393469
3440- /// [ExpressionInfo] representing an expression that reads the value of a
3441- /// variable.
3442- class _VariableReadInfo <Variable , Type >
3443- implements ExpressionInfo <Variable , Type > {
3444- @override
3445- final FlowModel <Variable , Type > after;
3446-
3447- /// The variable that is being read.
3448- final Variable _variable;
3449-
3450- _VariableReadInfo (this .after, this ._variable);
3451-
3452- @override
3453- FlowModel <Variable , Type > get ifFalse => after;
3454-
3455- @override
3456- FlowModel <Variable , Type > get ifTrue => after;
3457-
3458- @override
3459- String toString () => '_VariableReadInfo(after: $after , variable: $_variable )' ;
3460- }
3461-
34623470/// [_FlowContext] representing a `while` loop (or a C-style `for` loop, which
34633471/// is functionally similar).
34643472class _WhileContext <Variable , Type >
0 commit comments